Commit f2e9ebef12c6f00d650eb06f33dbdd06db0919f2
1 parent
388bb21a
MMU code improvements, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2811 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
24 additions
and
18 deletions
target-mips/helper.c
| ... | ... | @@ -73,19 +73,18 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, |
| 73 | 73 | for (i = 0; i < env->tlb_in_use; i++) { |
| 74 | 74 | r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; |
| 75 | 75 | /* 1k pages are not supported. */ |
| 76 | - target_ulong mask = tlb->PageMask | 0x1FFF; | |
| 76 | + target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); | |
| 77 | 77 | target_ulong tag = address & ~mask; |
| 78 | - int n; | |
| 78 | + target_ulong VPN = tlb->VPN & ~mask; | |
| 79 | 79 | |
| 80 | 80 | /* Check ASID, virtual page number & size */ |
| 81 | - if ((tlb->G == 1 || tlb->ASID == ASID) && | |
| 82 | - tlb->VPN == tag) { | |
| 81 | + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { | |
| 83 | 82 | /* TLB match */ |
| 84 | - n = !!(address & mask & ~(mask >> 1)); | |
| 83 | + int n = !!(address & mask & ~(mask >> 1)); | |
| 85 | 84 | /* Check access rights */ |
| 86 | - if (!(n ? tlb->V1 : tlb->V0)) | |
| 85 | + if (!(n ? tlb->V1 : tlb->V0)) | |
| 87 | 86 | return TLBRET_INVALID; |
| 88 | - if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | |
| 87 | + if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | |
| 89 | 88 | *physical = tlb->PFN[n] | (address & (mask >> 1)); |
| 90 | 89 | *prot = PAGE_READ; |
| 91 | 90 | if (n ? tlb->D1 : tlb->D0) |
| ... | ... | @@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 502 | 501 | target_ulong mask; |
| 503 | 502 | |
| 504 | 503 | tlb = &env->mmu.r4k.tlb[idx]; |
| 505 | - /* The qemu TLB is flushed then the ASID changes, so no need to | |
| 504 | + /* The qemu TLB is flushed when the ASID changes, so no need to | |
| 506 | 505 | flush these entries again. */ |
| 507 | 506 | if (tlb->G == 0 && tlb->ASID != ASID) { |
| 508 | 507 | return; |
| ... | ... | @@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 518 | 517 | } |
| 519 | 518 | |
| 520 | 519 | /* 1k pages are not supported. */ |
| 521 | - mask = tlb->PageMask | 0x1FFF; | |
| 520 | + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); | |
| 522 | 521 | if (tlb->V0) { |
| 523 | - addr = tlb->VPN; | |
| 522 | + addr = tlb->VPN & ~mask; | |
| 524 | 523 | end = addr | (mask >> 1); |
| 525 | 524 | while (addr < end) { |
| 526 | 525 | tlb_flush_page (env, addr); |
| ... | ... | @@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 528 | 527 | } |
| 529 | 528 | } |
| 530 | 529 | if (tlb->V1) { |
| 531 | - addr = tlb->VPN | ((mask >> 1) + 1); | |
| 532 | - addr = tlb->VPN + TARGET_PAGE_SIZE; | |
| 530 | + addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); | |
| 533 | 531 | end = addr | mask; |
| 534 | 532 | while (addr < end) { |
| 535 | 533 | tlb_flush_page (env, addr); | ... | ... |
target-mips/op.c
| ... | ... | @@ -1283,7 +1283,7 @@ void op_mtc0_context (void) |
| 1283 | 1283 | void op_mtc0_pagemask (void) |
| 1284 | 1284 | { |
| 1285 | 1285 | /* 1k pages not implemented */ |
| 1286 | - env->CP0_PageMask = T0 & 0x1FFFE000; | |
| 1286 | + env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1)); | |
| 1287 | 1287 | RETURN(); |
| 1288 | 1288 | } |
| 1289 | 1289 | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx) |
| 390 | 390 | |
| 391 | 391 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
| 392 | 392 | tlb = &env->mmu.r4k.tlb[idx]; |
| 393 | - tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF; | |
| 393 | + tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); | |
| 394 | 394 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
| 395 | 395 | tlb->PageMask = env->CP0_PageMask; |
| 396 | 396 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
| ... | ... | @@ -426,16 +426,21 @@ void r4k_do_tlbwr (void) |
| 426 | 426 | void r4k_do_tlbp (void) |
| 427 | 427 | { |
| 428 | 428 | r4k_tlb_t *tlb; |
| 429 | + target_ulong mask; | |
| 429 | 430 | target_ulong tag; |
| 431 | + target_ulong VPN; | |
| 430 | 432 | uint8_t ASID; |
| 431 | 433 | int i; |
| 432 | 434 | |
| 433 | - tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; | |
| 434 | 435 | ASID = env->CP0_EntryHi & 0xFF; |
| 435 | 436 | for (i = 0; i < env->nb_tlb; i++) { |
| 436 | 437 | tlb = &env->mmu.r4k.tlb[i]; |
| 438 | + /* 1k pages are not supported. */ | |
| 439 | + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); | |
| 440 | + tag = env->CP0_EntryHi & ~mask; | |
| 441 | + VPN = tlb->VPN & ~mask; | |
| 437 | 442 | /* Check ASID, virtual page number & size */ |
| 438 | - if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { | |
| 443 | + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { | |
| 439 | 444 | /* TLB match */ |
| 440 | 445 | env->CP0_Index = i; |
| 441 | 446 | break; |
| ... | ... | @@ -445,9 +450,12 @@ void r4k_do_tlbp (void) |
| 445 | 450 | /* No match. Discard any shadow entries, if any of them match. */ |
| 446 | 451 | for (i = env->nb_tlb; i < env->tlb_in_use; i++) { |
| 447 | 452 | tlb = &env->mmu.r4k.tlb[i]; |
| 448 | - | |
| 453 | + /* 1k pages are not supported. */ | |
| 454 | + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); | |
| 455 | + tag = env->CP0_EntryHi & ~mask; | |
| 456 | + VPN = tlb->VPN & ~mask; | |
| 449 | 457 | /* Check ASID, virtual page number & size */ |
| 450 | - if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { | |
| 458 | + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { | |
| 451 | 459 | r4k_mips_tlb_flush_extra (env, i); |
| 452 | 460 | break; |
| 453 | 461 | } | ... | ... |