Changes in kernel/genarch/src/mm/page_pt.c [d99c1d2:8f80c77] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/mm/page_pt.c
rd99c1d2 r8f80c77 33 33 /** 34 34 * @file 35 * @brief 35 * @brief Virtual Address Translation for hierarchical 4-level page tables. 36 36 */ 37 37 … … 46 46 #include <memstr.h> 47 47 48 static void pt_mapping_insert(as_t * as, uintptr_t page, uintptr_t frame, int flags);49 static void pt_mapping_remove(as_t * as, uintptr_t page);50 static pte_t *pt_mapping_find(as_t * as, uintptr_t page);48 static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int); 49 static void pt_mapping_remove(as_t *, uintptr_t); 50 static pte_t *pt_mapping_find(as_t *, uintptr_t); 51 51 52 52 page_mapping_operations_t pt_mapping_operations = { … … 61 61 * using flags. 62 62 * 63 * The page table must be locked and interrupts must be disabled. 64 * 65 * @param as Address space to wich page belongs. 66 * @param page Virtual address of the page to be mapped. 63 * @param as Address space to wich page belongs. 64 * @param page Virtual address of the page to be mapped. 67 65 * @param frame Physical address of memory frame to which the mapping is done. 68 66 * @param flags Flags to be used for mapping. 69 */ 70 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags) 67 * 68 */ 69 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, 70 unsigned int flags) 71 71 { 72 pte_t *ptl0 , *ptl1, *ptl2, *ptl3;73 pte_t *newpt; 74 75 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);76 72 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 73 74 ASSERT(interrupts_disabled()); 75 ASSERT(page_table_locked(as)); 76 77 77 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) { 78 newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);78 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA); 79 79 memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0); 80 80 SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt)); 81 81 SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 82 82 } 83 84 pt l1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));85 83 84 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 85 86 86 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) { 87 newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);87 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA); 88 88 memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0); 89 89 SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt)); 90 90 SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 91 91 } 92 93 pt l2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));94 92 93 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 94 95 95 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) { 96 newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);96 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA); 97 97 memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0); 98 98 SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt)); 99 99 SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 100 100 } 101 102 pt l3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));103 101 102 pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 103 104 104 SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame); 105 105 SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags); … … 114 114 * Empty page tables except PTL0 are freed. 115 115 * 116 * The page table must be locked and interrupts must be disabled. 117 * 118 * @param as Address space to wich page belongs. 116 * @param as Address space to wich page belongs. 119 117 * @param page Virtual address of the page to be demapped. 118 * 120 119 */ 121 120 void pt_mapping_remove(as_t *as, uintptr_t page) 122 121 { 123 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 124 bool empty = true; 125 int i; 122 ASSERT(interrupts_disabled()); 123 ASSERT(page_table_locked(as)); 126 124 127 125 /* 128 126 * First, remove the mapping, if it exists. 127 * 129 128 */ 130 131 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 132 129 130 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 133 131 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 134 132 return; 135 136 ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 137 133 134 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 138 135 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 139 136 return; 140 141 ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 142 137 138 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 143 139 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 144 140 return; 145 146 pt l3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));147 141 142 pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 143 148 144 /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ 149 145 memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); 150 146 151 147 /* 152 148 * Second, free all empty tables along the way from PTL3 down to PTL0. 149 * 153 150 */ 154 151 155 /* check PTL3 */ 152 /* Check PTL3 */ 153 bool empty = true; 154 155 unsigned int i; 156 156 for (i = 0; i < PTL3_ENTRIES; i++) { 157 157 if (PTE_VALID(&ptl3[i])) { … … 160 160 } 161 161 } 162 162 163 if (empty) { 163 164 /* 164 165 * PTL3 is empty. 165 166 * Release the frame and remove PTL3 pointer from preceding table. 167 * 166 168 */ 167 169 frame_free(KA2PA((uintptr_t) ptl3)); 168 if (PTL2_ENTRIES) 169 memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); 170 else if (PTL1_ENTRIES) 171 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); 172 else 173 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 170 #if (PTL2_ENTRIES != 0) 171 memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); 172 #elif (PTL1_ENTRIES != 0) 173 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); 174 #else 175 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 176 #endif 174 177 } else { 175 178 /* … … 177 180 * Therefore, there must be a path from PTL0 to PTL3 and 178 181 * thus nothing to free in higher levels. 179 * /180 return;181 }182 183 /* check PTL2, empty is still true */184 if (PTL2_ENTRIES) {185 for (i = 0; i < PTL2_ENTRIES; i++) { 186 if (PTE_VALID(&ptl2[i])) {187 empty = false;188 break;189 }182 * 183 */ 184 return; 185 } 186 187 /* Check PTL2, empty is still true */ 188 #if (PTL2_ENTRIES != 0) 189 for (i = 0; i < PTL2_ENTRIES; i++) { 190 if (PTE_VALID(&ptl2[i])) { 191 empty = false; 192 break; 190 193 } 191 if (empty) { 192 /* 193 * PTL2 is empty. 194 * Release the frame and remove PTL2 pointer from preceding table. 195 */ 196 frame_free(KA2PA((uintptr_t) ptl2)); 197 if (PTL1_ENTRIES) 198 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); 199 else 200 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 194 } 195 196 if (empty) { 197 /* 198 * PTL2 is empty. 199 * Release the frame and remove PTL2 pointer from preceding table. 200 * 201 */ 202 frame_free(KA2PA((uintptr_t) ptl2)); 203 #if (PTL1_ENTRIES != 0) 204 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); 205 #else 206 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 207 #endif 208 } else { 209 /* 210 * PTL2 is not empty. 211 * Therefore, there must be a path from PTL0 to PTL2 and 212 * thus nothing to free in higher levels. 213 * 214 */ 215 return; 216 } 217 #endif /* PTL2_ENTRIES != 0 */ 218 219 /* check PTL1, empty is still true */ 220 #if (PTL1_ENTRIES != 0) 221 for (i = 0; i < PTL1_ENTRIES; i++) { 222 if (PTE_VALID(&ptl1[i])) { 223 empty = false; 224 break; 201 225 } 202 else { 203 /* 204 * PTL2 is not empty. 205 * Therefore, there must be a path from PTL0 to PTL2 and 206 * thus nothing to free in higher levels. 207 */ 208 return; 209 } 210 } 211 212 /* check PTL1, empty is still true */ 213 if (PTL1_ENTRIES) { 214 for (i = 0; i < PTL1_ENTRIES; i++) { 215 if (PTE_VALID(&ptl1[i])) { 216 empty = false; 217 break; 218 } 219 } 220 if (empty) { 221 /* 222 * PTL1 is empty. 223 * Release the frame and remove PTL1 pointer from preceding table. 224 */ 225 frame_free(KA2PA((uintptr_t) ptl1)); 226 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 227 } 228 } 229 226 } 227 228 if (empty) { 229 /* 230 * PTL1 is empty. 231 * Release the frame and remove PTL1 pointer from preceding table. 232 * 233 */ 234 frame_free(KA2PA((uintptr_t) ptl1)); 235 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); 236 } 237 #endif /* PTL1_ENTRIES != 0 */ 230 238 } 231 239 … … 234 242 * Find mapping for virtual page. 235 243 * 236 * The page table must be locked and interrupts must be disabled. 237 * 238 * @param as Address space to which page belongs. 244 * @param as Address space to which page belongs. 239 245 * @param page Virtual page. 240 246 * 241 * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise. 247 * @return NULL if there is no such mapping; entry from PTL3 describing 248 * the mapping otherwise. 249 * 242 250 */ 243 251 pte_t *pt_mapping_find(as_t *as, uintptr_t page) 244 252 { 245 pte_t *ptl0, *ptl1, *ptl2, *ptl3;246 247 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 248 253 ASSERT(interrupts_disabled()); 254 ASSERT(page_table_locked(as)); 255 256 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 249 257 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 250 258 return NULL; 251 252 ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 253 259 260 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 254 261 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 255 262 return NULL; 256 257 ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 258 263 264 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 259 265 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 260 266 return NULL; 261 262 pt l3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));263 267 268 pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 269 264 270 return &ptl3[PTL3_INDEX(page)]; 265 271 }
Note:
See TracChangeset
for help on using the changeset viewer.