mirror of https://github.com/xqemu/xqemu.git
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
This commit is contained in:
parent
df628ff14e
commit
2ee4aed86f
|
@ -149,6 +149,7 @@ void dump_sc (void);
|
||||||
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||||
int is_user, int is_softmmu);
|
int is_user, int is_softmmu);
|
||||||
void do_interrupt (CPUState *env);
|
void do_interrupt (CPUState *env);
|
||||||
|
void invalidate_tlb (CPUState *env, int idx, int use_extra);
|
||||||
|
|
||||||
void cpu_loop_exit(void);
|
void cpu_loop_exit(void);
|
||||||
void do_raise_exception_err (uint32_t exception, int error_code);
|
void do_raise_exception_err (uint32_t exception, int error_code);
|
||||||
|
|
|
@ -416,3 +416,44 @@ void do_interrupt (CPUState *env)
|
||||||
env->exception_index = EXCP_NONE;
|
env->exception_index = EXCP_NONE;
|
||||||
}
|
}
|
||||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -376,53 +376,11 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global)
|
||||||
env->tlb_in_use = MIPS_TLB_NB;
|
env->tlb_in_use = MIPS_TLB_NB;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invalidate_tlb (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) {
|
|
||||||
tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN);
|
|
||||||
addr = tlb->VPN;
|
|
||||||
while (addr < tlb->end) {
|
|
||||||
tlb_flush_page (env, addr);
|
|
||||||
addr += TARGET_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tlb->V1) {
|
|
||||||
tb_invalidate_page_range(tlb->PFN[1], tlb->end2 - tlb->end);
|
|
||||||
addr = tlb->end;
|
|
||||||
while (addr < tlb->end2) {
|
|
||||||
tlb_flush_page (env, addr);
|
|
||||||
addr += TARGET_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mips_tlb_flush_extra (CPUState *env, int first)
|
static void mips_tlb_flush_extra (CPUState *env, int first)
|
||||||
{
|
{
|
||||||
/* Discard entries from env->tlb[first] onwards. */
|
/* Discard entries from env->tlb[first] onwards. */
|
||||||
while (env->tlb_in_use > first) {
|
while (env->tlb_in_use > first) {
|
||||||
invalidate_tlb(--env->tlb_in_use, 0);
|
invalidate_tlb(env, --env->tlb_in_use, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +417,7 @@ void do_tlbwi (void)
|
||||||
|
|
||||||
/* Wildly undefined effects for CP0_index containing a too high value and
|
/* Wildly undefined effects for CP0_index containing a too high value and
|
||||||
MIPS_TLB_NB not being a power of two. But so does real silicon. */
|
MIPS_TLB_NB not being a power of two. But so does real silicon. */
|
||||||
invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1), 0);
|
invalidate_tlb(env, env->CP0_index & (MIPS_TLB_NB - 1), 0);
|
||||||
fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
|
fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +425,7 @@ void do_tlbwr (void)
|
||||||
{
|
{
|
||||||
int r = cpu_mips_get_random(env);
|
int r = cpu_mips_get_random(env);
|
||||||
|
|
||||||
invalidate_tlb(r, 1);
|
invalidate_tlb(env, r, 1);
|
||||||
fill_tlb(r);
|
fill_tlb(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue