qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support


From: Yongbok Kim
Subject: Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
Date: Thu, 16 Oct 2014 11:52:47 +0100
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.1.2

Hi Leon,

As the issues below are all corrected in the PRPL already,

Reviewed-by: Yongbok Kim <address@hidden>

Regards,
Yongbok



On 08/07/2014 08:57, Leon Alrae wrote:
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 <address@hidden>
---
  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)) {

(((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) as you corrected it in PRPL

+        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;

int 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) {

(ctx->ie >= 2)

+            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) {

(ctx->ie >= 2)

+            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;

& 3

      /* 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)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]