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,19 +73,18 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, | ||
| 73 | for (i = 0; i < env->tlb_in_use; i++) { | 73 | for (i = 0; i < env->tlb_in_use; i++) { |
| 74 | r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; | 74 | r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; |
| 75 | /* 1k pages are not supported. */ | 75 | /* 1k pages are not supported. */ |
| 76 | - target_ulong mask = tlb->PageMask | 0x1FFF; | 76 | + target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 77 | target_ulong tag = address & ~mask; | 77 | target_ulong tag = address & ~mask; |
| 78 | - int n; | 78 | + target_ulong VPN = tlb->VPN & ~mask; |
| 79 | 79 | ||
| 80 | /* Check ASID, virtual page number & size */ | 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 | /* TLB match */ | 82 | /* TLB match */ |
| 84 | - n = !!(address & mask & ~(mask >> 1)); | 83 | + int n = !!(address & mask & ~(mask >> 1)); |
| 85 | /* Check access rights */ | 84 | /* Check access rights */ |
| 86 | - if (!(n ? tlb->V1 : tlb->V0)) | 85 | + if (!(n ? tlb->V1 : tlb->V0)) |
| 87 | return TLBRET_INVALID; | 86 | return TLBRET_INVALID; |
| 88 | - if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | 87 | + if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { |
| 89 | *physical = tlb->PFN[n] | (address & (mask >> 1)); | 88 | *physical = tlb->PFN[n] | (address & (mask >> 1)); |
| 90 | *prot = PAGE_READ; | 89 | *prot = PAGE_READ; |
| 91 | if (n ? tlb->D1 : tlb->D0) | 90 | if (n ? tlb->D1 : tlb->D0) |
| @@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
| 502 | target_ulong mask; | 501 | target_ulong mask; |
| 503 | 502 | ||
| 504 | tlb = &env->mmu.r4k.tlb[idx]; | 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 | flush these entries again. */ | 505 | flush these entries again. */ |
| 507 | if (tlb->G == 0 && tlb->ASID != ASID) { | 506 | if (tlb->G == 0 && tlb->ASID != ASID) { |
| 508 | return; | 507 | return; |
| @@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
| 518 | } | 517 | } |
| 519 | 518 | ||
| 520 | /* 1k pages are not supported. */ | 519 | /* 1k pages are not supported. */ |
| 521 | - mask = tlb->PageMask | 0x1FFF; | 520 | + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 522 | if (tlb->V0) { | 521 | if (tlb->V0) { |
| 523 | - addr = tlb->VPN; | 522 | + addr = tlb->VPN & ~mask; |
| 524 | end = addr | (mask >> 1); | 523 | end = addr | (mask >> 1); |
| 525 | while (addr < end) { | 524 | while (addr < end) { |
| 526 | tlb_flush_page (env, addr); | 525 | tlb_flush_page (env, addr); |
| @@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
| 528 | } | 527 | } |
| 529 | } | 528 | } |
| 530 | if (tlb->V1) { | 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 | end = addr | mask; | 531 | end = addr | mask; |
| 534 | while (addr < end) { | 532 | while (addr < end) { |
| 535 | tlb_flush_page (env, addr); | 533 | tlb_flush_page (env, addr); |
target-mips/op.c
| @@ -1283,7 +1283,7 @@ void op_mtc0_context (void) | @@ -1283,7 +1283,7 @@ void op_mtc0_context (void) | ||
| 1283 | void op_mtc0_pagemask (void) | 1283 | void op_mtc0_pagemask (void) |
| 1284 | { | 1284 | { |
| 1285 | /* 1k pages not implemented */ | 1285 | /* 1k pages not implemented */ |
| 1286 | - env->CP0_PageMask = T0 & 0x1FFFE000; | 1286 | + env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1)); |
| 1287 | RETURN(); | 1287 | RETURN(); |
| 1288 | } | 1288 | } |
| 1289 | 1289 |
target-mips/op_helper.c
| @@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx) | @@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx) | ||
| 390 | 390 | ||
| 391 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ | 391 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
| 392 | tlb = &env->mmu.r4k.tlb[idx]; | 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 | tlb->ASID = env->CP0_EntryHi & 0xFF; | 394 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
| 395 | tlb->PageMask = env->CP0_PageMask; | 395 | tlb->PageMask = env->CP0_PageMask; |
| 396 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; | 396 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
| @@ -426,16 +426,21 @@ void r4k_do_tlbwr (void) | @@ -426,16 +426,21 @@ void r4k_do_tlbwr (void) | ||
| 426 | void r4k_do_tlbp (void) | 426 | void r4k_do_tlbp (void) |
| 427 | { | 427 | { |
| 428 | r4k_tlb_t *tlb; | 428 | r4k_tlb_t *tlb; |
| 429 | + target_ulong mask; | ||
| 429 | target_ulong tag; | 430 | target_ulong tag; |
| 431 | + target_ulong VPN; | ||
| 430 | uint8_t ASID; | 432 | uint8_t ASID; |
| 431 | int i; | 433 | int i; |
| 432 | 434 | ||
| 433 | - tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; | ||
| 434 | ASID = env->CP0_EntryHi & 0xFF; | 435 | ASID = env->CP0_EntryHi & 0xFF; |
| 435 | for (i = 0; i < env->nb_tlb; i++) { | 436 | for (i = 0; i < env->nb_tlb; i++) { |
| 436 | tlb = &env->mmu.r4k.tlb[i]; | 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 | /* Check ASID, virtual page number & size */ | 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 | /* TLB match */ | 444 | /* TLB match */ |
| 440 | env->CP0_Index = i; | 445 | env->CP0_Index = i; |
| 441 | break; | 446 | break; |
| @@ -445,9 +450,12 @@ void r4k_do_tlbp (void) | @@ -445,9 +450,12 @@ void r4k_do_tlbp (void) | ||
| 445 | /* No match. Discard any shadow entries, if any of them match. */ | 450 | /* No match. Discard any shadow entries, if any of them match. */ |
| 446 | for (i = env->nb_tlb; i < env->tlb_in_use; i++) { | 451 | for (i = env->nb_tlb; i < env->tlb_in_use; i++) { |
| 447 | tlb = &env->mmu.r4k.tlb[i]; | 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 | /* Check ASID, virtual page number & size */ | 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 | r4k_mips_tlb_flush_extra (env, i); | 459 | r4k_mips_tlb_flush_extra (env, i); |
| 452 | break; | 460 | break; |
| 453 | } | 461 | } |