You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/09/02 12:17:30 UTC
[incubator-nuttx] branch master updated: arch:xtensa: add xtensa
mpu support
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new fd9ce01 arch:xtensa: add xtensa mpu support
fd9ce01 is described below
commit fd9ce0137e644e10e343479ee6ccb7a51a448a2f
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Wed Sep 1 21:37:15 2021 +0800
arch:xtensa: add xtensa mpu support
Add support for Xtensa Memory Protect Unit.
Change-Id: I27e2f05daae24429ef7513d843b4f217daeefa0d
---
arch/xtensa/src/common/mpu.h | 374 ++++++++++++++++++++++++++++++++++++
arch/xtensa/src/common/xtensa_mpu.c | 138 +++++++++++++
2 files changed, 512 insertions(+)
diff --git a/arch/xtensa/src/common/mpu.h b/arch/xtensa/src/common/mpu.h
new file mode 100644
index 0000000..75d1ae3
--- /dev/null
+++ b/arch/xtensa/src/common/mpu.h
@@ -0,0 +1,374 @@
+/****************************************************************************
+ * arch/xtensa/src/common/mpu.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_COMMON_XTENSA_MPU_H
+#define __ARCH_XTENSA_SRC_COMMON_XTENSA_MPU_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/chip/core-isa.h>
+
+#ifndef __ASSEMBLY__
+# include <sys/types.h>
+# include <stdint.h>
+# include <stdbool.h>
+# include <assert.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MPU_VADDR_MASK ~(XCHAL_MPU_ALIGN - (1))
+
+#define MPU_ENTRY_AS(vaddr, valid) \
+ (((vaddr) & MPU_VADDR_MASK) | \
+ ((valid) & (0x1)))
+
+#define MPU_ENTRY_AR(access, memtype) \
+ (((ENCODE_MEMORY_TYPE(memtype)) << (12)) | \
+ (((access) & (0xf)) << (8)))
+
+/****************************************************************************
+ * MPU access rights constants
+ ****************************************************************************/
+
+#define MPU_AR_NONE (0) /* no access */
+#define MPU_AR_R (4) /* Kernel read, User no access*/
+#define MPU_AR_RX (5) /* Kernel read/execute, User no access */
+#define MPU_AR_RW (6) /* Kernel read/write, User no access */
+#define MPU_AR_RWX (7) /* Kernel read/write/execute, User no access */
+#define MPU_AR_Ww (8) /* Kernel write, User write */
+#define MPU_AR_RWrwx (9) /* Kernel read/write , User read/write/execute */
+#define MPU_AR_RWr (10) /* Kernel read/write, User read */
+#define MPU_AR_RWXrx (11) /* Kernel read/write/execute, User read/execute */
+#define MPU_AR_Rr (12) /* Kernel read, User read */
+#define MPU_AR_RXrx (13) /* Kernel read/execute, User read/execute */
+#define MPU_AR_RWrw (14) /* Kernel read/write, User read/write */
+#define MPU_AR_RWXrwx (15) /* Kernel read/write/execute, User read/write/execute */
+#define MPU_AR_WIDTH 4 /* Bits used to encode access rights */
+
+/****************************************************************************
+ * MPU access memtype constants
+ ****************************************************************************/
+
+#define MPU_MEM_DEVICE (0x00008000)
+#define MPU_MEM_NON_CACHEABLE (0x00090000)
+#define MPU_MEM_WRITETHRU_NOALLOC (0x00080000)
+#define MPU_MEM_WRITETHRU (0x00040000)
+#define MPU_MEM_WRITETHRU_WRITEALLOC (0x00060000)
+#define MPU_MEM_WRITEBACK_NOALLOC (0x00050000)
+#define MPU_MEM_WRITEBACK (0x00070000)
+#define MPU_MEM_INTERRUPTIBLE (0x08000000)
+#define MPU_MEM_BUFFERABLE (0x01000000)
+#define MPU_MEM_NON_SHAREABLE (0x00000000)
+#define MPU_MEM_INNER_SHAREABLE (0x02000000)
+#define MPU_MEM_OUTER_SHAREABLE (0x04000000)
+#define MPU_MEM_SYSTEM_SHAREABLE (0x06000000)
+
+/****************************************************************************
+ * Layout of the MPU memory type specifier for: ENCODE_MEMORY_TYPE()
+ *
+ * Bits 0-3 - reserved for pass through of accessRights
+ * Bits 4-12 - reserved for pass through of memoryType bits
+ * Bit 13 - indicates to use existing access rights of region
+ * Bit 14 - indicates to use existing memory type of region
+ * Bit 15 - indicates device
+ * Bit 16-19- system cache properties
+ * Bit 20-23- local cache properties
+ * Bit 24 - indicates bufferable
+ * Bit 25-26- encodes shareability (1=inner, 2=outer, 3=system)
+ * Bit 27 - indicates interruptible
+ * Bits 28-31- reserved for future use
+ ****************************************************************************/
+
+#define SYSTEM_CACHE_BITS (0x000f0000)
+#define LOCAL_CACHE_BITS (0x00f00000)
+#define SYSTEM_RWC_MASK (0x00070000)
+#define LOCAL_RWC_MASK (0x00700000)
+#define SHIFT_RWC 16
+
+#define MEM_ANY_SHAREABLE(x) (((x & MPU_MEM_SYSTEM_SHAREABLE) \
+ != (0)) ? (1) : (0))
+
+#define MEM_INNER_SHAREABLE(x) (((x & MPU_MEM_SYSTEM_SHAREABLE) \
+ == MPU_MEM_INNER_SHAREABLE) ? (1) : (0))
+
+#define MEM_IS_BUFFERABLE(x) (((x & MPU_MEM_BUFFERABLE) != (0)) ? \
+ (1) : (0))
+
+#define MEM_IS_DEVICE(x) (((x & MPU_MEM_DEVICE) != (0)) ? (1) : (0))
+
+#define NON_CACHEABLE_DOMAIN(x) \
+ ((MEM_IS_DEVICE(x) != (0)) || \
+ (MEM_ANY_SHAREABLE(x) != (0)) ? (0x3) : (0))
+
+#define CACHEABLE_DOMAIN(x) ((MEM_ANY_SHAREABLE(x) != (0)) ? \
+ (0x3) : (0x1))
+
+#define MEM_CACHE_MASK(x) (x & SYSTEM_CACHE_BITS)
+
+#define IS_SYSTEM_NONCACHEABLE(x) \
+ (((MEM_CACHE_MASK(x) & MPU_MEM_NON_CACHEABLE) == \
+ MPU_MEM_NON_CACHEABLE) ? (1) : (0))
+
+#define ENCODE_DEVICE(x) \
+ (((((x & MPU_MEM_INTERRUPTIBLE) != (0)) \
+ ? (1) : (0)) << 3) | \
+ ((NON_CACHEABLE_DOMAIN(x) << 1) | MEM_IS_BUFFERABLE(x)))
+
+#define ENCODE_SYSTEM_NONCACHEABLE(x) \
+ (((x & LOCAL_CACHE_BITS) != (0)) && \
+ (((x & LOCAL_CACHE_BITS) >> 4) != MPU_MEM_NON_CACHEABLE)) ? \
+ ((0x89) | (((x) & LOCAL_CACHE_BITS) >> SHIFT_RWC)) :\
+ ((((0x18) | (NON_CACHEABLE_DOMAIN(x) << 1)) \
+ | MEM_IS_BUFFERABLE(x)))
+
+#define ENCODE_SYSTEM_CACHEABLE(x) \
+ (((((x & LOCAL_CACHE_BITS) >> 4) & MPU_MEM_NON_CACHEABLE) == \
+ MPU_MEM_NON_CACHEABLE) ? \
+ (CACHEABLE_DOMAIN(x) << 4) : \
+ ENCODE_SYSTEM_CACHEABLE_LOCAL_CACHEABLE(x)) | \
+ ((MEM_INNER_SHAREABLE(x) << 3) | \
+ ((MEM_CACHE_MASK(x) & SYSTEM_RWC_MASK) \
+ >> SHIFT_RWC))
+
+#define ENCODE_SYSTEM_CACHEABLE_LOCAL_CACHEABLE(x) \
+ ((CACHEABLE_DOMAIN(x) << 7) | (((((x & LOCAL_CACHE_BITS) != (0)) ? \
+ (x & LOCAL_CACHE_BITS) : \
+ ((MEM_CACHE_MASK(x) << 4)) \
+ & (LOCAL_RWC_MASK)) >> SHIFT_RWC)))
+
+#define ENCODE_MEMORY_TYPE(x) \
+ (((x & (0xffffe000)) != (0)) ? \
+ ((MEM_IS_DEVICE((x)) != (0)) ? ENCODE_DEVICE((x)) : \
+ ((IS_SYSTEM_NONCACHEABLE((x)) != (0)) ? \
+ ENCODE_SYSTEM_NONCACHEABLE((x)) : \
+ ENCODE_SYSTEM_CACHEABLE((x)))) : x)
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: mpu_allocregion
+ *
+ * Description:
+ * Allocate the next region
+ *
+ ****************************************************************************/
+
+unsigned int mpu_allocregion(void);
+
+/****************************************************************************
+ * Name: mpu_control
+ *
+ * Description:
+ * Configure and enable (or disable) the MPU
+ *
+ ****************************************************************************/
+
+void mpu_control(bool enable);
+
+/****************************************************************************
+ * Name: mpu_configure_region
+ *
+ * Description:
+ * Configure a region for privileged, strongly ordered memory
+ *
+ ****************************************************************************/
+
+void mpu_configure_region(uintptr_t base, size_t size,
+ uint8_t acc, uint16_t memtype);
+
+/****************************************************************************
+ * Name: mpu_priv_stronglyordered
+ *
+ * Description:
+ * Configure a region for privileged, strongly ordered memory
+ *
+ ****************************************************************************/
+
+#define mpu_priv_stronglyordered(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RWX, \
+ MPU_MEM_DEVICE); \
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_user_flash
+ *
+ * Description:
+ * Configure a region for user program flash
+ *
+ ****************************************************************************/
+
+#define mpu_user_flash(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RXrx, \
+ MPU_MEM_WRITEBACK);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_priv_flash
+ *
+ * Description:
+ * Configure a region for privileged program flash
+ *
+ ****************************************************************************/
+
+#define mpu_priv_flash(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RX, \
+ MPU_MEM_WRITEBACK);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_user_intsram
+ *
+ * Description:
+ * Configure a region as user internal SRAM
+ *
+ ****************************************************************************/
+
+#define mpu_user_intsram(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RWXrwx, \
+ MPU_MEM_WRITEBACK);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_priv_intsram
+ *
+ * Description:
+ * Configure a region as privileged internal SRAM
+ *
+ ****************************************************************************/
+
+#define mpu_priv_intsram(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size,\
+ MPU_AR_RWX, \
+ MPU_MEM_WRITETHRU);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_user_extsram
+ *
+ * Description:
+ * Configure a region as user external SRAM
+ *
+ ****************************************************************************/
+
+#define mpu_user_extsram(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RWXrwx, \
+ MPU_MEM_WRITETHRU);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_priv_extsram
+ *
+ * Description:
+ * Configure a region as privileged external SRAM
+ *
+ ****************************************************************************/
+
+#define mpu_priv_extsram(base, size) \
+ do \
+ { \
+ /* The configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RWX, \
+ MPU_MEM_WRITETHRU);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_peripheral
+ *
+ * Description:
+ * Configure a region as privileged peripheral address space
+ *
+ ****************************************************************************/
+
+#define mpu_peripheral(base, size) \
+ do \
+ { \
+ /* Then configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RW, \
+ MPU_MEM_DEVICE);\
+ } while (0)
+
+/****************************************************************************
+ * Name: mpu_user_peripheral
+ *
+ * Description:
+ * Configure a region as user peripheral address space
+ *
+ ****************************************************************************/
+
+#define mpu_user_peripheral(base, size) \
+ do \
+ { \
+ /* Then configure the region */ \
+ mpu_configure_region(base, size, \
+ MPU_AR_RWrw, \
+ MPU_MEM_DEVICE);\
+ } while (0)
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_XTENSA_SRC_COMMON_XTENSA_MPU_H */
diff --git a/arch/xtensa/src/common/xtensa_mpu.c b/arch/xtensa/src/common/xtensa_mpu.c
new file mode 100644
index 0000000..39f2c85
--- /dev/null
+++ b/arch/xtensa/src/common/xtensa_mpu.c
@@ -0,0 +1,138 @@
+/****************************************************************************
+ * arch/xtensa/src/common/xtensa_mpu.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "mpu.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Cache for mpu base address in entry */
+
+static uint32_t xtensa_mpu_base[XCHAL_MPU_ENTRIES];
+
+/* The next available region number in decreasing way */
+
+static uint8_t g_region = XCHAL_MPU_ENTRIES;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mpu_allocregion
+ *
+ * Description:
+ * Allocate the next region
+ *
+ * Assumptions:
+ * - Regions are never deallocated
+ * - Regions are only allocated early in initialization, so no special
+ * protection against re-entrancy is required;
+ *
+ ****************************************************************************/
+
+unsigned int mpu_allocregion(void)
+{
+ DEBUGASSERT((unsigned int)g_region >= 0);
+ return (unsigned int)--g_region;
+}
+
+/****************************************************************************
+ * Name: mpu_control
+ *
+ * Description:
+ * Configure and enable (or disable) the MPU
+ *
+ ****************************************************************************/
+
+void mpu_control(bool enable)
+{
+ uint32_t regval = 0;
+
+ if (enable)
+ {
+ uint32_t i;
+ for (i = XCHAL_MPU_ENTRIES - 1; i >= g_region; i--)
+ {
+ regval |= (1 << i);
+ }
+ }
+
+ __asm__ __volatile__ ("wsr %0, mpuenb\n" : : "r"(regval));
+}
+
+/****************************************************************************
+ * Name: mpu_configure_region
+ *
+ * Description:
+ * Configure a region
+ *
+ ****************************************************************************/
+
+void mpu_configure_region(uintptr_t base, size_t size,
+ uint8_t acc, uint16_t memtype)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t at;
+ uint32_t as;
+
+ /* Ensure address not overlay
+ *
+ * Xtensa ISA Reference Manual B4.6.5.3:
+ * The lowest address of each foregound segment
+ * must be no smaller than the lowest address of the
+ * preceding foregroud segment in numerical order.
+ */
+
+ if (region < (XCHAL_MPU_ENTRIES - 1))
+ {
+ DEBUGASSERT(base < xtensa_mpu_base[region + 1]);
+ }
+
+ /* Now only setup MPU entry, enable mpu in mpu_control */
+
+ as = MPU_ENTRY_AS(base, 0);
+ at = MPU_ENTRY_AR(acc, memtype);
+
+ /* Set segment bits */
+
+ at |= region;
+
+ /* update mpu entry .. requires an memw on same cache line */
+
+ __asm__ __volatile__
+ (
+ "\tj 1f\n"
+ "\t.align 16\n"
+ "\t1: memw\n"
+ "\twptlb %0, %1\n"
+ :
+ : "a" (at), "a"(as)
+ );
+
+ xtensa_mpu_base[region] = base;
+}