Commit 3b1c8be4f4f1b5d4114320aaf41ec4872ab4598c
1 parent
c281868e
Fix PageMask handling, second part.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2345 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
36 additions
and
16 deletions
target-mips/cpu.h
target-mips/helper.c
| ... | ... | @@ -41,23 +41,26 @@ enum { |
| 41 | 41 | static int map_address (CPUState *env, target_ulong *physical, int *prot, |
| 42 | 42 | target_ulong address, int rw, int access_type) |
| 43 | 43 | { |
| 44 | - target_ulong tag = address & (TARGET_PAGE_MASK << 1); | |
| 45 | - uint8_t ASID = env->CP0_EntryHi & 0xFF; | |
| 46 | - tlb_t *tlb; | |
| 47 | - int i, n; | |
| 44 | + int i; | |
| 48 | 45 | |
| 49 | 46 | for (i = 0; i < env->tlb_in_use; i++) { |
| 50 | - tlb = &env->tlb[i]; | |
| 47 | + tlb_t *tlb = &env->tlb[i]; | |
| 48 | + /* 1k pages are not supported. */ | |
| 49 | + uint8_t ASID = env->CP0_EntryHi & 0xFF; | |
| 50 | + target_ulong mask = tlb->PageMask | 0x1FFF; | |
| 51 | + target_ulong tag = address & ~mask; | |
| 52 | + int n; | |
| 53 | + | |
| 51 | 54 | /* Check ASID, virtual page number & size */ |
| 52 | 55 | if ((tlb->G == 1 || tlb->ASID == ASID) && |
| 53 | 56 | tlb->VPN == tag) { |
| 54 | 57 | /* TLB match */ |
| 55 | - n = (address >> TARGET_PAGE_BITS) & 1; | |
| 58 | + n = !!(address & mask & ~(mask >> 1)); | |
| 56 | 59 | /* Check access rights */ |
| 57 | 60 | if (!(n ? tlb->V1 : tlb->V0)) |
| 58 | 61 | return TLBRET_INVALID; |
| 59 | 62 | if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { |
| 60 | - *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK); | |
| 63 | + *physical = tlb->PFN[n] | (address & (mask >> 1)); | |
| 61 | 64 | *prot = PAGE_READ; |
| 62 | 65 | if (n ? tlb->D1 : tlb->D0) |
| 63 | 66 | *prot |= PAGE_WRITE; |
| ... | ... | @@ -420,9 +423,10 @@ void do_interrupt (CPUState *env) |
| 420 | 423 | void invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 421 | 424 | { |
| 422 | 425 | tlb_t *tlb; |
| 423 | - uint8_t ASID; | |
| 424 | - | |
| 425 | - ASID = env->CP0_EntryHi & 0xFF; | |
| 426 | + target_ulong addr; | |
| 427 | + target_ulong end; | |
| 428 | + uint8_t ASID = env->CP0_EntryHi & 0xFF; | |
| 429 | + target_ulong mask; | |
| 426 | 430 | |
| 427 | 431 | tlb = &env->tlb[idx]; |
| 428 | 432 | /* The qemu TLB is flushed then the ASID changes, so no need to |
| ... | ... | @@ -440,8 +444,23 @@ void invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 440 | 444 | return; |
| 441 | 445 | } |
| 442 | 446 | |
| 443 | - if (tlb->V0) | |
| 444 | - tlb_flush_page (env, tlb->VPN); | |
| 445 | - if (tlb->V1) | |
| 446 | - tlb_flush_page (env, tlb->VPN + TARGET_PAGE_SIZE); | |
| 447 | + /* 1k pages are not supported. */ | |
| 448 | + mask = tlb->PageMask | 0x1FFF; | |
| 449 | + if (tlb->V0) { | |
| 450 | + addr = tlb->VPN; | |
| 451 | + end = addr | (mask >> 1); | |
| 452 | + while (addr < end) { | |
| 453 | + tlb_flush_page (env, addr); | |
| 454 | + addr += TARGET_PAGE_SIZE; | |
| 455 | + } | |
| 456 | + } | |
| 457 | + if (tlb->V1) { | |
| 458 | + addr = tlb->VPN | ((mask >> 1) + 1); | |
| 459 | + addr = tlb->VPN + TARGET_PAGE_SIZE; | |
| 460 | + end = addr | mask; | |
| 461 | + while (addr < end) { | |
| 462 | + tlb_flush_page (env, addr); | |
| 463 | + addr += TARGET_PAGE_SIZE; | |
| 464 | + } | |
| 465 | + } | |
| 447 | 466 | } | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -392,6 +392,7 @@ static void fill_tlb (int idx) |
| 392 | 392 | tlb = &env->tlb[idx]; |
| 393 | 393 | tlb->VPN = env->CP0_EntryHi & (int32_t)0xFFFFE000; |
| 394 | 394 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
| 395 | + tlb->PageMask = env->CP0_PageMask; | |
| 395 | 396 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
| 396 | 397 | tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; |
| 397 | 398 | tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; |
| ... | ... | @@ -473,6 +474,7 @@ void do_tlbr (void) |
| 473 | 474 | mips_tlb_flush_extra(env, MIPS_TLB_NB); |
| 474 | 475 | |
| 475 | 476 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
| 477 | + env->CP0_PageMask = tlb->PageMask; | |
| 476 | 478 | env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | |
| 477 | 479 | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); |
| 478 | 480 | env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | | ... | ... |