| /* |
| * Copyright (c) 2023 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdint.h> |
| |
| #include <zephyr/toolchain.h> |
| #include <zephyr/sys/util_macro.h> |
| |
| #include <xtensa/config/core-isa.h> |
| |
| #ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H |
| #define ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H |
| |
| /** |
| * @defgroup xtensa_mpu_apis Xtensa Memory Protection Unit (MPU) APIs |
| * @ingroup xtensa_apis |
| * @{ |
| */ |
| |
| /** Number of available entries in the MPU table. */ |
| #define XTENSA_MPU_NUM_ENTRIES XCHAL_MPU_ENTRIES |
| |
| /** |
| * @name MPU memory region access rights. |
| * |
| * @note These are NOT bit masks, and must be used as whole value. |
| * |
| * @{ |
| */ |
| |
| /** Kernel and user modes no access. */ |
| #define XTENSA_MPU_ACCESS_P_NA_U_NA (0) |
| |
| /** Kernel mode execution only. */ |
| #define XTENSA_MPU_ACCESS_P_X_U_NA (2) |
| |
| /** User mode execution only. */ |
| #define XTENSA_MPU_ACCESS_P_NA_U_X (3) |
| |
| /** Kernel mode read only. */ |
| #define XTENSA_MPU_ACCESS_P_RO_U_NA (4) |
| |
| /** Kernel mode read and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RX_U_NA (5) |
| |
| /** Kernel mode read and write. */ |
| #define XTENSA_MPU_ACCESS_P_RW_U_NA (6) |
| |
| /** Kernel mode read, write and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RWX_U_NA (7) |
| |
| /** Kernel and user modes write only. */ |
| #define XTENSA_MPU_ACCESS_P_WO_U_WO (8) |
| |
| /** Kernel mode read, write. User mode read, write and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RW_U_RWX (9) |
| |
| /** Kernel mode read and write. User mode read only. */ |
| #define XTENSA_MPU_ACCESS_P_RW_U_RO (10) |
| |
| /** Kernel mode read, write and execution. User mode read and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RWX_U_RX (11) |
| |
| /** Kernel and user modes read only. */ |
| #define XTENSA_MPU_ACCESS_P_RO_U_RO (12) |
| |
| /** Kernel and user modes read and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RX_U_RX (13) |
| |
| /** Kernel and user modes read and write. */ |
| #define XTENSA_MPU_ACCESS_P_RW_U_RW (14) |
| |
| /** Kernel and user modes read, write and execution. */ |
| #define XTENSA_MPU_ACCESS_P_RWX_U_RWX (15) |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @brief Foreground MPU Entry. |
| * |
| * This holds the as, at register values for one MPU entry which can be |
| * used directly by WPTLB. |
| */ |
| struct xtensa_mpu_entry { |
| /** |
| * Content of as register for WPTLB. |
| * |
| * This contains the start address, the enable bit, and the lock bit. |
| */ |
| union { |
| /** Raw value. */ |
| uint32_t raw; |
| |
| /** Individual parts. */ |
| struct { |
| /** |
| * Enable bit for this entry. |
| * |
| * Modifying this will also modify the corresponding bit of |
| * the MPUENB register. |
| */ |
| uint32_t enable:1; |
| |
| /** |
| * Lock bit for this entry. |
| * |
| * Usable only if MPULOCKABLE parameter is enabled in |
| * processor configuration. |
| * |
| * Once set: |
| * - This cannot be cleared until reset. |
| * - This entry can no longer be modified. |
| * - The start address of the next entry also |
| * cannot be modified. |
| */ |
| uint32_t lock:1; |
| |
| /** Must be zero. */ |
| uint32_t mbz:3; |
| |
| /** |
| * Start address of this MPU entry. |
| * |
| * Effective bits in this portion are affected by the minimum |
| * segment size of each MPU entry, ranging from 32 bytes to 4GB. |
| */ |
| uint32_t start_addr:27; |
| } p; |
| } as; |
| |
| /** |
| * Content of at register for WPTLB. |
| * |
| * This contains the memory type, access rights, and the segment number. |
| */ |
| union { |
| /** Raw value. */ |
| uint32_t raw; |
| |
| /** Individual parts. */ |
| struct { |
| /** The segment number of this MPU entry. */ |
| uint32_t segment:5; |
| |
| /** Must be zero (part 1). */ |
| uint32_t mbz1:3; |
| |
| /** |
| * Access rights associated with this MPU entry. |
| * |
| * This dictates the access right from the start address of |
| * this entry, to the start address of next entry. |
| * |
| * Refer to XTENSA_MPU_ACCESS_* macros for available rights. |
| */ |
| uint32_t access_rights:4; |
| |
| /** |
| * Memory type associated with this MPU entry. |
| * |
| * This dictates the memory type from the start address of |
| * this entry, to the start address of next entry. |
| * |
| * This affects how the hardware treats the memory, for example, |
| * cacheable vs non-cacheable, shareable vs non-shareable. |
| * Refer to the Xtensa Instruction Set Architecture (ISA) manual |
| * for general description, and the processor manual for processor |
| * specific information. |
| */ |
| uint32_t memory_type:9; |
| |
| /** Must be zero (part 2). */ |
| uint32_t mbz2:11; |
| } p; |
| } at; |
| }; |
| |
| /** |
| * @brief Struct to hold foreground MPU map and its entries. |
| */ |
| struct xtensa_mpu_map { |
| /** |
| * Array of MPU entries. |
| */ |
| struct xtensa_mpu_entry entries[XTENSA_MPU_NUM_ENTRIES]; |
| }; |
| |
| /** |
| * @name Memory domain and partitions |
| * @{ |
| */ |
| |
| typedef uint32_t k_mem_partition_attr_t; |
| |
| static inline bool xtensa_mem_partition_is_executable(k_mem_partition_attr_t access_rights) |
| { |
| bool is_exec; |
| |
| switch (access_rights) { |
| case XTENSA_MPU_ACCESS_P_X_U_NA: |
| case XTENSA_MPU_ACCESS_P_NA_U_X: |
| case XTENSA_MPU_ACCESS_P_RX_U_NA: |
| case XTENSA_MPU_ACCESS_P_RWX_U_NA: |
| case XTENSA_MPU_ACCESS_P_RW_U_RWX: |
| case XTENSA_MPU_ACCESS_P_RWX_U_RX: |
| case XTENSA_MPU_ACCESS_P_RX_U_RX: |
| case XTENSA_MPU_ACCESS_P_RWX_U_RWX: |
| is_exec = true; |
| break; |
| default: |
| is_exec = false; |
| break; |
| }; |
| |
| return is_exec; |
| } |
| |
| static inline bool xtensa_mem_partition_is_writable(k_mem_partition_attr_t access_rights) |
| { |
| bool is_writable; |
| |
| switch (access_rights) { |
| case XTENSA_MPU_ACCESS_P_RW_U_NA: |
| case XTENSA_MPU_ACCESS_P_RWX_U_NA: |
| case XTENSA_MPU_ACCESS_P_WO_U_WO: |
| case XTENSA_MPU_ACCESS_P_RW_U_RWX: |
| case XTENSA_MPU_ACCESS_P_RW_U_RO: |
| case XTENSA_MPU_ACCESS_P_RWX_U_RX: |
| case XTENSA_MPU_ACCESS_P_RW_U_RW: |
| case XTENSA_MPU_ACCESS_P_RWX_U_RWX: |
| is_writable = true; |
| break; |
| default: |
| is_writable = false; |
| break; |
| }; |
| |
| return is_writable; |
| } |
| |
| #define K_MEM_PARTITION_IS_EXECUTABLE(access_rights) \ |
| (xtensa_mem_partition_is_executable(access_rights)) |
| |
| #define K_MEM_PARTITION_IS_WRITABLE(access_rights) \ |
| (xtensa_mem_partition_is_writable(access_rights)) |
| |
| /* Read-Write access permission attributes */ |
| #define K_MEM_PARTITION_P_RW_U_RW \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RW_U_RW}) |
| #define K_MEM_PARTITION_P_RW_U_NA \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RW_U_NA}) |
| #define K_MEM_PARTITION_P_RO_U_RO \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RO_U_RO}) |
| #define K_MEM_PARTITION_P_RO_U_NA \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RO_U_NA}) |
| #define K_MEM_PARTITION_P_NA_U_NA \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_NA_U_NA}) |
| |
| /* Execution-allowed attributes */ |
| #define K_MEM_PARTITION_P_RX_U_RX \ |
| ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RX_U_RX}) |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * Struct to describe a memory region [start, end). |
| */ |
| struct xtensa_mpu_range { |
| /** Start address (inclusive) of the memory region. */ |
| const uintptr_t start; |
| |
| /** |
| * End address (exclusive) of the memory region. |
| * |
| * Use 0xFFFFFFFF for the end of memory. |
| */ |
| const uintptr_t end; |
| |
| /** Access rights for the memory region. */ |
| const uint8_t access_rights:4; |
| |
| /** |
| * Memory type for the region. |
| * |
| * Refer to the Xtensa Instruction Set Architecture (ISA) manual |
| * for general description, and the processor manual for processor |
| * specific information. |
| */ |
| const uint16_t memory_type:9; |
| } __packed; |
| |
| /** |
| * @brief Additional memory regions required by SoC. |
| * |
| * These memory regions will be setup by MPU initialization code at boot. |
| * |
| * Must be defined in the SoC layer. |
| */ |
| extern const struct xtensa_mpu_range xtensa_soc_mpu_ranges[]; |
| |
| /** |
| * @brief Number of SoC additional memory regions. |
| * |
| * Must be defined in the SoC layer. |
| */ |
| extern const int xtensa_soc_mpu_ranges_num; |
| |
| /** |
| * @brief Initialize hardware MPU. |
| * |
| * This initializes the MPU hardware and setup the memory regions at boot. |
| */ |
| void xtensa_mpu_init(void); |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H */ |