Changes in kernel/genarch/src/mm/page_pt.c [8f80c77:d99c1d2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/mm/page_pt.c
r8f80c77 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(interrupts_disabled()); 75 ASSERT(page_table_locked(as));76 72 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 73 pte_t *newpt; 74 75 ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 76 77 77 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) { 78 pte_t *newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);78 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 e_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));85 83 84 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 pte_t *newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);87 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 e_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));94 92 93 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 pte_t *newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);96 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 e_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));103 101 102 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 * @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. 117 119 * @param page Virtual address of the page to be demapped. 118 *119 120 */ 120 121 void pt_mapping_remove(as_t *as, uintptr_t page) 121 122 { 122 ASSERT(interrupts_disabled()); 123 ASSERT(page_table_locked(as)); 123 pte_t *ptl0, *ptl1, *ptl2, *ptl3; 124 bool empty = true; 125 int i; 124 126 125 127 /* 126 128 * First, remove the mapping, if it exists. 127 * 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. 128 153 */ 129 154 130 pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table); 131 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 132 return; 133 134 pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page))); 135 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 136 return; 137 138 pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page))); 139 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 140 return; 141 142 pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 143 144 /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ 145 memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); 146 147 /* 148 * Second, free all empty tables along the way from PTL3 down to PTL0. 149 * 150 */ 151 152 /* Check PTL3 */ 153 bool empty = true; 154 155 unsigned int i; 155 /* check PTL3 */ 156 156 for (i = 0; i < PTL3_ENTRIES; i++) { 157 157 if (PTE_VALID(&ptl3[i])) { … … 160 160 } 161 161 } 162 163 162 if (empty) { 164 163 /* 165 164 * PTL3 is empty. 166 165 * Release the frame and remove PTL3 pointer from preceding table. 167 *168 166 */ 169 167 frame_free(KA2PA((uintptr_t) ptl3)); 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 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); 177 174 } else { 178 175 /* … … 180 177 * Therefore, there must be a path from PTL0 to PTL3 and 181 178 * thus nothing to free in higher levels. 182 *183 179 */ 184 180 return; 185 181 } 186 182 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; 193 } 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 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 219 212 /* 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; 225 } 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 */ 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 238 230 } 239 231 … … 242 234 * Find mapping for virtual page. 243 235 * 244 * @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. 245 239 * @param page Virtual page. 246 240 * 247 * @return NULL if there is no such mapping; entry from PTL3 describing 248 * the mapping otherwise. 249 * 241 * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise. 250 242 */ 251 243 pte_t *pt_mapping_find(as_t *as, uintptr_t page) 252 244 { 253 ASSERT(interrupts_disabled());254 ASSERT(page_table_locked(as)); 255 256 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 257 249 if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) 258 250 return NULL; 259 260 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 261 254 if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) 262 255 return NULL; 263 264 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 265 259 if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) 266 260 return NULL; 267 268 pt e_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));269 261 262 ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); 263 270 264 return &ptl3[PTL3_INDEX(page)]; 271 265 }
Note:
See TracChangeset
for help on using the changeset viewer.