All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leon Alrae <leon.alrae@imgtec.com>
To: qemu-devel@nongnu.org
Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com,
	leon.alrae@imgtec.com, aurelien@aurel32.net
Subject: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
Date: Tue, 8 Jul 2014 08:57:35 +0100	[thread overview]
Message-ID: <1404806257-28048-8-git-send-email-leon.alrae@imgtec.com> (raw)
In-Reply-To: <1404806257-28048-1-git-send-email-leon.alrae@imgtec.com>

For Standard TLB configuration (Config.MT=1):

TLBINV invalidates a set of TLB entries based on ASID. The virtual address is
ignored in the entry match. TLB entries which have their G bit set to 1 are not
modified.

TLBINVF causes all entries to be invalidated.

Note that this commit introduces support for Config4.IE == 3 only (i.e. TLBINV*
instructions operate on entire MMU).

Single TLB entry can be marked as invalid on TLB entry write by having
EntryHi.EHINV set to 1.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 disas/mips.c                 |    2 +
 target-mips/cpu.h            |    7 ++++
 target-mips/helper.c         |    2 +-
 target-mips/helper.h         |    2 +
 target-mips/op_helper.c      |   65 +++++++++++++++++++++++++++++++++++++----
 target-mips/translate.c      |   22 ++++++++++++++
 target-mips/translate_init.c |    2 +
 7 files changed, 94 insertions(+), 8 deletions(-)

diff --git a/disas/mips.c b/disas/mips.c
index e3e253f..ff2e4b3 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -2410,6 +2410,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"tlbp",    "",         0x42000008, 0xffffffff, INSN_TLB,       	0,		I1   	},
 {"tlbr",    "",         0x42000001, 0xffffffff, INSN_TLB,       	0,		I1   	},
 {"tlbwi",   "",         0x42000002, 0xffffffff, INSN_TLB,       	0,		I1   	},
+{"tlbinv",  "",         0x42000003, 0xffffffff, INSN_TLB,             0, I32  },
+{"tlbinvf", "",         0x42000004, 0xffffffff, INSN_TLB,             0, I32  },
 {"tlbwr",   "",         0x42000006, 0xffffffff, INSN_TLB,       	0,		I1   	},
 {"tlti",    "s,j",	0x040a0000, 0xfc1f0000,	RD_s|TRAP,		0,		I2	},
 {"tlt",     "s,t",	0x00000032, 0xfc00ffff, RD_s|RD_t|TRAP,		0,		I2	},
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 40ebca6..bc52222 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -34,6 +34,7 @@ struct r4k_tlb_t {
     uint_fast16_t XI1:1;
     uint_fast16_t RI0:1;
     uint_fast16_t RI1:1;
+    uint_fast16_t EHINV:1;
     target_ulong PFN[2];
 };
 
@@ -47,6 +48,8 @@ struct CPUMIPSTLBContext {
     void (*helper_tlbwr)(struct CPUMIPSState *env);
     void (*helper_tlbp)(struct CPUMIPSState *env);
     void (*helper_tlbr)(struct CPUMIPSState *env);
+    void (*helper_tlbinv)(struct CPUMIPSState *env);
+    void (*helper_tlbinvf)(struct CPUMIPSState *env);
     union {
         struct {
             r4k_tlb_t tlb[MIPS_TLB_MAX];
@@ -282,6 +285,7 @@ struct CPUMIPSState {
     target_ulong CP0_BadVAddr;
     int32_t CP0_Count;
     target_ulong CP0_EntryHi;
+#define CP0EnHi_EHINV 10
     int32_t CP0_Compare;
     int32_t CP0_Status;
 #define CP0St_CU3   31
@@ -393,6 +397,7 @@ struct CPUMIPSState {
     uint32_t CP0_Config4;
     uint32_t CP0_Config4_rw_bitmask;
 #define CP0C4_M    31
+#define CP0C4_IE   29
 #define CP0C4_KScrExist 16
     uint32_t CP0_Config5;
     uint32_t CP0_Config5_rw_bitmask;
@@ -528,6 +533,8 @@ void r4k_helper_tlbwi(CPUMIPSState *env);
 void r4k_helper_tlbwr(CPUMIPSState *env);
 void r4k_helper_tlbp(CPUMIPSState *env);
 void r4k_helper_tlbr(CPUMIPSState *env);
+void r4k_helper_tlbinv(CPUMIPSState *env);
+void r4k_helper_tlbinvf(CPUMIPSState *env);
 
 void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
                                 bool is_write, bool is_exec, int unused,
diff --git a/target-mips/helper.c b/target-mips/helper.c
index fed28b4..5d72438 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -83,7 +83,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
 #endif
 
         /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
+        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
             /* TLB match */
             int n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
diff --git a/target-mips/helper.h b/target-mips/helper.h
index e7e0c8c..aea12a9 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -342,6 +342,8 @@ DEF_HELPER_1(tlbwi, void, env)
 DEF_HELPER_1(tlbwr, void, env)
 DEF_HELPER_1(tlbp, void, env)
 DEF_HELPER_1(tlbr, void, env)
+DEF_HELPER_1(tlbinv, void, env)
+DEF_HELPER_1(tlbinvf, void, env)
 DEF_HELPER_1(di, tl, env)
 DEF_HELPER_1(ei, tl, env)
 DEF_HELPER_1(eret, void, env)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 3579bde..fa96bb3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1361,10 +1361,14 @@ void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
 
 void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
 {
-    target_ulong old, val;
+    target_ulong old, val, mask;
+    mask = (TARGET_PAGE_MASK << 1) | 0xFF;
+    if (env->CP0_Config4 & (1 << CP0C4_IE)) {
+        mask |= 1 << CP0EnHi_EHINV;
+    }
 
     /* 1k pages not implemented */
-    val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
+    val = arg1 & mask;
 #if defined(TARGET_MIPS64)
     val &= env->SEGMask;
 #endif
@@ -1858,6 +1862,11 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
 
     /* 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;
@@ -1879,6 +1888,31 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
     tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
 }
 
+void r4k_helper_tlbinv(CPUMIPSState *env)
+{
+    int idx;
+    r4k_tlb_t *tlb;
+    uint8_t ASID = env->CP0_EntryHi & 0xFF;
+
+    for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
+        tlb = &env->tlb->mmu.r4k.tlb[idx];
+        if (!tlb->G && tlb->ASID == ASID) {
+            tlb->EHINV = 1;
+        }
+    }
+    cpu_mips_tlb_flush(env, 1);
+}
+
+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, 1);
+}
+
 void r4k_helper_tlbwi(CPUMIPSState *env)
 {
     r4k_tlb_t *tlb;
@@ -1940,7 +1974,7 @@ void r4k_helper_tlbp(CPUMIPSState *env)
         tag &= env->SEGMask;
 #endif
         /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
+        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
             /* TLB match */
             env->CP0_Index = i;
             break;
@@ -1984,16 +2018,23 @@ void r4k_helper_tlbr(CPUMIPSState *env)
 
     r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
 
-    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
-    env->CP0_PageMask = tlb->PageMask;
-    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
+    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 = tlb->VPN | tlb->ASID;
+        env->CP0_PageMask = tlb->PageMask;
+        env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                         ((target_ulong)tlb->RI0 << CP0EnLo_RI) |
                         ((target_ulong)tlb->XI0 << CP0EnLo_XI) |
                         (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
-    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
+        env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
                         ((target_ulong)tlb->RI1 << CP0EnLo_RI) |
                         ((target_ulong)tlb->XI1 << CP0EnLo_XI) |
                         (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
+    }
 }
 
 void helper_tlbwi(CPUMIPSState *env)
@@ -2016,6 +2057,16 @@ 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);
+}
+
 /* Specials */
 target_ulong helper_di(CPUMIPSState *env)
 {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index a8c8318..4179fea 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -901,6 +901,8 @@ enum {
 enum {
     OPC_TLBR     = 0x01 | OPC_C0,
     OPC_TLBWI    = 0x02 | OPC_C0,
+    OPC_TLBINV   = 0x03 | OPC_C0,
+    OPC_TLBINVF  = 0x04 | OPC_C0,
     OPC_TLBWR    = 0x06 | OPC_C0,
     OPC_TLBP     = 0x08 | OPC_C0,
     OPC_RFE      = 0x10 | OPC_C0,
@@ -1177,6 +1179,7 @@ typedef struct DisasContext {
     bool ulri;
     int kscrexist;
     bool rxi;
+    bool ie;
 } DisasContext;
 
 enum {
@@ -7560,6 +7563,24 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
             goto die;
         gen_helper_tlbwi(cpu_env);
         break;
+    case OPC_TLBINV:
+        opn = "tlbinv";
+        if (ctx->ie) {
+            if (!env->tlb->helper_tlbinv) {
+                goto die;
+            }
+            gen_helper_tlbinv(cpu_env);
+        } /* treat as nop if TLBINV not supported */
+        break;
+    case OPC_TLBINVF:
+        opn = "tlbinvf";
+        if (ctx->ie) {
+            if (!env->tlb->helper_tlbinvf) {
+                goto die;
+            }
+            gen_helper_tlbinvf(cpu_env);
+        } /* treat as nop if TLBINV not supported */
+        break;
     case OPC_TLBWR:
         opn = "tlbwr";
         if (!env->tlb->helper_tlbwr)
@@ -17554,6 +17575,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.bstate = BS_NONE;
     ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
     ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
+    ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 1;
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 779afff..bcfc46a 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -657,6 +657,8 @@ static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def)
     env->tlb->helper_tlbwr = r4k_helper_tlbwr;
     env->tlb->helper_tlbp = r4k_helper_tlbp;
     env->tlb->helper_tlbr = r4k_helper_tlbr;
+    env->tlb->helper_tlbinv = r4k_helper_tlbinv;
+    env->tlb->helper_tlbinvf = r4k_helper_tlbinvf;
 }
 
 static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
-- 
1.7.5.4

  parent reply	other threads:[~2014-07-08  7:58 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers Leon Alrae
2014-10-14 13:59   ` Yongbok Kim
2014-10-20 12:54     ` Leon Alrae
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum Leon Alrae
2014-07-08 13:00   ` Peter Maydell
2014-07-08 16:08     ` Leon Alrae
2014-07-08 16:12       ` Peter Maydell
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch Leon Alrae
2014-10-14 15:55   ` Yongbok Kim
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry Leon Alrae
2014-10-15 12:24   ` Yongbok Kim
2014-10-24 14:16     ` Leon Alrae
2014-10-24 14:27       ` Yongbok Kim
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 5/9] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1} Leon Alrae
2014-10-15 15:20   ` Yongbok Kim
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 6/9] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions Leon Alrae
2014-10-15 15:39   ` Yongbok Kim
2014-07-08  7:57 ` Leon Alrae [this message]
2014-10-16 10:52   ` [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support Yongbok Kim
2014-10-16 13:03     ` Leon Alrae
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support Leon Alrae
2014-07-08 12:44   ` James Hogan
2014-07-08 15:56     ` Leon Alrae
2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 9/9] target-mips: update cpu_save/cpu_load to support new registers Leon Alrae
2014-10-16 13:06   ` Yongbok Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1404806257-28048-8-git-send-email-leon.alrae@imgtec.com \
    --to=leon.alrae@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=cristian.cuna@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    --cc=yongbok.kim@imgtec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.