Changeset 25eec4e in mainline for kernel/arch/mips64/src/mm/tlb.c
- Timestamp:
- 2013-04-19T18:38:18Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6d717a4
- Parents:
- a1e2df13 (diff), 289cb7dd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips64/src/mm/tlb.c
ra1e2df13 r25eec4e 79 79 * @param access Access mode that caused the fault. 80 80 * @param istate Pointer to interrupted state. 81 * @param pfrc Pointer to variable where as_page_fault()82 * return code will be stored.83 81 * 84 82 * @return PTE on success, NULL otherwise. … … 86 84 */ 87 85 static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, 88 istate_t *istate , int *pfrc)86 istate_t *istate) 89 87 { 90 88 entry_hi_t hi; 91 89 hi.value = cp0_entry_hi_read(); 92 90 93 /* 94 * Handler cannot succeed if the ASIDs don't match. 95 */ 96 if (hi.asid != AS->asid) { 97 printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid); 98 return NULL; 99 } 91 ASSERT(hi.asid == AS->asid); 100 92 101 93 /* … … 109 101 */ 110 102 return pte; 111 } else { 112 int rc; 113 114 /* 115 * Mapping not found in page tables. 116 * Resort to higher-level page fault handler. 117 */ 118 switch (rc = as_page_fault(badvaddr, access, istate)) { 119 case AS_PF_OK: 120 /* 121 * The higher-level page fault handler succeeded, 122 * The mapping ought to be in place. 123 */ 124 pte = page_mapping_find(AS, badvaddr, true); 125 ASSERT(pte); 126 ASSERT(pte->p); 127 ASSERT((pte->w) || (access != PF_ACCESS_WRITE)); 128 return pte; 129 case AS_PF_DEFER: 130 *pfrc = AS_PF_DEFER; 131 return NULL; 132 case AS_PF_FAULT: 133 *pfrc = AS_PF_FAULT; 134 return NULL; 135 default: 136 panic("Unexpected return code (%d).", rc); 137 } 138 } 103 } 104 105 /* 106 * Mapping not found in page tables. 107 * Resort to higher-level page fault handler. 108 */ 109 if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) { 110 /* 111 * The higher-level page fault handler succeeded, 112 * The mapping ought to be in place. 113 */ 114 pte = page_mapping_find(AS, badvaddr, true); 115 ASSERT(pte); 116 ASSERT(pte->p); 117 ASSERT((pte->w) || (access != PF_ACCESS_WRITE)); 118 return pte; 119 } 120 121 return NULL; 139 122 } 140 123 … … 156 139 } 157 140 158 static void tlb_refill_fail(istate_t *istate)159 {160 uintptr_t va = cp0_badvaddr_read();161 162 fault_if_from_uspace(istate, "TLB Refill Exception on %p.",163 (void *) va);164 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Refill Exception.");165 }166 167 static void tlb_invalid_fail(istate_t *istate)168 {169 uintptr_t va = cp0_badvaddr_read();170 171 fault_if_from_uspace(istate, "TLB Invalid Exception on %p.",172 (void *) va);173 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Invalid Exception.");174 }175 176 static void tlb_modified_fail(istate_t *istate)177 {178 uintptr_t va = cp0_badvaddr_read();179 180 fault_if_from_uspace(istate, "TLB Modified Exception on %p.",181 (void *) va);182 panic_memtrap(istate, PF_ACCESS_WRITE, va, "TLB Modified Exception.");183 }184 185 141 /** Process TLB Refill Exception. 186 142 * … … 196 152 mutex_unlock(&AS->lock); 197 153 198 int pfrc; 199 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, 200 istate, &pfrc); 201 if (!pte) { 202 switch (pfrc) { 203 case AS_PF_FAULT: 204 goto fail; 205 break; 206 case AS_PF_DEFER: 207 /* 208 * The page fault came during copy_from_uspace() 209 * or copy_to_uspace(). 210 */ 211 return; 212 default: 213 panic("Unexpected pfrc (%d).", pfrc); 154 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 155 if (pte) { 156 /* 157 * Record access to PTE. 158 */ 159 pte->a = 1; 160 161 entry_lo_t lo; 162 entry_hi_t hi; 163 164 tlb_prepare_entry_hi(&hi, asid, badvaddr); 165 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, 166 pte->frame); 167 168 /* 169 * New entry is to be inserted into TLB 170 */ 171 cp0_entry_hi_write(hi.value); 172 173 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 174 cp0_entry_lo0_write(lo.value); 175 cp0_entry_lo1_write(0); 176 } else { 177 cp0_entry_lo0_write(0); 178 cp0_entry_lo1_write(lo.value); 214 179 } 215 } 216 217 /* 218 * Record access to PTE. 219 */ 220 pte->a = 1; 221 222 entry_lo_t lo; 223 entry_hi_t hi; 224 225 tlb_prepare_entry_hi(&hi, asid, badvaddr); 226 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, 227 pte->frame); 228 229 /* 230 * New entry is to be inserted into TLB 231 */ 232 cp0_entry_hi_write(hi.value); 233 234 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 235 cp0_entry_lo0_write(lo.value); 236 cp0_entry_lo1_write(0); 237 } else { 238 cp0_entry_lo0_write(0); 239 cp0_entry_lo1_write(lo.value); 240 } 241 242 cp0_pagemask_write(TLB_PAGE_MASK_16K); 243 tlbwr(); 244 245 return; 246 247 fail: 248 tlb_refill_fail(istate); 180 181 cp0_pagemask_write(TLB_PAGE_MASK_16K); 182 tlbwr(); 183 } 249 184 } 250 185 … … 271 206 index.value = cp0_index_read(); 272 207 273 /* 274 * Fail if the entry is not in TLB. 275 */ 276 if (index.p) { 277 printf("TLB entry not found.\n"); 278 goto fail; 279 } 280 281 int pfrc; 282 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, 283 istate, &pfrc); 284 if (!pte) { 285 switch (pfrc) { 286 case AS_PF_FAULT: 287 goto fail; 288 break; 289 case AS_PF_DEFER: 290 /* 291 * The page fault came during copy_from_uspace() 292 * or copy_to_uspace(). 293 */ 294 return; 295 default: 296 panic("Unexpected pfrc (%d).", pfrc); 297 } 298 } 299 300 /* 301 * Read the faulting TLB entry. 302 */ 303 tlbr(); 304 305 /* 306 * Record access to PTE. 307 */ 308 pte->a = 1; 309 310 entry_lo_t lo; 311 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, 312 pte->frame); 313 314 /* 315 * The entry is to be updated in TLB. 316 */ 317 if ((badvaddr / PAGE_SIZE) % 2 == 0) 318 cp0_entry_lo0_write(lo.value); 319 else 320 cp0_entry_lo1_write(lo.value); 321 322 cp0_pagemask_write(TLB_PAGE_MASK_16K); 323 tlbwi(); 324 325 return; 326 327 fail: 328 tlb_invalid_fail(istate); 208 ASSERT(!index.p); 209 210 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 211 if (pte) { 212 /* 213 * Read the faulting TLB entry. 214 */ 215 tlbr(); 216 217 /* 218 * Record access to PTE. 219 */ 220 pte->a = 1; 221 222 entry_lo_t lo; 223 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, 224 pte->frame); 225 226 /* 227 * The entry is to be updated in TLB. 228 */ 229 if ((badvaddr / PAGE_SIZE) % 2 == 0) 230 cp0_entry_lo0_write(lo.value); 231 else 232 cp0_entry_lo1_write(lo.value); 233 234 cp0_pagemask_write(TLB_PAGE_MASK_16K); 235 tlbwi(); 236 } 237 329 238 } 330 239 … … 351 260 index.value = cp0_index_read(); 352 261 353 /* 354 * Fail if the entry is not in TLB. 355 */ 356 if (index.p) { 357 printf("TLB entry not found.\n"); 358 goto fail; 359 } 360 361 int pfrc; 362 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, 363 istate, &pfrc); 364 if (!pte) { 365 switch (pfrc) { 366 case AS_PF_FAULT: 367 goto fail; 368 break; 369 case AS_PF_DEFER: 370 /* 371 * The page fault came during copy_from_uspace() 372 * or copy_to_uspace(). 373 */ 374 return; 375 default: 376 panic("Unexpected pfrc (%d).", pfrc); 377 } 378 } 379 380 /* 381 * Read the faulting TLB entry. 382 */ 383 tlbr(); 384 385 /* 386 * Record access and write to PTE. 387 */ 388 pte->a = 1; 389 pte->d = 1; 390 391 entry_lo_t lo; 392 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->c, 393 pte->frame); 394 395 /* 396 * The entry is to be updated in TLB. 397 */ 398 if ((badvaddr / PAGE_SIZE) % 2 == 0) 399 cp0_entry_lo0_write(lo.value); 400 else 401 cp0_entry_lo1_write(lo.value); 402 403 cp0_pagemask_write(TLB_PAGE_MASK_16K); 404 tlbwi(); 405 406 return; 407 408 fail: 409 tlb_modified_fail(istate); 262 ASSERT(!index.p); 263 264 pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate); 265 if (pte) { 266 /* 267 * Read the faulting TLB entry. 268 */ 269 tlbr(); 270 271 /* 272 * Record access and write to PTE. 273 */ 274 pte->a = 1; 275 pte->d = 1; 276 277 entry_lo_t lo; 278 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->c, 279 pte->frame); 280 281 /* 282 * The entry is to be updated in TLB. 283 */ 284 if ((badvaddr / PAGE_SIZE) % 2 == 0) 285 cp0_entry_lo0_write(lo.value); 286 else 287 cp0_entry_lo1_write(lo.value); 288 289 cp0_pagemask_write(TLB_PAGE_MASK_16K); 290 tlbwi(); 291 } 410 292 } 411 293
Note:
See TracChangeset
for help on using the changeset viewer.