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