From 99029be1c2875cd857614397674bbf563ddb6f91 Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Fri, 20 Dec 2019 10:29:34 +0100 Subject: target/mips: Add implementation of GINVT instruction Implement emulation of GINVT instruction. As QEMU doesn't support caches and virtualization, this implementation covers only one instruction (GINVT - Global Invalidate TLB) among all TLB-related MIPS instructions. Reviewed-by: Aleksandar Rikalo Signed-off-by: Yongbok Kim Signed-off-by: Aleksandar Markovic Message-Id: <1579883929-1517-5-git-send-email-aleksandar.markovic@rt-rk.com> --- target/mips/helper.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'target/mips/helper.c') diff --git a/target/mips/helper.c b/target/mips/helper.c index 781930a7dd..afd78b1990 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -72,8 +72,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID = env->CP0_MemoryMapID; + bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); + uint32_t tlb_mmid; int i; + MMID = mi ? MMID : (uint32_t) ASID; + for (i = 0; i < env->tlb->tlb_in_use; i++) { r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; /* 1k pages are not supported. */ @@ -84,8 +89,9 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, tag &= env->SEGMask; #endif - /* Check ASID, virtual page number & size */ - if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { + /* Check ASID/MMID, virtual page number & size */ + tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; + if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) { /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ @@ -1418,14 +1424,20 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra) target_ulong addr; target_ulong end; uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID = env->CP0_MemoryMapID; + bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); + uint32_t tlb_mmid; target_ulong mask; + MMID = mi ? MMID : (uint32_t) ASID; + tlb = &env->tlb->mmu.r4k.tlb[idx]; /* - * The qemu TLB is flushed when the ASID changes, so no need to + * The qemu TLB is flushed when the ASID/MMID changes, so no need to * flush these entries again. */ - if (tlb->G == 0 && tlb->ASID != ASID) { + tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; + if (tlb->G == 0 && tlb_mmid != MMID) { return; } -- cgit 1.4.1