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