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