diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-01-03 15:18:08 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-01-03 15:18:08 +0000 |
commit | 2ee4aed86ff2ba38a0e1846de18a9aec38d73015 (patch) | |
tree | 45bc5a10e2ec58f11fa58cc7d0b1c0611206add6 /target-mips/helper.c | |
parent | df628ff14eeb825eafbf820ea71b09b8d9434029 (diff) |
moved invalidate_tlb() to helper.c as a work around for gcc 3.2.2 bug - suppressed invalid tb_invalidate_page_range() calls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2287 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r-- | target-mips/helper.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c index e70dc1a99e..43038c2d7e 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -416,3 +416,44 @@ void do_interrupt (CPUState *env) env->exception_index = EXCP_NONE; } #endif /* !defined(CONFIG_USER_ONLY) */ + +void invalidate_tlb (CPUState *env, int idx, int use_extra) +{ + tlb_t *tlb; + target_ulong addr; + uint8_t ASID; + + ASID = env->CP0_EntryHi & 0xFF; + + tlb = &env->tlb[idx]; + /* The qemu TLB is flushed then the ASID changes, so no need to + flush these entries again. */ + if (tlb->G == 0 && tlb->ASID != ASID) { + return; + } + + if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) { + /* For tlbwr, we can shadow the discarded entry into + a new (fake) TLB entry, as long as the guest can not + tell that it's there. */ + env->tlb[env->tlb_in_use] = *tlb; + env->tlb_in_use++; + return; + } + + if (tlb->V0) { + addr = tlb->VPN; + while (addr < tlb->end) { + tlb_flush_page (env, addr); + addr += TARGET_PAGE_SIZE; + } + } + if (tlb->V1) { + addr = tlb->end; + while (addr < tlb->end2) { + tlb_flush_page (env, addr); + addr += TARGET_PAGE_SIZE; + } + } +} + |