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