提交 eff6ff94 编写于 作者: J James Hogan 提交者: Yongbok Kim

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.

Fixes: 2fb58b73 ("target-mips: add RI and XI fields to TLB entry")
Fixes: 9456c2fb ("target-mips: add TLBINV support")
Signed-off-by: NJames Hogan <james.hogan@imgtec.com>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: NYongbok Kim <yongbok.kim@imgtec.com>
[yongbok.kim@imgtec.com:
  cosmetic changes]
Signed-off-by: NYongbok Kim <yongbok.kim@imgtec.com>
上级 e40df9a8
...@@ -2029,7 +2029,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env) ...@@ -2029,7 +2029,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
int idx; int idx;
target_ulong VPN; target_ulong VPN;
uint16_t ASID; 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; idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb = &env->tlb->mmu.r4k.tlb[idx];
...@@ -2038,17 +2038,25 @@ void r4k_helper_tlbwi(CPUMIPSState *env) ...@@ -2038,17 +2038,25 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
VPN &= env->SEGMask; VPN &= env->SEGMask;
#endif #endif
ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 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; G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
V0 = (env->CP0_EntryLo0 & 2) != 0; V0 = (env->CP0_EntryLo0 & 2) != 0;
D0 = (env->CP0_EntryLo0 & 4) != 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; V1 = (env->CP0_EntryLo1 & 2) != 0;
D1 = (env->CP0_EntryLo1 & 4) != 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 /* Discard cached TLB entries, unless tlbwi is just upgrading access
permissions on the current entry. */ permissions on the current entry. */
if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G || if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
(!tlb->EHINV && EHINV) ||
(tlb->V0 && !V0) || (tlb->D0 && !D0) || (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); r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册