Changes in kernel/genarch/src/mm/page_pt.c [fdaad75d:d99c1d2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/mm/page_pt.c
rfdaad75d rd99c1d2 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 * , 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);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); 51 51 52 52 page_mapping_operations_t pt_mapping_operations = { … … 61 61 * using flags. 62 62 * 63 * @param as Address space to wich page belongs. 64 * @param page Virtual address of the page to be mapped. 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. 65 67 * @param frame Physical address of memory frame to which the mapping is done. 66 68 * @param flags Flags to be used for mapping. 67 * 68 */ 69 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, 70 unsigned int flags) 69 */ 70 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags) 71 71 { 72 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 73 74 ASSERT(page_table_locked(as)); 75 72 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 73 pte_t *newpt; 74 75 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 76 76 77 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) { 77 pte_t *newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);78 newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA); 78 79 memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0); 79 80 SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt)); 80 81 SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 81 82 } 82 83 pt e_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));84 83 84 ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 85 85 86 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) { 86 pte_t *newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);87 newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA); 87 88 memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0); 88 89 SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt)); 89 90 SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 90 91 } 91 92 pt e_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));93 92 93 ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 94 94 95 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) { 95 pte_t *newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);96 newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA); 96 97 memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0); 97 98 SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt)); 98 99 SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); 99 100 } 100 101 pt e_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));102 101 102 ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 103 103 104 SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame); 104 105 SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags); … … 113 114 * Empty page tables except PTL0 are freed. 114 115 * 115 * @param as Address space to wich page belongs. 116 * The page table must be locked and interrupts must be disabled. 117 * 118 * @param as Address space to wich page belongs. 116 119 * @param page Virtual address of the page to be demapped. 117 *118 120 */ 119 121 void pt_mapping_remove(as_t *as, uintptr_t page) 120 122 { 121 ASSERT(page_table_locked(as)); 123 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 124 bool empty = true; 125 int i; 122 126 123 127 /* 124 128 * First, remove the mapping, if it exists. 125 * 129 */ 130 131 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 132 133 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 134 return; 135 136 ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 137 138 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 139 return; 140 141 ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 142 143 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 144 return; 145 146 ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 147 148 /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ 149 memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); 150 151 /* 152 * Second, free all empty tables along the way from PTL3 down to PTL0. 126 153 */ 127 154 128 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 129 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 130 return; 131 132 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 133 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 134 return; 135 136 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 137 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 138 return; 139 140 pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 141 142 /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ 143 memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); 144 145 /* 146 * Second, free all empty tables along the way from PTL3 down to PTL0. 147 * 148 */ 149 150 /* Check PTL3 */ 151 bool empty = true; 152 153 unsigned int i; 155 /* check PTL3 */ 154 156 for (i = 0; i < PTL3_ENTRIES; i++) { 155 157 if (PTE_VALID(&ptl3[i])) { … … 158 160 } 159 161 } 160 161 162 if (empty) { 162 163 /* 163 164 * PTL3 is empty. 164 165 * 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 != 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 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); 175 174 } else { 176 175 /* … … 178 177 * Therefore, there must be a path from PTL0 to PTL3 and 179 178 * thus nothing to free in higher levels. 180 *181 179 */ 182 180 return; 183 181 } 184 182 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; 191 } 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 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 } 190 } 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); 201 } 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 217 212 /* 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; 223 } 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 */ 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 236 230 } 237 231 … … 240 234 * Find mapping for virtual page. 241 235 * 242 * @param as Address space to which page belongs. 236 * The page table must be locked and interrupts must be disabled. 237 * 238 * @param as Address space to which page belongs. 243 239 * @param page Virtual page. 244 240 * 245 * @return NULL if there is no such mapping; entry from PTL3 describing 246 * the mapping otherwise. 247 * 241 * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise. 248 242 */ 249 243 pte_t *pt_mapping_find(as_t *as, uintptr_t page) 250 244 { 251 ASSERT(page_table_locked(as)); 252 253 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 245 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 246 247 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 248 254 249 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 255 250 return NULL; 256 257 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 251 252 ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 253 258 254 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 259 255 return NULL; 260 261 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 256 257 ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 258 262 259 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 263 260 return NULL; 264 265 pt e_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));266 261 262 ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 263 267 264 return &ptl3[PTL3_INDEX(page)]; 268 265 }
Note:
See TracChangeset
for help on using the changeset viewer.