mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 14:15:39 +00:00
target/mips: Fix TLBWI shadow flush for EHINV,XI,RI
Writing specific TLB entries with TLBWI flushes shadow TLB entries unless an existing entry is having its access permissions upgraded. This is necessary as software would from then on expect the previous mapping in that entry to no longer be in effect (even if QEMU has quietly evicted it to the shadow TLB on a TLBWR). However it won't do this if only EHINV, XI, or RI bits have been set, even if that results in a reduction of permissions, so add the necessary checks to invoke the flush when these bits are set. Backports commit eff6ff9431aa9776062a5f4a08d1f6503ca9995a from qemu
This commit is contained in:
parent
fe0de45a26
commit
310e3f0a1d
|
@ -2007,7 +2007,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
|
|||
int idx;
|
||||
target_ulong VPN;
|
||||
uint16_t ASID;
|
||||
bool G, V0, D0, V1, D1;
|
||||
bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
|
||||
|
||||
idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
|
||||
tlb = &env->tlb->mmu.r4k.tlb[idx];
|
||||
|
@ -2016,17 +2016,25 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
|
|||
VPN &= env->SEGMask;
|
||||
#endif
|
||||
ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
|
||||
EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
|
||||
G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
|
||||
V0 = (env->CP0_EntryLo0 & 2) != 0;
|
||||
D0 = (env->CP0_EntryLo0 & 4) != 0;
|
||||
XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1;
|
||||
RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1;
|
||||
V1 = (env->CP0_EntryLo1 & 2) != 0;
|
||||
D1 = (env->CP0_EntryLo1 & 4) != 0;
|
||||
XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
|
||||
RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
|
||||
|
||||
/* Discard cached TLB entries, unless tlbwi is just upgrading access
|
||||
permissions on the current entry. */
|
||||
if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
|
||||
(!tlb->EHINV && EHINV) ||
|
||||
(tlb->V0 && !V0) || (tlb->D0 && !D0) ||
|
||||
(tlb->V1 && !V1) || (tlb->D1 && !D1)) {
|
||||
(!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
|
||||
(tlb->V1 && !V1) || (tlb->D1 && !D1) ||
|
||||
(!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
|
||||
r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue