summary refs log tree commit diff stats
path: root/target/mips/helper.c
diff options
context:
space:
mode:
authorYongbok Kim <yongbok.kim@mips.com>2019-12-20 10:29:34 +0100
committerAleksandar Markovic <amarkovic@wavecomp.com>2020-01-29 19:28:52 +0100
commit99029be1c2875cd857614397674bbf563ddb6f91 (patch)
tree28c1dde351decde94f717efd13a1db2db8bd561d /target/mips/helper.c
parentfeafe82cc2289a31b3e3f11dc76f3539ea22d670 (diff)
downloadfocaccia-qemu-99029be1c2875cd857614397674bbf563ddb6f91.tar.gz
focaccia-qemu-99029be1c2875cd857614397674bbf563ddb6f91.zip
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 <aleksandar.rikalo@rt-rk.com>
Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Message-Id: <1579883929-1517-5-git-send-email-aleksandar.markovic@rt-rk.com>
Diffstat (limited to 'target/mips/helper.c')
-rw-r--r--target/mips/helper.c20
1 files changed, 16 insertions, 4 deletions
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;
     }