Changes in kernel/arch/arm32/include/mm/page.h [3b71e84d:914e063] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/arm32/include/mm/page.h
r3b71e84d r914e063 37 37 #define KERN_arm32_PAGE_H_ 38 38 39 #include <arch/mm/frame.h> 40 #include <mm/mm.h> 41 #include <arch/exception.h> 42 #include <trace.h> 43 44 #define PAGE_WIDTH FRAME_WIDTH 45 #define PAGE_SIZE FRAME_SIZE 46 39 #ifdef MACHINE_beagleboardxm 40 #ifndef __ASM__ 41 # define KA2PA(x) ((uintptr_t) (x)) 42 # define PA2KA(x) ((uintptr_t) (x)) 43 #else 44 # define KA2PA(x) (x) 45 # define PA2KA(x) (x) 46 #endif 47 #else 47 48 #ifndef __ASM__ 48 49 # define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) … … 52 53 # define PA2KA(x) ((x) + 0x80000000) 53 54 #endif 55 #endif 54 56 55 /* Number of entries in each level. */ 56 #define PTL0_ENTRIES_ARCH (1 << 12) /* 4096 */ 57 #define PTL1_ENTRIES_ARCH 0 58 #define PTL2_ENTRIES_ARCH 0 59 /* coarse page tables used (256 * 4 = 1KB per page) */ 60 #define PTL3_ENTRIES_ARCH (1 << 8) /* 256 */ 61 62 /* Page table sizes for each level. */ 63 #define PTL0_SIZE_ARCH FOUR_FRAMES 64 #define PTL1_SIZE_ARCH 0 65 #define PTL2_SIZE_ARCH 0 66 #define PTL3_SIZE_ARCH ONE_FRAME 67 68 /* Macros calculating indices into page tables for each level. */ 69 #define PTL0_INDEX_ARCH(vaddr) (((vaddr) >> 20) & 0xfff) 70 #define PTL1_INDEX_ARCH(vaddr) 0 71 #define PTL2_INDEX_ARCH(vaddr) 0 72 #define PTL3_INDEX_ARCH(vaddr) (((vaddr) >> 12) & 0x0ff) 73 74 /* Get PTE address accessors for each level. */ 75 #define GET_PTL1_ADDRESS_ARCH(ptl0, i) \ 76 ((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10)) 77 #define GET_PTL2_ADDRESS_ARCH(ptl1, i) \ 78 (ptl1) 79 #define GET_PTL3_ADDRESS_ARCH(ptl2, i) \ 80 (ptl2) 81 #define GET_FRAME_ADDRESS_ARCH(ptl3, i) \ 82 ((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12)) 83 84 /* Set PTE address accessors for each level. */ 85 #define SET_PTL0_ADDRESS_ARCH(ptl0) \ 86 (set_ptl0_addr((pte_t *) (ptl0))) 87 #define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \ 88 (((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10) 89 #define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) 90 #define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) 91 #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \ 92 (((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12) 93 94 /* Get PTE flags accessors for each level. */ 95 #define GET_PTL1_FLAGS_ARCH(ptl0, i) \ 96 get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i)) 97 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \ 98 PAGE_PRESENT 99 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \ 100 PAGE_PRESENT 101 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \ 102 get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i)) 103 104 /* Set PTE flags accessors for each level. */ 105 #define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \ 106 set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x)) 107 #define SET_PTL2_FLAGS_ARCH(ptl1, i, x) 108 #define SET_PTL3_FLAGS_ARCH(ptl2, i, x) 109 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \ 110 set_pt_level1_flags((pte_t *) (ptl3), (size_t) (i), (x)) 111 112 /* Macros for querying the last-level PTE entries. */ 113 #define PTE_VALID_ARCH(pte) \ 114 (*((uint32_t *) (pte)) != 0) 115 #define PTE_PRESENT_ARCH(pte) \ 116 (((pte_t *) (pte))->l0.descriptor_type != 0) 117 #define PTE_GET_FRAME_ARCH(pte) \ 118 (((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH) 119 #define PTE_WRITABLE_ARCH(pte) \ 120 (((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW) 121 #define PTE_EXECUTABLE_ARCH(pte) \ 122 1 123 124 #ifndef __ASM__ 125 126 /** Level 0 page table entry. */ 127 typedef struct { 128 /* 0b01 for coarse tables, see below for details */ 129 unsigned descriptor_type : 2; 130 unsigned impl_specific : 3; 131 unsigned domain : 4; 132 unsigned should_be_zero : 1; 133 134 /* Pointer to the coarse 2nd level page table (holding entries for small 135 * (4KB) or large (64KB) pages. ARM also supports fine 2nd level page 136 * tables that may hold even tiny pages (1KB) but they are bigger (4KB 137 * per table in comparison with 1KB per the coarse table) 138 */ 139 unsigned coarse_table_addr : 22; 140 } ATTRIBUTE_PACKED pte_level0_t; 141 142 /** Level 1 page table entry (small (4KB) pages used). */ 143 typedef struct { 144 145 /* 0b10 for small pages */ 146 unsigned descriptor_type : 2; 147 unsigned bufferable : 1; 148 unsigned cacheable : 1; 149 150 /* access permissions for each of 4 subparts of a page 151 * (for each 1KB when small pages used */ 152 unsigned access_permission_0 : 2; 153 unsigned access_permission_1 : 2; 154 unsigned access_permission_2 : 2; 155 unsigned access_permission_3 : 2; 156 unsigned frame_base_addr : 20; 157 } ATTRIBUTE_PACKED pte_level1_t; 158 159 typedef union { 160 pte_level0_t l0; 161 pte_level1_t l1; 162 } pte_t; 163 164 /* Level 1 page tables access permissions */ 165 166 /** User mode: no access, privileged mode: no access. */ 167 #define PTE_AP_USER_NO_KERNEL_NO 0 168 169 /** User mode: no access, privileged mode: read/write. */ 170 #define PTE_AP_USER_NO_KERNEL_RW 1 171 172 /** User mode: read only, privileged mode: read/write. */ 173 #define PTE_AP_USER_RO_KERNEL_RW 2 174 175 /** User mode: read/write, privileged mode: read/write. */ 176 #define PTE_AP_USER_RW_KERNEL_RW 3 177 178 179 /* pte_level0_t and pte_level1_t descriptor_type flags */ 180 181 /** pte_level0_t and pte_level1_t "not present" flag (used in descriptor_type). */ 182 #define PTE_DESCRIPTOR_NOT_PRESENT 0 183 184 /** pte_level0_t coarse page table flag (used in descriptor_type). */ 185 #define PTE_DESCRIPTOR_COARSE_TABLE 1 186 187 /** pte_level1_t small page table flag (used in descriptor type). */ 188 #define PTE_DESCRIPTOR_SMALL_PAGE 2 189 190 191 /** Sets the address of level 0 page table. 192 * 193 * @param pt Pointer to the page table to set. 194 * 195 */ 196 NO_TRACE static inline void set_ptl0_addr(pte_t *pt) 197 { 198 asm volatile ( 199 "mcr p15, 0, %[pt], c2, c0, 0\n" 200 :: [pt] "r" (pt) 201 ); 202 } 203 204 205 /** Returns level 0 page table entry flags. 206 * 207 * @param pt Level 0 page table. 208 * @param i Index of the entry to return. 209 * 210 */ 211 NO_TRACE static inline int get_pt_level0_flags(pte_t *pt, size_t i) 212 { 213 pte_level0_t *p = &pt[i].l0; 214 int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT); 215 216 return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) | 217 (1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) | 218 (1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT); 219 } 220 221 /** Returns level 1 page table entry flags. 222 * 223 * @param pt Level 1 page table. 224 * @param i Index of the entry to return. 225 * 226 */ 227 NO_TRACE static inline int get_pt_level1_flags(pte_t *pt, size_t i) 228 { 229 pte_level1_t *p = &pt[i].l1; 230 231 int dt = p->descriptor_type; 232 int ap = p->access_permission_0; 233 234 return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) | 235 ((ap == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT) | 236 ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT) | 237 ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_WRITE_SHIFT) | 238 ((ap != PTE_AP_USER_NO_KERNEL_RW) << PAGE_USER_SHIFT) | 239 ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_READ_SHIFT) | 240 ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT) | 241 (1 << PAGE_EXEC_SHIFT) | 242 (p->bufferable << PAGE_CACHEABLE); 243 } 244 245 /** Sets flags of level 0 page table entry. 246 * 247 * @param pt level 0 page table 248 * @param i index of the entry to be changed 249 * @param flags new flags 250 * 251 */ 252 NO_TRACE static inline void set_pt_level0_flags(pte_t *pt, size_t i, int flags) 253 { 254 pte_level0_t *p = &pt[i].l0; 255 256 if (flags & PAGE_NOT_PRESENT) { 257 p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT; 258 /* 259 * Ensures that the entry will be recognized as valid when 260 * PTE_VALID_ARCH applied. 261 */ 262 p->should_be_zero = 1; 263 } else { 264 p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE; 265 p->should_be_zero = 0; 266 } 267 } 268 269 270 /** Sets flags of level 1 page table entry. 271 * 272 * We use same access rights for the whole page. When page 273 * is not preset we store 1 in acess_rigts_3 so that at least 274 * one bit is 1 (to mark correct page entry, see #PAGE_VALID_ARCH). 275 * 276 * @param pt Level 1 page table. 277 * @param i Index of the entry to be changed. 278 * @param flags New flags. 279 * 280 */ 281 NO_TRACE static inline void set_pt_level1_flags(pte_t *pt, size_t i, int flags) 282 { 283 pte_level1_t *p = &pt[i].l1; 284 285 if (flags & PAGE_NOT_PRESENT) { 286 p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT; 287 p->access_permission_3 = 1; 288 } else { 289 p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE; 290 p->access_permission_3 = p->access_permission_0; 291 } 292 293 p->cacheable = p->bufferable = (flags & PAGE_CACHEABLE) != 0; 294 295 /* default access permission */ 296 p->access_permission_0 = p->access_permission_1 = 297 p->access_permission_2 = p->access_permission_3 = 298 PTE_AP_USER_NO_KERNEL_RW; 299 300 if (flags & PAGE_USER) { 301 if (flags & PAGE_READ) { 302 p->access_permission_0 = p->access_permission_1 = 303 p->access_permission_2 = p->access_permission_3 = 304 PTE_AP_USER_RO_KERNEL_RW; 305 } 306 if (flags & PAGE_WRITE) { 307 p->access_permission_0 = p->access_permission_1 = 308 p->access_permission_2 = p->access_permission_3 = 309 PTE_AP_USER_RW_KERNEL_RW; 310 } 311 } 312 } 313 314 315 extern void page_arch_init(void); 316 317 318 #endif /* __ASM__ */ 57 #if defined(PROCESSOR_armv7) 58 #include "page_armv7.h" 59 #elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5) 60 #include "page_armv4.h" 61 #endif 319 62 320 63 #endif
Note:
See TracChangeset
for help on using the changeset viewer.