Changeset 1dbc43f in mainline for kernel/arch/mips32/src/mm/tlb.c
- Timestamp:
- 2012-11-22T21:23:47Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 908bb96
- Parents:
- 34ae0a5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/mm/tlb.c
r34ae0a5 r1dbc43f 48 48 #include <symtab.h> 49 49 50 static void tlb_refill_fail(istate_t *); 51 static void tlb_invalid_fail(istate_t *); 52 static void tlb_modified_fail(istate_t *); 53 54 static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *, int *); 50 static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *); 55 51 56 52 /** Initialize TLB. … … 92 88 uintptr_t badvaddr; 93 89 pte_t *pte; 94 int pfrc;95 90 96 91 badvaddr = cp0_badvaddr_read(); 97 92 asid = AS->asid; 98 93 99 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc); 100 if (!pte) { 101 switch (pfrc) { 102 case AS_PF_FAULT: 103 goto fail; 104 break; 105 case AS_PF_DEFER: 106 /* 107 * The page fault came during copy_from_uspace() 108 * or copy_to_uspace(). 109 */ 110 return; 111 default: 112 panic("Unexpected pfrc (%d).", pfrc); 94 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 95 if (pte) { 96 /* 97 * Record access to PTE. 98 */ 99 pte->a = 1; 100 101 tlb_prepare_entry_hi(&hi, asid, badvaddr); 102 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, 103 pte->cacheable, pte->pfn); 104 105 /* 106 * New entry is to be inserted into TLB 107 */ 108 cp0_entry_hi_write(hi.value); 109 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 110 cp0_entry_lo0_write(lo.value); 111 cp0_entry_lo1_write(0); 112 } else { 113 cp0_entry_lo0_write(0); 114 cp0_entry_lo1_write(lo.value); 113 115 } 114 } 115 116 /* 117 * Record access to PTE. 118 */ 119 pte->a = 1; 120 121 tlb_prepare_entry_hi(&hi, asid, badvaddr); 122 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, 123 pte->pfn); 124 125 /* 126 * New entry is to be inserted into TLB 127 */ 128 cp0_entry_hi_write(hi.value); 129 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 130 cp0_entry_lo0_write(lo.value); 131 cp0_entry_lo1_write(0); 132 } 133 else { 134 cp0_entry_lo0_write(0); 135 cp0_entry_lo1_write(lo.value); 136 } 137 cp0_pagemask_write(TLB_PAGE_MASK_16K); 138 tlbwr(); 139 140 return; 141 142 fail: 143 tlb_refill_fail(istate); 116 cp0_pagemask_write(TLB_PAGE_MASK_16K); 117 tlbwr(); 118 } 144 119 } 145 120 … … 155 130 entry_hi_t hi; 156 131 pte_t *pte; 157 int pfrc;158 132 159 133 badvaddr = cp0_badvaddr_read(); … … 168 142 index.value = cp0_index_read(); 169 143 170 /* 171 * Fail if the entry is not in TLB. 172 */ 173 if (index.p) { 174 printf("TLB entry not found.\n"); 175 goto fail; 176 } 177 178 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc); 179 if (!pte) { 180 switch (pfrc) { 181 case AS_PF_FAULT: 182 goto fail; 183 break; 184 case AS_PF_DEFER: 185 /* 186 * The page fault came during copy_from_uspace() 187 * or copy_to_uspace(). 188 */ 189 return; 190 default: 191 panic("Unexpected pfrc (%d).", pfrc); 192 } 193 } 194 195 /* 196 * Read the faulting TLB entry. 197 */ 198 tlbr(); 199 200 /* 201 * Record access to PTE. 202 */ 203 pte->a = 1; 204 205 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, 206 pte->pfn); 207 208 /* 209 * The entry is to be updated in TLB. 210 */ 211 if ((badvaddr / PAGE_SIZE) % 2 == 0) 212 cp0_entry_lo0_write(lo.value); 213 else 214 cp0_entry_lo1_write(lo.value); 215 cp0_pagemask_write(TLB_PAGE_MASK_16K); 216 tlbwi(); 217 218 return; 219 220 fail: 221 tlb_invalid_fail(istate); 144 ASSERT(!index.p); 145 146 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 147 if (pte) { 148 /* 149 * Read the faulting TLB entry. 150 */ 151 tlbr(); 152 153 /* 154 * Record access to PTE. 155 */ 156 pte->a = 1; 157 158 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, 159 pte->cacheable, pte->pfn); 160 161 /* 162 * The entry is to be updated in TLB. 163 */ 164 if ((badvaddr / PAGE_SIZE) % 2 == 0) 165 cp0_entry_lo0_write(lo.value); 166 else 167 cp0_entry_lo1_write(lo.value); 168 cp0_pagemask_write(TLB_PAGE_MASK_16K); 169 tlbwi(); 170 } 222 171 } 223 172 … … 233 182 entry_hi_t hi; 234 183 pte_t *pte; 235 int pfrc;236 184 237 185 badvaddr = cp0_badvaddr_read(); … … 249 197 * Fail if the entry is not in TLB. 250 198 */ 251 if (index.p) { 252 printf("TLB entry not found.\n"); 253 goto fail; 254 } 255 256 pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate, &pfrc); 257 if (!pte) { 258 switch (pfrc) { 259 case AS_PF_FAULT: 260 goto fail; 261 break; 262 case AS_PF_DEFER: 263 /* 264 * The page fault came during copy_from_uspace() 265 * or copy_to_uspace(). 266 */ 267 return; 268 default: 269 panic("Unexpected pfrc (%d).", pfrc); 270 } 271 } 272 273 /* 274 * Read the faulting TLB entry. 275 */ 276 tlbr(); 277 278 /* 279 * Record access and write to PTE. 280 */ 281 pte->a = 1; 282 pte->d = 1; 283 284 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, 285 pte->pfn); 286 287 /* 288 * The entry is to be updated in TLB. 289 */ 290 if ((badvaddr / PAGE_SIZE) % 2 == 0) 291 cp0_entry_lo0_write(lo.value); 292 else 293 cp0_entry_lo1_write(lo.value); 294 cp0_pagemask_write(TLB_PAGE_MASK_16K); 295 tlbwi(); 296 297 return; 298 299 fail: 300 tlb_modified_fail(istate); 301 } 302 303 void tlb_refill_fail(istate_t *istate) 304 { 305 uintptr_t va = cp0_badvaddr_read(); 306 307 fault_if_from_uspace(istate, "TLB Refill Exception on %p.", 308 (void *) va); 309 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Refill Exception."); 310 } 311 312 313 void tlb_invalid_fail(istate_t *istate) 314 { 315 uintptr_t va = cp0_badvaddr_read(); 316 317 fault_if_from_uspace(istate, "TLB Invalid Exception on %p.", 318 (void *) va); 319 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Invalid Exception."); 320 } 321 322 void tlb_modified_fail(istate_t *istate) 323 { 324 uintptr_t va = cp0_badvaddr_read(); 325 326 fault_if_from_uspace(istate, "TLB Modified Exception on %p.", 327 (void *) va); 328 panic_memtrap(istate, PF_ACCESS_WRITE, va, "TLB Modified Exception."); 199 ASSERT(!index.p); 200 201 pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate); 202 if (pte) { 203 /* 204 * Read the faulting TLB entry. 205 */ 206 tlbr(); 207 208 /* 209 * Record access and write to PTE. 210 */ 211 pte->a = 1; 212 pte->d = 1; 213 214 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, 215 pte->cacheable, pte->pfn); 216 217 /* 218 * The entry is to be updated in TLB. 219 */ 220 if ((badvaddr / PAGE_SIZE) % 2 == 0) 221 cp0_entry_lo0_write(lo.value); 222 else 223 cp0_entry_lo1_write(lo.value); 224 cp0_pagemask_write(TLB_PAGE_MASK_16K); 225 tlbwi(); 226 } 329 227 } 330 228 … … 334 232 * @param access Access mode that caused the fault. 335 233 * @param istate Pointer to interrupted state. 336 * @param pfrc Pointer to variable where as_page_fault() return code337 * will be stored.338 234 * 339 235 * @return PTE on success, NULL otherwise. 340 236 */ 341 pte_t * 342 find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, 343 int *pfrc) 237 pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate) 344 238 { 345 239 entry_hi_t hi; … … 348 242 hi.value = cp0_entry_hi_read(); 349 243 350 /* 351 * Handler cannot succeed if the ASIDs don't match. 352 */ 353 if (hi.asid != AS->asid) { 354 printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid); 355 return NULL; 356 } 244 ASSERT(hi.asid == AS->asid); 357 245 358 246 /* … … 366 254 */ 367 255 return pte; 368 } else { 369 int rc; 370 371 /* 372 * Mapping not found in page tables. 373 * Resort to higher-level page fault handler. 374 */ 375 switch (rc = as_page_fault(badvaddr, access, istate)) { 376 case AS_PF_OK: 377 /* 378 * The higher-level page fault handler succeeded, 379 * The mapping ought to be in place. 380 */ 381 pte = page_mapping_find(AS, badvaddr, true); 382 ASSERT(pte && pte->p); 383 ASSERT(pte->w || access != PF_ACCESS_WRITE); 384 return pte; 385 case AS_PF_DEFER: 386 *pfrc = AS_PF_DEFER; 387 return NULL; 388 case AS_PF_FAULT: 389 *pfrc = AS_PF_FAULT; 390 return NULL; 391 default: 392 panic("Unexpected rc (%d).", rc); 393 } 394 395 } 256 } 257 258 /* 259 * Mapping not found in page tables. 260 * Resort to higher-level page fault handler. 261 */ 262 if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) { 263 pte = page_mapping_find(AS, badvaddr, true); 264 ASSERT(pte && pte->p); 265 ASSERT(pte->w || access != PF_ACCESS_WRITE); 266 return pte; 267 } 268 269 return NULL; 396 270 } 397 271
Note:
See TracChangeset
for help on using the changeset viewer.