Rev 2128 | Rev 2467 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2128 | Rev 2465 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | * Copyright (c) 2003-2007 Jakub Jermar |
2 | * Copyright (c) 2007 Pavel Jancik, Michal Kebrt |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
Line 28... | Line 28... | ||
28 | 28 | ||
29 | /** @addtogroup arm32mm |
29 | /** @addtogroup arm32mm |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | /** @file |
32 | /** @file |
- | 33 | * @brief Paging related declarations. |
|
33 | */ |
34 | */ |
34 | 35 | ||
35 | #ifndef KERN_arm32_PAGE_H_ |
36 | #ifndef KERN_arm32_PAGE_H_ |
36 | #define KERN_arm32_PAGE_H_ |
37 | #define KERN_arm32_PAGE_H_ |
37 | 38 | ||
38 | #include <arch/mm/frame.h> |
39 | #include <arch/mm/frame.h> |
- | 40 | #include <mm/mm.h> |
|
- | 41 | #include <arch/exception.h> |
|
39 | 42 | ||
40 | #define PAGE_WIDTH FRAME_WIDTH |
43 | #define PAGE_WIDTH FRAME_WIDTH |
41 | #define PAGE_SIZE FRAME_SIZE |
44 | #define PAGE_SIZE FRAME_SIZE |
42 | 45 | ||
43 | #define PAGE_COLOR_BITS 0 /* dummy */ |
46 | #define PAGE_COLOR_BITS 0 /* dummy */ |
Line 50... | Line 53... | ||
50 | # define PA2KA(x) ((x) + 0x80000000) |
53 | # define PA2KA(x) ((x) + 0x80000000) |
51 | #endif |
54 | #endif |
52 | 55 | ||
53 | #ifdef KERNEL |
56 | #ifdef KERNEL |
54 | 57 | ||
55 | #define PTL0_ENTRIES_ARCH 0 /* TODO */ |
58 | #define PTL0_ENTRIES_ARCH (2 << 12) /* 4096 */ |
56 | #define PTL1_ENTRIES_ARCH 0 /* TODO */ |
59 | #define PTL1_ENTRIES_ARCH 0 |
57 | #define PTL2_ENTRIES_ARCH 0 /* TODO */ |
60 | #define PTL2_ENTRIES_ARCH 0 |
- | 61 | ||
- | 62 | /* coarse page tables used (256 * 4 = 1KB per page) */ |
|
58 | #define PTL3_ENTRIES_ARCH 0 /* TODO */ |
63 | #define PTL3_ENTRIES_ARCH (2 << 8) /* 256 */ |
59 | 64 | ||
60 | #define PTL0_INDEX_ARCH(vaddr) 0 /* TODO */ |
65 | #define PTL0_SIZE_ARCH FOUR_FRAMES |
61 | #define PTL1_INDEX_ARCH(vaddr) 0 /* TODO */ |
66 | #define PTL1_SIZE_ARCH 0 |
62 | #define PTL2_INDEX_ARCH(vaddr) 0 /* TODO */ |
67 | #define PTL2_SIZE_ARCH 0 |
63 | #define PTL3_INDEX_ARCH(vaddr) 0 /* TODO */ |
68 | #define PTL3_SIZE_ARCH ONE_FRAME |
64 | 69 | ||
- | 70 | #define PTL0_INDEX_ARCH(vaddr) (((vaddr) >> 20) & 0xfff) |
|
- | 71 | #define PTL1_INDEX_ARCH(vaddr) 0 |
|
65 | #define SET_PTL0_ADDRESS_ARCH(ptl0) |
72 | #define PTL2_INDEX_ARCH(vaddr) 0 |
- | 73 | #define PTL3_INDEX_ARCH(vaddr) (((vaddr) >> 12) & 0x0ff) |
|
66 | 74 | ||
67 | #define GET_PTL1_ADDRESS_ARCH(ptl0, i) 0 /* TODO */ |
75 | #define GET_PTL1_ADDRESS_ARCH(ptl0, i) \ |
- | 76 | ((pte_t *) ((((pte_level0_t *)(ptl0))[(i)]).coarse_table_addr << 10)) |
|
68 | #define GET_PTL2_ADDRESS_ARCH(ptl1, i) 0 /* TODO */ |
77 | #define GET_PTL2_ADDRESS_ARCH(ptl1, i) \ |
- | 78 | (ptl1) |
|
69 | #define GET_PTL3_ADDRESS_ARCH(ptl2, i) 0 /* TODO */ |
79 | #define GET_PTL3_ADDRESS_ARCH(ptl2, i) \ |
- | 80 | (ptl2) |
|
70 | #define GET_FRAME_ADDRESS_ARCH(ptl3, i) 0 /* TODO */ |
81 | #define GET_FRAME_ADDRESS_ARCH(ptl3, i) \ |
- | 82 | ((uintptr_t) ((((pte_level1_t *)(ptl3))[(i)]).frame_base_addr << 12)) |
|
71 | 83 | ||
- | 84 | #define SET_PTL0_ADDRESS_ARCH(ptl0) \ |
|
- | 85 | (set_ptl0_addr((pte_level0_t *) (ptl0))) |
|
72 | #define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) /* TODO */ |
86 | #define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \ |
- | 87 | (((pte_level0_t *) (ptl0))[(i)].coarse_table_addr = (a) >> 10) |
|
73 | #define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) /* TODO */ |
88 | #define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) |
74 | #define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) /* TODO */ |
89 | #define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) |
75 | #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) /* TODO */ |
90 | #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \ |
- | 91 | (((pte_level1_t *) (ptl3))[(i)].frame_base_addr = (a) >> 12) |
|
76 | 92 | ||
77 | #define GET_PTL1_FLAGS_ARCH(ptl0, i) 0 /* TODO */ |
93 | #define GET_PTL1_FLAGS_ARCH(ptl0, i) \ |
- | 94 | get_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i)) |
|
78 | #define GET_PTL2_FLAGS_ARCH(ptl1, i) 0 /* TODO */ |
95 | #define GET_PTL2_FLAGS_ARCH(ptl1, i) \ |
- | 96 | PAGE_PRESENT |
|
79 | #define GET_PTL3_FLAGS_ARCH(ptl2, i) 0 /* TODO */ |
97 | #define GET_PTL3_FLAGS_ARCH(ptl2, i) \ |
- | 98 | PAGE_PRESENT |
|
80 | #define GET_FRAME_FLAGS_ARCH(ptl3, i) 0 /* TODO */ |
99 | #define GET_FRAME_FLAGS_ARCH(ptl3, i) \ |
- | 100 | get_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i)) |
|
81 | 101 | ||
82 | #define SET_PTL1_FLAGS_ARCH(ptl0, i, x) /* TODO */ |
102 | #define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \ |
- | 103 | set_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i), (x)) |
|
83 | #define SET_PTL2_FLAGS_ARCH(ptl1, i, x) /* TODO */ |
104 | #define SET_PTL2_FLAGS_ARCH(ptl1, i, x) |
84 | #define SET_PTL3_FLAGS_ARCH(ptl2, i, x) /* TODO */ |
105 | #define SET_PTL3_FLAGS_ARCH(ptl2, i, x) |
85 | #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) /* TODO */ |
106 | #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \ |
- | 107 | set_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i), (x)) |
|
86 | 108 | ||
87 | #define PTE_VALID_ARCH(pte) 0 /* TODO */ |
109 | #define PTE_VALID_ARCH(pte) \ |
- | 110 | (*((uint32_t *) (pte)) != 0) |
|
88 | #define PTE_PRESENT_ARCH(pte) 0 /* TODO */ |
111 | #define PTE_PRESENT_ARCH(pte) \ |
- | 112 | (((pte_level0_t *) (pte))->descriptor_type != 0) |
|
- | 113 | ||
- | 114 | /* pte should point into ptl3 */ |
|
89 | #define PTE_GET_FRAME_ARCH(pte) 0 /* TODO */ |
115 | #define PTE_GET_FRAME_ARCH(pte) \ |
- | 116 | (((pte_level1_t *) (pte))->frame_base_addr << FRAME_WIDTH) |
|
- | 117 | ||
- | 118 | /* pte should point into ptl3 */ |
|
90 | #define PTE_WRITABLE_ARCH(pte) 0 /* TODO */ |
119 | #define PTE_WRITABLE_ARCH(pte) \ |
- | 120 | (((pte_level1_t *) (pte))->access_permission_0 == \ |
|
- | 121 | PTE_AP_USER_RW_KERNEL_RW) |
|
- | 122 | ||
91 | #define PTE_EXECUTABLE_ARCH(pte) 0 /* TODO */ |
123 | #define PTE_EXECUTABLE_ARCH(pte) \ |
- | 124 | 1 |
|
92 | 125 | ||
93 | #ifndef __ASM__ |
126 | #ifndef __ASM__ |
94 | 127 | ||
- | 128 | /** Level 0 page table entry. */ |
|
95 | #include <mm/mm.h> |
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; |
|
96 | #include <arch/exception.h> |
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]; |
|
97 | 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 | */ |
|
98 | static inline int get_pt_flags(pte_t *pt, index_t i) |
248 | static inline void set_pt_level0_flags(pte_level0_t *pt, index_t i, int flags) |
99 | { |
249 | { |
100 | return 0; /* TODO */ |
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 | } |
|
101 | } |
263 | } |
102 | 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 | */ |
|
103 | static inline void set_pt_flags(pte_t *pt, index_t i, int flags) |
276 | static inline void set_pt_level1_flags(pte_level1_t *pt, index_t i, int flags) |
104 | { |
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; |
|
105 | /* TODO */ |
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; |
|
106 | return; |
305 | } |
- | 306 | } |
|
107 | } |
307 | } |
108 | 308 | ||
- | 309 | ||
109 | extern void page_arch_init(void); |
310 | extern void page_arch_init(void); |
110 | 311 | ||
- | 312 | ||
111 | #endif /* __ASM__ */ |
313 | #endif /* __ASM__ */ |
112 | 314 | ||
113 | #endif /* KERNEL */ |
315 | #endif /* KERNEL */ |
114 | 316 | ||
115 | #endif |
317 | #endif |