aboutsummaryrefslogtreecommitdiff
path: root/target/mips/op_helper.c
diff options
context:
space:
mode:
authorPhilippe Mathieu-Daudé <f4bug@amsat.org>2021-04-13 21:30:40 +0200
committerPhilippe Mathieu-Daudé <f4bug@amsat.org>2021-05-02 16:49:35 +0200
commit6575529b654ffeaebf1b00c53e33c834d68b7c33 (patch)
treef7eb528ca7602880109777e2dadf3ba0e34b7b86 /target/mips/op_helper.c
parentecdbcb0a9450e9109ae3dd6cfa10c71fda753bda (diff)
target/mips: Move TLB management helpers to tcg/sysemu/tlb_helper.c
Move TLB management helpers to tcg/sysemu/tlb_helper.c. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20210428170410.479308-26-f4bug@amsat.org>
Diffstat (limited to 'target/mips/op_helper.c')
-rw-r--r--target/mips/op_helper.c333
1 files changed, 0 insertions, 333 deletions
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index a7fe1de8c4..cb2a7e96fc 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -324,339 +324,6 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
return env->CP0_YQMask;
}
-#ifndef CONFIG_USER_ONLY
-/* TLB management */
-static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first)
-{
- /* Discard entries from env->tlb[first] onwards. */
- while (env->tlb->tlb_in_use > first) {
- r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
- }
-}
-
-static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
-{
-#if defined(TARGET_MIPS64)
- return extract64(entrylo, 6, 54);
-#else
- return extract64(entrylo, 6, 24) | /* PFN */
- (extract64(entrylo, 32, 32) << 24); /* PFNX */
-#endif
-}
-
-static void r4k_fill_tlb(CPUMIPSState *env, int idx)
-{
- r4k_tlb_t *tlb;
- uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1);
-
- /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
- tlb = &env->tlb->mmu.r4k.tlb[idx];
- if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) {
- tlb->EHINV = 1;
- return;
- }
- tlb->EHINV = 0;
- tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
-#if defined(TARGET_MIPS64)
- tlb->VPN &= env->SEGMask;
-#endif
- tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
- tlb->MMID = env->CP0_MemoryMapID;
- tlb->PageMask = env->CP0_PageMask;
- tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
- tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
- tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
- tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
- tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
- tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
- tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12;
- tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
- tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
- tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
- tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
- tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
- tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12;
-}
-
-void r4k_helper_tlbinv(CPUMIPSState *env)
-{
- bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
- uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
- uint32_t MMID = env->CP0_MemoryMapID;
- uint32_t tlb_mmid;
- r4k_tlb_t *tlb;
- int idx;
-
- MMID = mi ? MMID : (uint32_t) ASID;
- for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
- tlb = &env->tlb->mmu.r4k.tlb[idx];
- tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
- if (!tlb->G && tlb_mmid == MMID) {
- tlb->EHINV = 1;
- }
- }
- cpu_mips_tlb_flush(env);
-}
-
-void r4k_helper_tlbinvf(CPUMIPSState *env)
-{
- int idx;
-
- for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
- env->tlb->mmu.r4k.tlb[idx].EHINV = 1;
- }
- cpu_mips_tlb_flush(env);
-}
-
-void r4k_helper_tlbwi(CPUMIPSState *env)
-{
- bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
- target_ulong VPN;
- uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
- uint32_t MMID = env->CP0_MemoryMapID;
- uint32_t tlb_mmid;
- bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
- r4k_tlb_t *tlb;
- int idx;
-
- MMID = mi ? MMID : (uint32_t) ASID;
-
- idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
- tlb = &env->tlb->mmu.r4k.tlb[idx];
- VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
-#if defined(TARGET_MIPS64)
- VPN &= env->SEGMask;
-#endif
- 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;
-
- tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
- /*
- * Discard cached TLB entries, unless tlbwi is just upgrading access
- * permissions on the current entry.
- */
- if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G ||
- (!tlb->EHINV && EHINV) ||
- (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
- (!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_invalidate_tlb(env, idx, 0);
- r4k_fill_tlb(env, idx);
-}
-
-void r4k_helper_tlbwr(CPUMIPSState *env)
-{
- int r = cpu_mips_get_random(env);
-
- r4k_invalidate_tlb(env, r, 1);
- r4k_fill_tlb(env, r);
-}
-
-void r4k_helper_tlbp(CPUMIPSState *env)
-{
- bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
- r4k_tlb_t *tlb;
- target_ulong mask;
- target_ulong tag;
- target_ulong VPN;
- uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
- uint32_t MMID = env->CP0_MemoryMapID;
- uint32_t tlb_mmid;
- int i;
-
- MMID = mi ? MMID : (uint32_t) ASID;
- for (i = 0; i < env->tlb->nb_tlb; i++) {
- tlb = &env->tlb->mmu.r4k.tlb[i];
- /* 1k pages are not supported. */
- mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
- tag = env->CP0_EntryHi & ~mask;
- VPN = tlb->VPN & ~mask;
-#if defined(TARGET_MIPS64)
- tag &= env->SEGMask;
-#endif
- tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
- /* Check ASID/MMID, virtual page number & size */
- if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
- /* TLB match */
- env->CP0_Index = i;
- break;
- }
- }
- if (i == env->tlb->nb_tlb) {
- /* No match. Discard any shadow entries, if any of them match. */
- for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
- tlb = &env->tlb->mmu.r4k.tlb[i];
- /* 1k pages are not supported. */
- mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
- tag = env->CP0_EntryHi & ~mask;
- VPN = tlb->VPN & ~mask;
-#if defined(TARGET_MIPS64)
- tag &= env->SEGMask;
-#endif
- tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
- /* Check ASID/MMID, virtual page number & size */
- if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) {
- r4k_mips_tlb_flush_extra(env, i);
- break;
- }
- }
-
- env->CP0_Index |= 0x80000000;
- }
-}
-
-static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
-{
-#if defined(TARGET_MIPS64)
- return tlb_pfn << 6;
-#else
- return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
- (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
-#endif
-}
-
-void r4k_helper_tlbr(CPUMIPSState *env)
-{
- bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
- uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
- uint32_t MMID = env->CP0_MemoryMapID;
- uint32_t tlb_mmid;
- r4k_tlb_t *tlb;
- int idx;
-
- MMID = mi ? MMID : (uint32_t) ASID;
- idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
- tlb = &env->tlb->mmu.r4k.tlb[idx];
-
- tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
- /* If this will change the current ASID/MMID, flush qemu's TLB. */
- if (MMID != tlb_mmid) {
- cpu_mips_tlb_flush(env);
- }
-
- r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
-
- if (tlb->EHINV) {
- env->CP0_EntryHi = 1 << CP0EnHi_EHINV;
- env->CP0_PageMask = 0;
- env->CP0_EntryLo0 = 0;
- env->CP0_EntryLo1 = 0;
- } else {
- env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID;
- env->CP0_MemoryMapID = tlb->MMID;
- env->CP0_PageMask = tlb->PageMask;
- env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
- ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
- ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
- get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
- env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
- ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
- ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
- get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
- }
-}
-
-void helper_tlbwi(CPUMIPSState *env)
-{
- env->tlb->helper_tlbwi(env);
-}
-
-void helper_tlbwr(CPUMIPSState *env)
-{
- env->tlb->helper_tlbwr(env);
-}
-
-void helper_tlbp(CPUMIPSState *env)
-{
- env->tlb->helper_tlbp(env);
-}
-
-void helper_tlbr(CPUMIPSState *env)
-{
- env->tlb->helper_tlbr(env);
-}
-
-void helper_tlbinv(CPUMIPSState *env)
-{
- env->tlb->helper_tlbinv(env);
-}
-
-void helper_tlbinvf(CPUMIPSState *env)
-{
- env->tlb->helper_tlbinvf(env);
-}
-
-static void global_invalidate_tlb(CPUMIPSState *env,
- uint32_t invMsgVPN2,
- uint8_t invMsgR,
- uint32_t invMsgMMid,
- bool invAll,
- bool invVAMMid,
- bool invMMid,
- bool invVA)
-{
-
- int idx;
- r4k_tlb_t *tlb;
- bool VAMatch;
- bool MMidMatch;
-
- for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
- tlb = &env->tlb->mmu.r4k.tlb[idx];
- VAMatch =
- (((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask))
-#ifdef TARGET_MIPS64
- &&
- (extract64(env->CP0_EntryHi, 62, 2) == invMsgR)
-#endif
- );
- MMidMatch = tlb->MMID == invMsgMMid;
- if ((invAll && (idx > env->CP0_Wired)) ||
- (VAMatch && invVAMMid && (tlb->G || MMidMatch)) ||
- (VAMatch && invVA) ||
- (MMidMatch && !(tlb->G) && invMMid)) {
- tlb->EHINV = 1;
- }
- }
- cpu_mips_tlb_flush(env);
-}
-
-void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type)
-{
- bool invAll = type == 0;
- bool invVA = type == 1;
- bool invMMid = type == 2;
- bool invVAMMid = type == 3;
- uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1);
- uint8_t invMsgR = 0;
- uint32_t invMsgMMid = env->CP0_MemoryMapID;
- CPUState *other_cs = first_cpu;
-
-#ifdef TARGET_MIPS64
- invMsgR = extract64(arg, 62, 2);
-#endif
-
- CPU_FOREACH(other_cs) {
- MIPSCPU *other_cpu = MIPS_CPU(other_cs);
- global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid,
- invAll, invVAMMid, invMMid, invVA);
- }
-}
-
-#endif /* !CONFIG_USER_ONLY */
-
static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
{
if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {