1 /* 2 * Copyright 2019 Broadcom 3 * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_ 8 #define ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_ 9 10 #ifndef _ASMLANGUAGE 11 #include <stdint.h> 12 #include <stdlib.h> 13 #endif 14 15 /* Following Memory types supported through MAIR encodings can be passed 16 * by user through "attrs"(attributes) field of specified memory region. 17 * As MAIR supports such 8 encodings, we will reserve attrs[2:0]; 18 * so that we can provide encodings upto 7 if needed in future. 19 */ 20 #define MT_TYPE_MASK 0x7U 21 #define MT_TYPE(attr) (attr & MT_TYPE_MASK) 22 #define MT_DEVICE_nGnRnE 0U 23 #define MT_DEVICE_nGnRE 1U 24 #define MT_DEVICE_GRE 2U 25 #define MT_NORMAL_NC 3U 26 #define MT_NORMAL 4U 27 #define MT_NORMAL_WT 5U 28 29 #define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_nGnRnE * 8)) | \ 30 (0x04 << (MT_DEVICE_nGnRE * 8)) | \ 31 (0x0c << (MT_DEVICE_GRE * 8)) | \ 32 (0x44 << (MT_NORMAL_NC * 8)) | \ 33 (0xffUL << (MT_NORMAL * 8)) | \ 34 (0xbbUL << (MT_NORMAL_WT * 8))) 35 36 /* More flags from user's perspective are supported using remaining bits 37 * of "attrs" field, i.e. attrs[31:3], underlying code will take care 38 * of setting PTE fields correctly. 39 * 40 * current usage of attrs[31:3] is: 41 * attrs[3] : Access Permissions 42 * attrs[4] : Memory access from secure/ns state 43 * attrs[5] : Execute Permissions privileged mode (PXN) 44 * attrs[6] : Execute Permissions unprivileged mode (UXN) 45 * attrs[7] : Mirror RO/RW permissions to EL0 46 * attrs[8] : Overwrite existing mapping if any 47 * attrs[9] : non-Global mapping (nG) 48 * attrs[10]: Paged-out mapping 49 * 50 */ 51 #define MT_PERM_SHIFT 3U 52 #define MT_SEC_SHIFT 4U 53 #define MT_P_EXECUTE_SHIFT 5U 54 #define MT_U_EXECUTE_SHIFT 6U 55 #define MT_RW_AP_SHIFT 7U 56 #define MT_NO_OVERWRITE_SHIFT 8U 57 #define MT_NON_GLOBAL_SHIFT 9U 58 #define MT_PAGED_OUT_SHIFT 10U 59 60 #define MT_RO (0U << MT_PERM_SHIFT) 61 #define MT_RW (1U << MT_PERM_SHIFT) 62 63 #define MT_RW_AP_ELx (1U << MT_RW_AP_SHIFT) 64 #define MT_RW_AP_EL_HIGHER (0U << MT_RW_AP_SHIFT) 65 66 #define MT_SECURE (0U << MT_SEC_SHIFT) 67 #define MT_NS (1U << MT_SEC_SHIFT) 68 69 #define MT_P_EXECUTE (0U << MT_P_EXECUTE_SHIFT) 70 #define MT_P_EXECUTE_NEVER (1U << MT_P_EXECUTE_SHIFT) 71 72 #define MT_U_EXECUTE (0U << MT_U_EXECUTE_SHIFT) 73 #define MT_U_EXECUTE_NEVER (1U << MT_U_EXECUTE_SHIFT) 74 75 #define MT_NO_OVERWRITE (1U << MT_NO_OVERWRITE_SHIFT) 76 77 #define MT_G (0U << MT_NON_GLOBAL_SHIFT) 78 #define MT_NG (1U << MT_NON_GLOBAL_SHIFT) 79 80 #define MT_PAGED_OUT (1U << MT_PAGED_OUT_SHIFT) 81 82 #define MT_P_RW_U_RW (MT_RW | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) 83 #define MT_P_RW_U_NA (MT_RW | MT_RW_AP_EL_HIGHER | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) 84 #define MT_P_RO_U_RO (MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) 85 #define MT_P_RO_U_NA (MT_RO | MT_RW_AP_EL_HIGHER | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) 86 #define MT_P_RO_U_RX (MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE) 87 #define MT_P_RX_U_RX (MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE | MT_U_EXECUTE) 88 #define MT_P_RX_U_NA (MT_RO | MT_RW_AP_EL_HIGHER | MT_P_EXECUTE | MT_U_EXECUTE_NEVER) 89 90 #ifdef CONFIG_ARMV8_A_NS 91 #define MT_DEFAULT_SECURE_STATE MT_NS 92 #else 93 #define MT_DEFAULT_SECURE_STATE MT_SECURE 94 #endif 95 96 /* Definitions used by arch_page_info_get() */ 97 #define ARCH_DATA_PAGE_LOADED BIT(0) 98 #define ARCH_DATA_PAGE_ACCESSED BIT(1) 99 #define ARCH_DATA_PAGE_DIRTY BIT(2) 100 #define ARCH_DATA_PAGE_NOT_MAPPED BIT(3) 101 102 /* 103 * Special unpaged "location" tags (highest possible descriptor physical 104 * address values unlikely to conflict with backing store locations) 105 */ 106 #define ARCH_UNPAGED_ANON_ZERO 0x0000fffffffff000 107 #define ARCH_UNPAGED_ANON_UNINIT 0x0000ffffffffe000 108 109 #ifndef _ASMLANGUAGE 110 111 /* Region definition data structure */ 112 struct arm_mmu_region { 113 /* Region Base Physical Address */ 114 uintptr_t base_pa; 115 /* Region Base Virtual Address */ 116 uintptr_t base_va; 117 /* Region size */ 118 size_t size; 119 /* Region Name */ 120 const char *name; 121 /* Region Attributes */ 122 uint32_t attrs; 123 }; 124 125 /* MMU configuration data structure */ 126 struct arm_mmu_config { 127 /* Number of regions */ 128 unsigned int num_regions; 129 /* Regions */ 130 const struct arm_mmu_region *mmu_regions; 131 }; 132 133 struct arm_mmu_ptables { 134 uint64_t *base_xlat_table; 135 uint64_t ttbr0; 136 }; 137 138 /* Convenience macros to represent the ARMv8-A-specific 139 * configuration for memory access permission and 140 * cache-ability attribution. 141 */ 142 143 #define MMU_REGION_ENTRY(_name, _base_pa, _base_va, _size, _attrs) \ 144 {\ 145 .name = _name, \ 146 .base_pa = _base_pa, \ 147 .base_va = _base_va, \ 148 .size = _size, \ 149 .attrs = _attrs, \ 150 } 151 152 #define MMU_REGION_FLAT_ENTRY(name, adr, sz, attrs) \ 153 MMU_REGION_ENTRY(name, adr, adr, sz, attrs) 154 155 /* 156 * @brief Auto generate mmu region entry for node_id 157 * 158 * Example usage: 159 * 160 * @code{.c} 161 * DT_FOREACH_STATUS_OKAY_VARGS(nxp_imx_gpio, 162 * MMU_REGION_DT_FLAT_ENTRY, 163 * (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS)) 164 * @endcode 165 * 166 * @note Since devicetree_generated.h does not include 167 * node_id##_P_reg_FOREACH_PROP_ELEM* definitions, 168 * we can't automate dts node with multiple reg 169 * entries. 170 */ 171 #define MMU_REGION_DT_FLAT_ENTRY(node_id, attrs) \ 172 MMU_REGION_FLAT_ENTRY(DT_NODE_FULL_NAME(node_id), \ 173 DT_REG_ADDR(node_id), \ 174 DT_REG_SIZE(node_id), \ 175 attrs), 176 177 /* 178 * @brief Auto generate mmu region entry for status = "okay" 179 * nodes compatible to a driver 180 * 181 * Example usage: 182 * 183 * @code{.c} 184 * MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(nxp_imx_gpio, 185 * (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS)) 186 * @endcode 187 * 188 * @note This is a wrapper of @ref MMU_REGION_DT_FLAT_ENTRY 189 */ 190 #define MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(compat, attr) \ 191 DT_FOREACH_STATUS_OKAY_VARGS(compat, \ 192 MMU_REGION_DT_FLAT_ENTRY, attr) 193 194 /* Kernel macros for memory attribution 195 * (access permissions and cache-ability). 196 * 197 * The macros are to be stored in k_mem_partition_attr_t 198 * objects. The format of a k_mem_partition_attr_t object 199 * is an uint32_t composed by permission and attribute flags 200 * located in include/arch/arm64/arm_mmu.h 201 */ 202 203 /* Read-Write access permission attributes */ 204 #define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \ 205 {MT_P_RW_U_RW}) 206 #define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \ 207 {MT_P_RW_U_NA}) 208 #define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \ 209 {MT_P_RO_U_RO}) 210 #define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \ 211 {MT_P_RO_U_NA}) 212 /* Execution-allowed attributes */ 213 #define K_MEM_PARTITION_P_RX_U_RX ((k_mem_partition_attr_t) \ 214 {MT_P_RX_U_RX}) 215 /* Typedef for the k_mem_partition attribute */ 216 typedef struct { uint32_t attrs; } k_mem_partition_attr_t; 217 218 /* Reference to the MMU configuration. 219 * 220 * This struct is defined and populated for each SoC (in the SoC definition), 221 * and holds the build-time configuration information for the fixed MMU 222 * regions enabled during kernel initialization. 223 */ 224 extern const struct arm_mmu_config mmu_config; 225 226 #endif /* _ASMLANGUAGE */ 227 228 #endif /* ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_ */ 229