All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6
@ 2014-07-08  7:57 Leon Alrae
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers Leon Alrae
                   ` (8 more replies)
  0 siblings, 9 replies; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

This patch series implement set of features whose presence became mandatory in
MIPS64R6:
- KScratch registers,
- Read-Inhibit and Execute-Inhibit page protection bits,
- TLB Invalidate (TLBINV and TLBINVF instructions),
- BadInstr and BadInstrP.
This series should be applied on the top of pending patches introducing
MIPS64R6 Instruction Set.

Commits briefly describe each feature. For more details please refer to the
Volume III (The MIPS64 and microMIPS64 Privileged Resource Architecture) and
Volume II (The MIPS64 Instruction Set) of MIPS documents available at:
http://www.imgtec.com/mips/architectures/mips64.asp

This patchset focuses on features which existed before Release 6. It does not
contain new MIPS64R6 features like forbidden slot, SBRI, reserved fields.
This will come as a separate patchset soon.

Any comments / suggestions are more than welcome!

Thanks,
Leon

v2:
* changed BadInstr implementation - fetching instruction word instead of
  generating code to save the last instruction,
* dropped patch updating cpu configuration - this will be done later, when all
  the required features are implemented,
* modified mtc0 and mfc0 to behave like on the real HW when referring to
  an unimplemented cp0 register (new registers only)
* updated CPU_SAVE_VERSION,
* added a patch to the series providing mmu_access_type enum.

Leon Alrae (9):
  target-mips: add KScratch registers
  softmmu: provide softmmu access type enum
  target-mips: distinguish between data load and instruction fetch
  target-mips: add RI and XI fields to TLB entry
  target-mips: update PageGrain and m{t,f}c0 EntryLo{0,1}
  target-mips: add new Read-Inhibit and Execute-Inhibit exceptions
  target-mips: add TLBINV support
  target-mips: add BadInstr and BadInstrP support
  target-mips: update cpu_save/cpu_load to support new registers

 disas/mips.c                 |    2 +
 include/exec/cpu-common.h    |    6 ++
 softmmu_template.h           |   26 ++++---
 target-mips/cpu.h            |   38 +++++++++-
 target-mips/helper.c         |  103 +++++++++++++++++++++----
 target-mips/helper.h         |    7 ++
 target-mips/machine.c        |   14 ++++
 target-mips/op_helper.c      |  115 +++++++++++++++++++++++++---
 target-mips/translate.c      |  172 ++++++++++++++++++++++++++++++++++++++++--
 target-mips/translate_init.c |    4 +
 10 files changed, 438 insertions(+), 49 deletions(-)

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers
  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 ` Leon Alrae
  2014-10-14 13:59   ` Yongbok Kim
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum Leon Alrae
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

KScratch<n> Registers (CP0 Register 31, Selects 2 to 7)

The KScratch registers are read/write registers available for scratch pad
storage by kernel mode software. They are 32-bits in width for 32-bit
processors and 64-bits for 64-bit processors.

CP0Config4.KScrExist[2:7] bits indicate presence of CP0_KScratch1-6 registers.
For Release 6, all KScratch registers are required.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |    3 +++
 target-mips/translate.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 51a8331..4f6aa5b 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -136,6 +136,7 @@ typedef struct mips_def_t mips_def_t;
 #define MIPS_TC_MAX 5
 #define MIPS_FPU_MAX 1
 #define MIPS_DSP_ACC 4
+#define MIPS_KSCRATCH_NUM 6
 
 typedef struct TCState TCState;
 struct TCState {
@@ -229,6 +230,7 @@ struct CPUMIPSState {
     target_ulong CP0_EntryLo0;
     target_ulong CP0_EntryLo1;
     target_ulong CP0_Context;
+    target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
     int32_t CP0_PageMask;
     int32_t CP0_PageGrain;
     int32_t CP0_Wired;
@@ -375,6 +377,7 @@ struct CPUMIPSState {
     uint32_t CP0_Config4;
     uint32_t CP0_Config4_rw_bitmask;
 #define CP0C4_M    31
+#define CP0C4_KScrExist 16
     uint32_t CP0_Config5;
     uint32_t CP0_Config5_rw_bitmask;
 #define CP0C5_M          31
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 6956fdd..ee18bf3 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1175,6 +1175,7 @@ typedef struct DisasContext {
     int bstate;
     target_ulong btarget;
     bool ulri;
+    int kscrexist;
 } DisasContext;
 
 enum {
@@ -4611,6 +4612,15 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
+static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
+{
+    if (ctx->insn_flags & ISA_MIPS32R6) {
+        tcg_gen_movi_tl(arg, 0);
+    } else {
+        tcg_gen_movi_tl(arg, ~0);
+    }
+}
+
 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
@@ -5193,6 +5203,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_ld_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                tcg_gen_ext32s_tl(arg, arg);
+                rn = "KScratch";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
         default:
             goto die;
         }
@@ -5801,6 +5821,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                rn = "KScratch";
+            }
+            break;
         default:
             goto die;
         }
@@ -6388,6 +6415,15 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_ld_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                rn = "KScratch";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
         default:
             goto die;
         }
@@ -6987,6 +7023,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                rn = "KScratch";
+            }
+            break;
         default:
             goto die;
         }
@@ -17490,6 +17533,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.CP0_Config1 = env->CP0_Config1;
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
+    ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
     /* 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);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum
  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-07-08  7:57 ` Leon Alrae
  2014-07-08 13:00   ` Peter Maydell
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch Leon Alrae
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

New MIPS features depend on the access type and enum is more convenient than
using the numbers directly.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 include/exec/cpu-common.h |    6 ++++++
 softmmu_template.h        |   26 ++++++++++++++++----------
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index e3ec4c8..1c3171a 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -26,6 +26,12 @@ typedef struct CPUListState {
     FILE *file;
 } CPUListState;
 
+enum mmu_access_type {
+    MMU_DATA_LOAD  = 0,
+    MMU_DATA_STORE = 1,
+    MMU_INST_FETCH = 2
+};
+
 #if !defined(CONFIG_USER_ONLY)
 
 enum device_endian {
diff --git a/softmmu_template.h b/softmmu_template.h
index 5a07f99..858bf6b 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -67,10 +67,10 @@
 #endif
 
 #ifdef SOFTMMU_CODE_ACCESS
-#define READ_ACCESS_TYPE 2
+#define READ_ACCESS_TYPE MMU_INST_FETCH
 #define ADDR_READ addr_code
 #else
-#define READ_ACCESS_TYPE 0
+#define READ_ACCESS_TYPE MMU_DATA_LOAD
 #define ADDR_READ addr_read
 #endif
 
@@ -365,10 +365,11 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0) {
-            cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                                 mmu_idx, retaddr);
         }
 #endif
-        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
         tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
     }
 
@@ -394,7 +395,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
         int i;
     do_unaligned_access:
 #ifdef ALIGNED_ONLY
-        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                             mmu_idx, retaddr);
 #endif
         /* XXX: not efficient, but simple */
         /* Note: relies on the fact that tlb_fill() does not remove the
@@ -413,7 +415,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
     /* Handle aligned access or unaligned access in the same page.  */
 #ifdef ALIGNED_ONLY
     if ((addr & (DATA_SIZE - 1)) != 0) {
-        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                             mmu_idx, retaddr);
     }
 #endif
 
@@ -441,10 +444,11 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0) {
-            cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                                 mmu_idx, retaddr);
         }
 #endif
-        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
         tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
     }
 
@@ -470,7 +474,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
         int i;
     do_unaligned_access:
 #ifdef ALIGNED_ONLY
-        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                             mmu_idx, retaddr);
 #endif
         /* XXX: not efficient, but simple */
         /* Note: relies on the fact that tlb_fill() does not remove the
@@ -489,7 +494,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
     /* Handle aligned access or unaligned access in the same page.  */
 #ifdef ALIGNED_ONLY
     if ((addr & (DATA_SIZE - 1)) != 0) {
-        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+                             mmu_idx, retaddr);
     }
 #endif
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch
  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-07-08  7:57 ` [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum Leon Alrae
@ 2014-07-08  7:57 ` 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
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien


Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/helper.c |   21 ++++++++++-----------
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 8a997e4..9871273 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -87,7 +87,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
             /* Check access rights */
             if (!(n ? tlb->V1 : tlb->V0))
                 return TLBRET_INVALID;
-            if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
+            if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
                 *physical = tlb->PFN[n] | (address & (mask >> 1));
                 *prot = PAGE_READ;
                 if (n ? tlb->D1 : tlb->D0)
@@ -237,25 +237,28 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
     case TLBRET_BADADDR:
         /* Reference to kernel address from user mode or supervisor mode */
         /* Reference to supervisor address from user mode */
-        if (rw)
+        if (rw == MMU_DATA_STORE) {
             exception = EXCP_AdES;
-        else
+        } else {
             exception = EXCP_AdEL;
+        }
         break;
     case TLBRET_NOMATCH:
         /* No TLB match for a mapped address */
-        if (rw)
+        if (rw == MMU_DATA_STORE) {
             exception = EXCP_TLBS;
-        else
+        } else {
             exception = EXCP_TLBL;
+        }
         error_code = 1;
         break;
     case TLBRET_INVALID:
         /* TLB match with no valid bit */
-        if (rw)
+        if (rw == MMU_DATA_STORE) {
             exception = EXCP_TLBS;
-        else
+        } else {
             exception = EXCP_TLBL;
+        }
         break;
     case TLBRET_DIRTY:
         /* TLB match but 'D' bit is cleared */
@@ -312,8 +315,6 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
     qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
               __func__, env->active_tc.PC, address, rw, mmu_idx);
 
-    rw &= 1;
-
     /* data access */
 #if !defined(CONFIG_USER_ONLY)
     /* XXX: put correct access by using cpu_restore_state()
@@ -347,8 +348,6 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
     int access_type;
     int ret = 0;
 
-    rw &= 1;
-
     /* data access */
     access_type = ACCESS_INT;
     ret = get_physical_address(env, &physical, &prot,
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (2 preceding siblings ...)
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch Leon Alrae
@ 2014-07-08  7:57 ` Leon Alrae
  2014-10-15 12:24   ` 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
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

In Revision 3 of the architecture, the RI and XI bits were added to the TLB
to enable more secure access of memory pages. These bits (along with the Dirty
bit) allow the implementation of read-only, write-only, no-execute access
policies for mapped pages.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |   11 +++++++++++
 target-mips/helper.c    |   11 ++++++++++-
 target-mips/op_helper.c |    8 ++++++++
 3 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 4f6aa5b..5afafd7 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -30,6 +30,10 @@ struct r4k_tlb_t {
     uint_fast16_t V1:1;
     uint_fast16_t D0:1;
     uint_fast16_t D1:1;
+    uint_fast16_t XI0:1;
+    uint_fast16_t XI1:1;
+    uint_fast16_t RI0:1;
+    uint_fast16_t RI1:1;
     target_ulong PFN[2];
 };
 
@@ -229,6 +233,13 @@ struct CPUMIPSState {
 #define CP0VPEOpt_DWX0	0
     target_ulong CP0_EntryLo0;
     target_ulong CP0_EntryLo1;
+#if defined(TARGET_MIPS64)
+# define CP0EnLo_RI 63
+# define CP0EnLo_XI 62
+#else
+# define CP0EnLo_RI 31
+# define CP0EnLo_XI 30
+#endif
     target_ulong CP0_Context;
     target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
     int32_t CP0_PageMask;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 9871273..6aa8c8a 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -27,6 +27,8 @@
 #include "sysemu/kvm.h"
 
 enum {
+    TLBRET_XI = -6,
+    TLBRET_RI = -5,
     TLBRET_DIRTY = -4,
     TLBRET_INVALID = -3,
     TLBRET_NOMATCH = -2,
@@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
             /* TLB match */
             int n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
-            if (!(n ? tlb->V1 : tlb->V0))
+            if (!(n ? tlb->V1 : tlb->V0)) {
                 return TLBRET_INVALID;
+            }
+            if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
+                return TLBRET_XI;
+            }
+            if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
+                return TLBRET_RI;
+            }
             if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
                 *physical = tlb->PFN[n] | (address & (mask >> 1));
                 *prot = PAGE_READ;
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index b8d384a..3f39305 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
     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] = (env->CP0_EntryLo0 >> 6) << 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] = (env->CP0_EntryLo1 >> 6) << 12;
 }
 
@@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
     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) |
+                        ((target_ulong)tlb->RI1 << CP0EnLo_RI) |
+                        ((target_ulong)tlb->XI1 << CP0EnLo_XI) |
                         (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
 }
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 5/9] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1}
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (3 preceding siblings ...)
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry Leon Alrae
@ 2014-07-08  7:57 ` 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
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

PageGrain needs rw bitmask which differs between MIPS architectures.
In pre-R6 if RIXI is supported, PageGrain.XIE and PageGrain.RIE are writeable,
whereas in R6 they are read-only 1.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h            |    4 ++++
 target-mips/helper.h         |    5 +++++
 target-mips/op_helper.c      |   25 ++++++++++++++++++++++---
 target-mips/translate.c      |   26 ++++++++++++++++++++++++--
 target-mips/translate_init.c |    2 ++
 5 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 5afafd7..8ccb3bb 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -243,7 +243,10 @@ struct CPUMIPSState {
     target_ulong CP0_Context;
     target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
     int32_t CP0_PageMask;
+    int32_t CP0_PageGrain_rw_bitmask;
     int32_t CP0_PageGrain;
+#define CP0PG_RIE 31
+#define CP0PG_XIE 30
     int32_t CP0_Wired;
     int32_t CP0_SRSConf0_rw_bitmask;
     int32_t CP0_SRSConf0;
@@ -377,6 +380,7 @@ struct CPUMIPSState {
 #define CP0C3_M    31
 #define CP0C3_ISA_ON_EXC 16
 #define CP0C3_ULRI 13
+#define CP0C3_RXI  12
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
 #define CP0C3_VEIC 6
diff --git a/target-mips/helper.h b/target-mips/helper.h
index a127db5..e7e0c8c 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -152,6 +152,11 @@ DEF_HELPER_2(mtc0_datalo, void, env, tl)
 DEF_HELPER_2(mtc0_taghi, void, env, tl)
 DEF_HELPER_2(mtc0_datahi, void, env, tl)
 
+#if defined(TARGET_MIPS64)
+DEF_HELPER_2(dmtc0_entrylo0, void, env, i64)
+DEF_HELPER_2(dmtc0_entrylo1, void, env, i64)
+#endif
+
 /* MIPS MT functions */
 DEF_HELPER_2(mftgpr, tl, env, i32)
 DEF_HELPER_2(mftlo, tl, env, i32)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 3f39305..3579bde 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1099,9 +1099,18 @@ void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
 {
     /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
+    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
+    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_RI - 31));
 }
 
+#if defined(TARGET_MIPS64)
+void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
+{
+    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
+    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
+}
+#endif
+
 void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
 {
     uint32_t mask = env->CP0_TCStatus_rw_bitmask;
@@ -1266,9 +1275,18 @@ void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
 {
     /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
+    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
+    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_RI - 31));
 }
 
+#if defined(TARGET_MIPS64)
+void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
+{
+    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
+    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
+}
+#endif
+
 void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
 {
     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
@@ -1285,7 +1303,8 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
     /* SmartMIPS not implemented */
     /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
-    env->CP0_PageGrain = 0;
+    env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
+                         (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
 }
 
 void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index ee18bf3..a8c8318 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1176,6 +1176,7 @@ typedef struct DisasContext {
     target_ulong btarget;
     bool ulri;
     int kscrexist;
+    bool rxi;
 } DisasContext;
 
 enum {
@@ -4703,6 +4704,15 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         switch (sel) {
         case 0:
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
+#if defined(TARGET_MIPS64)
+            if (ctx->rxi) {
+                TCGv tmp = tcg_temp_new();
+                tcg_gen_andi_tl(tmp, arg, (3ull << 62));
+                tcg_gen_shri_tl(tmp, tmp, 32);
+                tcg_gen_or_tl(arg, arg, tmp);
+                tcg_temp_free(tmp);
+            }
+#endif
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo0";
             break;
@@ -4749,6 +4759,15 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         switch (sel) {
         case 0:
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
+#if defined(TARGET_MIPS64)
+            if (ctx->rxi) {
+                TCGv tmp = tcg_temp_new();
+                tcg_gen_andi_tl(tmp, arg, (3ull << 62));
+                tcg_gen_shri_tl(tmp, tmp, 32);
+                tcg_gen_or_tl(arg, arg, tmp);
+                tcg_temp_free(tmp);
+            }
+#endif
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo1";
             break;
@@ -6524,7 +6543,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
     case 2:
         switch (sel) {
         case 0:
-            gen_helper_mtc0_entrylo0(cpu_env, arg);
+            gen_helper_dmtc0_entrylo0(cpu_env, arg);
             rn = "EntryLo0";
             break;
         case 1:
@@ -6569,7 +6588,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
     case 3:
         switch (sel) {
         case 0:
-            gen_helper_mtc0_entrylo1(cpu_env, arg);
+            gen_helper_dmtc0_entrylo1(cpu_env, arg);
             rn = "EntryLo1";
             break;
         default:
@@ -17534,6 +17553,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
     ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
+    ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 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);
@@ -17913,6 +17933,8 @@ void cpu_state_reset(CPUMIPSState *env)
     env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
     env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
     env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
+    env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
+    env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
     env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
     env->insn_flags = env->cpu_model->insn_flags;
 
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 67b7837..779afff 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -96,6 +96,8 @@ struct mips_def_t {
     int32_t CP0_SRSConf3;
     int32_t CP0_SRSConf4_rw_bitmask;
     int32_t CP0_SRSConf4;
+    int32_t CP0_PageGrain_rw_bitmask;
+    int32_t CP0_PageGrain;
     int insn_flags;
     enum mips_mmu_types mmu_type;
 };
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 6/9] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (4 preceding siblings ...)
  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-07-08  7:57 ` Leon Alrae
  2014-10-15 15:39   ` Yongbok Kim
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support Leon Alrae
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

An Execute-Inhibit exception occurs when the virtual address of an instruction
fetch matches a TLB entry whose XI bit is set. This exception type can only
occur if the XI bit is implemented within the TLB and is enabled, this is
denoted by the PageGrain XIE bit.

An Read-Inhibit exception occurs when the virtual address of a memory load
reference matches a TLB entry whose RI bit is set. This exception type can
only occur if the RI bit is implemented within the TLB and is enabled, this is
denoted by the PageGrain RIE bit.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h    |    5 ++++-
 target-mips/helper.c |   25 ++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 8ccb3bb..40ebca6 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -247,6 +247,7 @@ struct CPUMIPSState {
     int32_t CP0_PageGrain;
 #define CP0PG_RIE 31
 #define CP0PG_XIE 30
+#define CP0PG_IEC 27
     int32_t CP0_Wired;
     int32_t CP0_SRSConf0_rw_bitmask;
     int32_t CP0_SRSConf0;
@@ -645,8 +646,10 @@ enum {
     EXCP_C2E,
     EXCP_CACHE, /* 32 */
     EXCP_DSPDIS,
+    EXCP_TLBXI,
+    EXCP_TLBRI,
 
-    EXCP_LAST = EXCP_DSPDIS,
+    EXCP_LAST = EXCP_TLBRI,
 };
 /* Dummy exception for conditional stores.  */
 #define EXCP_SC 0x100
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 6aa8c8a..fed28b4 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -273,7 +273,22 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
         /* TLB match but 'D' bit is cleared */
         exception = EXCP_LTLBL;
         break;
-
+    case TLBRET_XI:
+        /* Execute-Inhibit Exception */
+        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
+            exception = EXCP_TLBXI;
+        } else {
+            exception = EXCP_TLBL;
+        }
+        break;
+    case TLBRET_RI:
+        /* Read-Inhibit Exception */
+        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
+            exception = EXCP_TLBRI;
+        } else {
+            exception = EXCP_TLBL;
+        }
+        break;
     }
     /* Raise exception */
     env->CP0_BadVAddr = address;
@@ -404,6 +419,8 @@ static const char * const excp_names[EXCP_LAST + 1] = {
     [EXCP_MDMX] = "MDMX",
     [EXCP_C2E] = "precise coprocessor 2",
     [EXCP_CACHE] = "cache error",
+    [EXCP_TLBXI] = "TLB execute-inhibit",
+    [EXCP_TLBRI] = "TLB read-inhibit",
 };
 
 target_ulong exception_resume_pc (CPUMIPSState *env)
@@ -622,6 +639,12 @@ void mips_cpu_do_interrupt(CPUState *cs)
     case EXCP_C2E:
         cause = 18;
         goto set_EPC;
+    case EXCP_TLBRI:
+        cause = 19;
+        goto set_EPC;
+    case EXCP_TLBXI:
+        cause = 20;
+        goto set_EPC;
     case EXCP_MDMX:
         cause = 22;
         goto set_EPC;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (5 preceding siblings ...)
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 6/9] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions Leon Alrae
@ 2014-07-08  7:57 ` Leon Alrae
  2014-10-16 10:52   ` Yongbok Kim
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support 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
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

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

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (6 preceding siblings ...)
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support Leon Alrae
@ 2014-07-08  7:57 ` Leon Alrae
  2014-07-08 12:44   ` James Hogan
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 9/9] target-mips: update cpu_save/cpu_load to support new registers Leon Alrae
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

BadInstr Register (CP0 Register 8, Select 1)
The BadInstr register is a read-only register that capture the most recent
instruction which caused an exception.

BadInstrP Register (CP0 Register 8, Select 2)
The BadInstrP register contains the prior branch instruction, when the
faulting instruction is in a branch delay slot.

Using error_code to indicate whether AdEL or TLBL was triggered during
instruction fetch, in this case BadInstr is not updated as valid instruction
word is not available.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |    6 +++
 target-mips/helper.c    |   44 ++++++++++++++++++++++++--
 target-mips/op_helper.c |   17 +++++++++-
 target-mips/translate.c |   80 +++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index bc52222..656f5ca 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -177,6 +177,8 @@ struct TCState {
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
     target_ulong CP0_UserLocal;
+    uint32_t CP0_BadInstr;
+    uint32_t CP0_BadInstrP;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
@@ -383,6 +385,8 @@ struct CPUMIPSState {
 #define CP0C2_SA   0
     int32_t CP0_Config3;
 #define CP0C3_M    31
+#define CP0C3_BP 27
+#define CP0C3_BI 26
 #define CP0C3_ISA_ON_EXC 16
 #define CP0C3_ULRI 13
 #define CP0C3_RXI  12
@@ -453,6 +457,8 @@ struct CPUMIPSState {
     CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
     /* QEMU */
     int error_code;
+#define EXCP_TLB_NOMATCH   0x1
+#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
 #define MIPS_HFLAG_TMASK  0xC07FF
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 5d72438..67fc71d 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -25,6 +25,7 @@
 
 #include "cpu.h"
 #include "sysemu/kvm.h"
+#include "exec/cpu_ldst.h"
 
 enum {
     TLBRET_XI = -6,
@@ -241,6 +242,10 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
     CPUState *cs = CPU(mips_env_get_cpu(env));
     int exception = 0, error_code = 0;
 
+    if (rw == MMU_INST_FETCH) {
+        error_code |= EXCP_INST_NOTAVAIL;
+    }
+
     switch (tlb_error) {
     default:
     case TLBRET_BADADDR:
@@ -259,7 +264,7 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
         } else {
             exception = EXCP_TLBL;
         }
-        error_code = 1;
+        error_code |= EXCP_TLB_NOMATCH;
         break;
     case TLBRET_INVALID:
         /* TLB match with no valid bit */
@@ -451,6 +456,20 @@ static void set_hflags_for_handler (CPUMIPSState *env)
                         << MIPS_HFLAG_M16_SHIFT);
     }
 }
+
+static inline void set_badinstr_registers(CPUMIPSState *env)
+{
+    if (env->hflags & MIPS_HFLAG_M16) {
+        /* TODO: add BadInstr support for microMIPS */
+        return;
+    }
+    if (env->CP0_Config3 & (1 << CP0C3_BI)) {
+        env->active_tc.CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC);
+    }
+    if (env->CP0_Config3 & (1 << CP0C3_BP) && env->hflags & MIPS_HFLAG_BMASK) {
+        env->active_tc.CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4);
+    }
+}
 #endif
 
 void mips_cpu_do_interrupt(CPUState *cs)
@@ -458,6 +477,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
 #if !defined(CONFIG_USER_ONLY)
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
+    bool update_badinstr = 0;
     target_ulong offset;
     int cause = -1;
     const char *name;
@@ -566,10 +586,13 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_LTLBL:
         cause = 1;
+        update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
         goto set_EPC;
     case EXCP_TLBL:
         cause = 2;
-        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
+        update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
+        if (env->error_code & EXCP_TLB_NOMATCH &&
+            !(env->CP0_Status & (1 << CP0St_EXL))) {
 #if defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
             int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
@@ -586,7 +609,9 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_TLBS:
         cause = 3;
-        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
+        update_badinstr = 1;
+        if (env->error_code & EXCP_TLB_NOMATCH &&
+            !(env->CP0_Status & (1 << CP0St_EXL))) {
 #if defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
             int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
@@ -603,9 +628,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_AdEL:
         cause = 4;
+        update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
         goto set_EPC;
     case EXCP_AdES:
         cause = 5;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_IBE:
         cause = 6;
@@ -615,32 +642,40 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_SYSCALL:
         cause = 8;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_BREAK:
         cause = 9;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_RI:
         cause = 10;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_CpU:
         cause = 11;
+        update_badinstr = 1;
         env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
                          (env->error_code << CP0Ca_CE);
         goto set_EPC;
     case EXCP_OVERFLOW:
         cause = 12;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_TRAP:
         cause = 13;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_FPE:
         cause = 15;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_C2E:
         cause = 18;
         goto set_EPC;
     case EXCP_TLBRI:
         cause = 19;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_TLBXI:
         cause = 20;
@@ -671,6 +706,9 @@ void mips_cpu_do_interrupt(CPUState *cs)
  set_EPC:
         if (!(env->CP0_Status & (1 << CP0St_EXL))) {
             env->CP0_EPC = exception_resume_pc(env);
+            if (update_badinstr) {
+                set_badinstr_registers(env);
+            }
             if (env->hflags & MIPS_HFLAG_BMASK) {
                 env->CP0_Cause |= (1U << CP0Ca_BD);
             } else {
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index fa96bb3..431f3a1 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2238,13 +2238,26 @@ void helper_wait(CPUMIPSState *env)
 #if !defined(CONFIG_USER_ONLY)
 
 void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
-                                  int is_write, int is_user, uintptr_t retaddr)
+                                  int access_type, int is_user,
+                                  uintptr_t retaddr)
 {
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
+    int error_code = 0;
+    int excp;
 
     env->CP0_BadVAddr = addr;
-    do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr);
+
+    if (access_type == MMU_DATA_STORE) {
+        excp = EXCP_AdES;
+    } else {
+        excp = EXCP_AdEL;
+        if (access_type == MMU_INST_FETCH) {
+            error_code |= EXCP_INST_NOTAVAIL;
+        }
+    }
+
+    do_raise_exception_err(env, excp, error_code, retaddr);
 }
 
 void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4179fea..b931574 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1180,6 +1180,8 @@ typedef struct DisasContext {
     int kscrexist;
     bool rxi;
     bool ie;
+    bool bi;
+    bool bp;
 } DisasContext;
 
 enum {
@@ -4872,9 +4874,27 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ext32s_tl(arg, arg);
             rn = "BadVAddr";
             break;
+        case 1:
+            if (ctx->bi) {
+                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                              active_tc.CP0_BadInstr));
+                rn = "BadInstr";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
+        case 2:
+            if (ctx->bp) {
+                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                              active_tc.CP0_BadInstrP));
+                rn = "BadInstrP";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 9:
         switch (sel) {
@@ -5472,8 +5492,22 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         }
         break;
     case 8:
-        /* ignored */
-        rn = "BadVAddr";
+        switch (sel) {
+        case 0:
+            /* ignored */
+            rn = "BadVAddr";
+            break;
+        case 1:
+            /* ignored */
+            rn = "BadInstr";
+            break;
+        case 2:
+            /* ignored */
+            rn = "BadInstrP";
+            break;
+        default:
+            goto die;
+        }
         break;
     case 9:
         switch (sel) {
@@ -6098,6 +6132,24 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
             rn = "BadVAddr";
             break;
+        case 1:
+            if (ctx->bi) {
+                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                              active_tc.CP0_BadInstr));
+                rn = "BadInstr";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
+        case 2:
+            if (ctx->bp) {
+                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                              active_tc.CP0_BadInstrP));
+                rn = "BadInstrP";
+            } else {
+                gen_mfc0_unimplemented(ctx, arg);
+            }
+            break;
         default:
             goto die;
         }
@@ -6683,8 +6735,22 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         }
         break;
     case 8:
-        /* ignored */
-        rn = "BadVAddr";
+        switch (sel) {
+        case 0:
+            /* ignored */
+            rn = "BadVAddr";
+            break;
+        case 1:
+            /* ignored */
+            rn = "BadInstr";
+            break;
+        case 2:
+            /* ignored */
+            rn = "BadInstrP";
+            break;
+        default:
+            goto die;
+        }
         break;
     case 9:
         switch (sel) {
@@ -16940,7 +17006,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
     /* make sure instructions are on a word boundary */
     if (ctx->pc & 0x3) {
         env->CP0_BadVAddr = ctx->pc;
-        generate_exception(ctx, EXCP_AdEL);
+        generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
         return;
     }
 
@@ -17576,6 +17642,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
     ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
     ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 1;
+    ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
+    ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 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);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH v2 9/9] target-mips: update cpu_save/cpu_load to support new registers
  2014-07-08  7:57 [Qemu-devel] [PATCH v2 0/9] target-mips: implement features required in MIPS64 Release 6 Leon Alrae
                   ` (7 preceding siblings ...)
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support Leon Alrae
@ 2014-07-08  7:57 ` Leon Alrae
  2014-10-16 13:06   ` Yongbok Kim
  8 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08  7:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien


Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h     |    2 +-
 target-mips/machine.c |   14 ++++++++++++++
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 656f5ca..23bb22c 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -557,7 +557,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
 extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
 
-#define CPU_SAVE_VERSION 4
+#define CPU_SAVE_VERSION 5
 
 /* MMU modes definitions. We carefully match the indices with our
    hflags layout. */
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 0496faa..576dc10 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -26,6 +26,8 @@ static void save_tc(QEMUFile *f, TCState *tc)
     qemu_put_betls(f, &tc->CP0_TCScheFBack);
     qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
     qemu_put_betls(f, &tc->CP0_UserLocal);
+    qemu_put_be32s(f, &tc->CP0_BadInstr);
+    qemu_put_be32s(f, &tc->CP0_BadInstrP);
 }
 
 static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -144,6 +146,9 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_sbe32s(f, &env->CP0_DataHi);
     qemu_put_betls(f, &env->CP0_ErrorEPC);
     qemu_put_sbe32s(f, &env->CP0_DESAVE);
+    for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
+        qemu_put_betls(f, &env->CP0_KScratch[i]);
+    }
 
     /* Save inactive TC state */
     for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
@@ -177,6 +182,10 @@ static void load_tc(QEMUFile *f, TCState *tc, int version_id)
     if (version_id >= 4) {
         qemu_get_betls(f, &tc->CP0_UserLocal);
     }
+    if (version_id >= 5) {
+        qemu_get_be32s(f, &tc->CP0_BadInstr);
+        qemu_get_be32s(f, &tc->CP0_BadInstrP);
+    }
 }
 
 static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -301,6 +310,11 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_sbe32s(f, &env->CP0_DataHi);
     qemu_get_betls(f, &env->CP0_ErrorEPC);
     qemu_get_sbe32s(f, &env->CP0_DESAVE);
+    if (version_id >= 5) {
+        for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
+            qemu_get_betls(f, &env->CP0_KScratch[i]);
+        }
+    }
 
     /* Load inactive TC state */
     for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support
  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
  0 siblings, 1 reply; 26+ messages in thread
From: James Hogan @ 2014-07-08 12:44 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: yongbok.kim, cristian.cuna, aurelien

Hi Leon,

On 08/07/14 08:57, Leon Alrae wrote:
> BadInstr Register (CP0 Register 8, Select 1)
> The BadInstr register is a read-only register that capture the most recent
> instruction which caused an exception.
> 
> BadInstrP Register (CP0 Register 8, Select 2)
> The BadInstrP register contains the prior branch instruction, when the
> faulting instruction is in a branch delay slot.
> 
> Using error_code to indicate whether AdEL or TLBL was triggered during
> instruction fetch, in this case BadInstr is not updated as valid instruction
> word is not available.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/cpu.h       |    6 +++
>  target-mips/helper.c    |   44 ++++++++++++++++++++++++--
>  target-mips/op_helper.c |   17 +++++++++-
>  target-mips/translate.c |   80 +++++++++++++++++++++++++++++++++++++++++++---
>  4 files changed, 136 insertions(+), 11 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index bc52222..656f5ca 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -177,6 +177,8 @@ struct TCState {
>      target_ulong CP0_TCScheFBack;
>      int32_t CP0_Debug_tcstatus;
>      target_ulong CP0_UserLocal;
> +    uint32_t CP0_BadInstr;
> +    uint32_t CP0_BadInstrP;

According to the PRA, BadInstr/BadInstrP are instantiated per VPE, so
shouldn't these be in struct CPUMIPSState?

Cheers
James

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum
  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
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2014-07-08 13:00 UTC (permalink / raw)
  To: Leon Alrae; +Cc: yongbok.kim, cristian.cuna, QEMU Developers, Aurelien Jarno

On 8 July 2014 08:57, Leon Alrae <leon.alrae@imgtec.com> wrote:
> New MIPS features depend on the access type and enum is more convenient than
> using the numbers directly.
>
Mmm, I've thought for a while it would be better to have this
be an enum, but never got round to it.

> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  include/exec/cpu-common.h |    6 ++++++
>  softmmu_template.h        |   26 ++++++++++++++++----------
>  2 files changed, 22 insertions(+), 10 deletions(-)
>
> diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
> index e3ec4c8..1c3171a 100644
> --- a/include/exec/cpu-common.h
> +++ b/include/exec/cpu-common.h
> @@ -26,6 +26,12 @@ typedef struct CPUListState {
>      FILE *file;
>  } CPUListState;
>
> +enum mmu_access_type {

CODING_STYLE says enum names should be CamelCase.
I think you also want this to be a typedef.

> +    MMU_DATA_LOAD  = 0,
> +    MMU_DATA_STORE = 1,
> +    MMU_INST_FETCH = 2
> +};
> +

We should probably also chase through and update the
prototypes of functions like tlb_fill() and cpu_unaligned_access()
and so on to take this enum type rather than int. (I
suspect there's a lot of those running into different
targets so it might need doing over multiple patches.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 8/9] target-mips: add BadInstr and BadInstrP support
  2014-07-08 12:44   ` James Hogan
@ 2014-07-08 15:56     ` Leon Alrae
  0 siblings, 0 replies; 26+ messages in thread
From: Leon Alrae @ 2014-07-08 15:56 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: yongbok.kim, cristian.cuna, aurelien

Hi James,

On 08/07/2014 13:44, James Hogan wrote:
> Hi Leon,
> 
> On 08/07/14 08:57, Leon Alrae wrote:
>> BadInstr Register (CP0 Register 8, Select 1)
>> The BadInstr register is a read-only register that capture the most recent
>> instruction which caused an exception.
>>
>> BadInstrP Register (CP0 Register 8, Select 2)
>> The BadInstrP register contains the prior branch instruction, when the
>> faulting instruction is in a branch delay slot.
>>
>> Using error_code to indicate whether AdEL or TLBL was triggered during
>> instruction fetch, in this case BadInstr is not updated as valid instruction
>> word is not available.
>>
>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>> ---
>>  target-mips/cpu.h       |    6 +++
>>  target-mips/helper.c    |   44 ++++++++++++++++++++++++--
>>  target-mips/op_helper.c |   17 +++++++++-
>>  target-mips/translate.c |   80 +++++++++++++++++++++++++++++++++++++++++++---
>>  4 files changed, 136 insertions(+), 11 deletions(-)
>>
>> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>> index bc52222..656f5ca 100644
>> --- a/target-mips/cpu.h
>> +++ b/target-mips/cpu.h
>> @@ -177,6 +177,8 @@ struct TCState {
>>      target_ulong CP0_TCScheFBack;
>>      int32_t CP0_Debug_tcstatus;
>>      target_ulong CP0_UserLocal;
>> +    uint32_t CP0_BadInstr;
>> +    uint32_t CP0_BadInstrP;
> 
> According to the PRA, BadInstr/BadInstrP are instantiated per VPE, so
> shouldn't these be in struct CPUMIPSState?
> 
> Cheers
> James
> 

Thanks for pointing this out - I'll correct it in the next version.

Regards,
Leon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum
  2014-07-08 13:00   ` Peter Maydell
@ 2014-07-08 16:08     ` Leon Alrae
  2014-07-08 16:12       ` Peter Maydell
  0 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-07-08 16:08 UTC (permalink / raw)
  To: Peter Maydell; +Cc: yongbok.kim, cristian.cuna, QEMU Developers, Aurelien Jarno

Hi Peter,

On 08/07/2014 14:00, Peter Maydell wrote:
> On 8 July 2014 08:57, Leon Alrae <leon.alrae@imgtec.com> wrote:
>> New MIPS features depend on the access type and enum is more convenient than
>> using the numbers directly.
>>
> Mmm, I've thought for a while it would be better to have this
> be an enum, but never got round to it.
> 
>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>> ---
>>  include/exec/cpu-common.h |    6 ++++++
>>  softmmu_template.h        |   26 ++++++++++++++++----------
>>  2 files changed, 22 insertions(+), 10 deletions(-)
>>
>> diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
>> index e3ec4c8..1c3171a 100644
>> --- a/include/exec/cpu-common.h
>> +++ b/include/exec/cpu-common.h
>> @@ -26,6 +26,12 @@ typedef struct CPUListState {
>>      FILE *file;
>>  } CPUListState;
>>
>> +enum mmu_access_type {
> 
> CODING_STYLE says enum names should be CamelCase.
> I think you also want this to be a typedef.

The style was copied from "enum device_endian {" which is few lines
below, I assumed it was correct :) I'll fix this.

>> +    MMU_DATA_LOAD  = 0,
>> +    MMU_DATA_STORE = 1,
>> +    MMU_INST_FETCH = 2
>> +};
>> +
> 
> We should probably also chase through and update the
> prototypes of functions like tlb_fill() and cpu_unaligned_access()
> and so on to take this enum type rather than int. (I
> suspect there's a lot of those running into different
> targets so it might need doing over multiple patches.)
> 
> thanks
> -- PMM
> 

I intentionally skipped this here to focus this patchset on the new
features only. I also think that eventually we will have to update the
prototypes and go through all the targets.

Thanks,
Leon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/9] softmmu: provide softmmu access type enum
  2014-07-08 16:08     ` Leon Alrae
@ 2014-07-08 16:12       ` Peter Maydell
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2014-07-08 16:12 UTC (permalink / raw)
  To: Leon Alrae; +Cc: yongbok.kim, cristian.cuna, QEMU Developers, Aurelien Jarno

On 8 July 2014 17:08, Leon Alrae <leon.alrae@imgtec.com> wrote:
> I intentionally skipped this here to focus this patchset on the new
> features only. I also think that eventually we will have to update the
> prototypes and go through all the targets.

Yeah, that's reasonable. If you make this a typedef then we
can update the prototypes later.

-- PMM

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers
  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
  0 siblings, 1 reply; 26+ messages in thread
From: Yongbok Kim @ 2014-10-14 13:59 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Not related code changes are included.
See the comment below.

Other than,
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok


On 08/07/2014 08:57, Leon Alrae wrote:
> KScratch<n> Registers (CP0 Register 31, Selects 2 to 7)
>
> The KScratch registers are read/write registers available for scratch pad
> storage by kernel mode software. They are 32-bits in width for 32-bit
> processors and 64-bits for 64-bit processors.
>
> CP0Config4.KScrExist[2:7] bits indicate presence of CP0_KScratch1-6 registers.
> For Release 6, all KScratch registers are required.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h       |    3 +++
>   target-mips/translate.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 47 insertions(+), 0 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 51a8331..4f6aa5b 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -136,6 +136,7 @@ typedef struct mips_def_t mips_def_t;
>   #define MIPS_TC_MAX 5
>   #define MIPS_FPU_MAX 1
>   #define MIPS_DSP_ACC 4
> +#define MIPS_KSCRATCH_NUM 6
>   
>   typedef struct TCState TCState;
>   struct TCState {
> @@ -229,6 +230,7 @@ struct CPUMIPSState {
>       target_ulong CP0_EntryLo0;
>       target_ulong CP0_EntryLo1;
>       target_ulong CP0_Context;
> +    target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>       int32_t CP0_PageMask;
>       int32_t CP0_PageGrain;
>       int32_t CP0_Wired;
> @@ -375,6 +377,7 @@ struct CPUMIPSState {
>       uint32_t CP0_Config4;
>       uint32_t CP0_Config4_rw_bitmask;
>   #define CP0C4_M    31
> +#define CP0C4_KScrExist 16
>       uint32_t CP0_Config5;
>       uint32_t CP0_Config5_rw_bitmask;
>   #define CP0C5_M          31
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 6956fdd..ee18bf3 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1175,6 +1175,7 @@ typedef struct DisasContext {
>       int bstate;
>       target_ulong btarget;
>       bool ulri;
> +    int kscrexist;
>   } DisasContext;
>   
>   enum {
> @@ -4611,6 +4612,15 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
>       tcg_gen_st_tl(arg, cpu_env, off);
>   }
>   
> +static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
> +{
> +    if (ctx->insn_flags & ISA_MIPS32R6) {
> +        tcg_gen_movi_tl(arg, 0);
> +    } else {
> +        tcg_gen_movi_tl(arg, ~0);
> +    }
> +}
> +

Not related with KScratch registers. It would be better to be a separate 
patch or
as part of the patch [PATCH 5/6] target-mips: correctly handle access to 
unimplemented CP0 register.

>   static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>   {
>       const char *rn = "invalid";
> @@ -5193,6 +5203,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>               rn = "DESAVE";
>               break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_ld_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                tcg_gen_ext32s_tl(arg, arg);
> +                rn = "KScratch";
> +            } else {
> +                gen_mfc0_unimplemented(ctx, arg);
> +            }
> +            break;
>           default:
>               goto die;
>           }
> @@ -5801,6 +5821,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>               rn = "DESAVE";
>               break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_st_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                rn = "KScratch";
> +            }
> +            break;
>           default:
>               goto die;
>           }
> @@ -6388,6 +6415,15 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>               rn = "DESAVE";
>               break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_ld_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                rn = "KScratch";
> +            } else {
> +                gen_mfc0_unimplemented(ctx, arg);
> +            }
> +            break;
>           default:
>               goto die;
>           }
> @@ -6987,6 +7023,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>               rn = "DESAVE";
>               break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_st_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                rn = "KScratch";
> +            }
> +            break;
>           default:
>               goto die;
>           }
> @@ -17490,6 +17533,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>       ctx.CP0_Config1 = env->CP0_Config1;
>       ctx.tb = tb;
>       ctx.bstate = BS_NONE;
> +    ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
>       /* 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);

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch
  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
  0 siblings, 0 replies; 26+ messages in thread
From: Yongbok Kim @ 2014-10-14 15:55 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

On 08/07/2014 08:57, Leon Alrae wrote:
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/helper.c |   21 ++++++++++-----------
>   1 files changed, 10 insertions(+), 11 deletions(-)
>
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 8a997e4..9871273 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -87,7 +87,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
>               /* Check access rights */
>               if (!(n ? tlb->V1 : tlb->V0))
>                   return TLBRET_INVALID;
> -            if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
> +            if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
>                   *physical = tlb->PFN[n] | (address & (mask >> 1));
>                   *prot = PAGE_READ;
>                   if (n ? tlb->D1 : tlb->D0)
> @@ -237,25 +237,28 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
>       case TLBRET_BADADDR:
>           /* Reference to kernel address from user mode or supervisor mode */
>           /* Reference to supervisor address from user mode */
> -        if (rw)
> +        if (rw == MMU_DATA_STORE) {
>               exception = EXCP_AdES;
> -        else
> +        } else {
>               exception = EXCP_AdEL;
> +        }
>           break;
>       case TLBRET_NOMATCH:
>           /* No TLB match for a mapped address */
> -        if (rw)
> +        if (rw == MMU_DATA_STORE) {
>               exception = EXCP_TLBS;
> -        else
> +        } else {
>               exception = EXCP_TLBL;
> +        }
>           error_code = 1;
>           break;
>       case TLBRET_INVALID:
>           /* TLB match with no valid bit */
> -        if (rw)
> +        if (rw == MMU_DATA_STORE) {
>               exception = EXCP_TLBS;
> -        else
> +        } else {
>               exception = EXCP_TLBL;
> +        }
>           break;
>       case TLBRET_DIRTY:
>           /* TLB match but 'D' bit is cleared */
> @@ -312,8 +315,6 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
>       qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
>                 __func__, env->active_tc.PC, address, rw, mmu_idx);
>   
> -    rw &= 1;
> -
>       /* data access */
>   #if !defined(CONFIG_USER_ONLY)
>       /* XXX: put correct access by using cpu_restore_state()
> @@ -347,8 +348,6 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
>       int access_type;
>       int ret = 0;
>   
> -    rw &= 1;
> -
>       /* data access */
>       access_type = ACCESS_INT;
>       ret = get_physical_address(env, &physical, &prot,

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
  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
  0 siblings, 1 reply; 26+ messages in thread
From: Yongbok Kim @ 2014-10-15 12:24 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien


On 08/07/2014 08:57, Leon Alrae wrote:
> In Revision 3 of the architecture, the RI and XI bits were added to the TLB
> to enable more secure access of memory pages. These bits (along with the Dirty
> bit) allow the implementation of read-only, write-only, no-execute access
> policies for mapped pages.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h       |   11 +++++++++++
>   target-mips/helper.c    |   11 ++++++++++-
>   target-mips/op_helper.c |    8 ++++++++
>   3 files changed, 29 insertions(+), 1 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 4f6aa5b..5afafd7 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -30,6 +30,10 @@ struct r4k_tlb_t {
>       uint_fast16_t V1:1;
>       uint_fast16_t D0:1;
>       uint_fast16_t D1:1;
> +    uint_fast16_t XI0:1;
> +    uint_fast16_t XI1:1;
> +    uint_fast16_t RI0:1;
> +    uint_fast16_t RI1:1;
>       target_ulong PFN[2];
>   };
>   
> @@ -229,6 +233,13 @@ struct CPUMIPSState {
>   #define CP0VPEOpt_DWX0	0
>       target_ulong CP0_EntryLo0;
>       target_ulong CP0_EntryLo1;
> +#if defined(TARGET_MIPS64)
> +# define CP0EnLo_RI 63
> +# define CP0EnLo_XI 62
> +#else
> +# define CP0EnLo_RI 31
> +# define CP0EnLo_XI 30
> +#endif
>       target_ulong CP0_Context;
>       target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>       int32_t CP0_PageMask;
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 9871273..6aa8c8a 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -27,6 +27,8 @@
>   #include "sysemu/kvm.h"
>   
>   enum {
> +    TLBRET_XI = -6,
> +    TLBRET_RI = -5,
>       TLBRET_DIRTY = -4,
>       TLBRET_INVALID = -3,
>       TLBRET_NOMATCH = -2,
> @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
>               /* TLB match */
>               int n = !!(address & mask & ~(mask >> 1));
>               /* Check access rights */
> -            if (!(n ? tlb->V1 : tlb->V0))
> +            if (!(n ? tlb->V1 : tlb->V0)) {
>                   return TLBRET_INVALID;
> +            }
> +            if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
> +                return TLBRET_XI;
> +            }
> +            if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
> +                return TLBRET_RI;

PC relative loads are allowed where execute is allowed (even though RI 
is 1).
Rather than just return RI here have to check XI and its OP code.

> +            }
>               if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
>                   *physical = tlb->PFN[n] | (address & (mask >> 1));
>                   *prot = PAGE_READ;
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index b8d384a..3f39305 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
>       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] = (env->CP0_EntryLo0 >> 6) << 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] = (env->CP0_EntryLo1 >> 6) << 12;
>   }
>   
> @@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
>       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) |
> +                        ((target_ulong)tlb->RI1 << CP0EnLo_RI) |
> +                        ((target_ulong)tlb->XI1 << CP0EnLo_XI) |
>                           (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
>   }
>   

Regards,
Yongbok

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/9] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1}
  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
  0 siblings, 0 replies; 26+ messages in thread
From: Yongbok Kim @ 2014-10-15 15:20 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

dm{t,f}c0_entrylo{0,1} is also added.
Please reflect it in the title.

I have other minor comments below.

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

On 08/07/2014 08:57, Leon Alrae wrote:
> PageGrain needs rw bitmask which differs between MIPS architectures.
> In pre-R6 if RIXI is supported, PageGrain.XIE and PageGrain.RIE are writeable,
> whereas in R6 they are read-only 1.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h            |    4 ++++
>   target-mips/helper.h         |    5 +++++
>   target-mips/op_helper.c      |   25 ++++++++++++++++++++++---
>   target-mips/translate.c      |   26 ++++++++++++++++++++++++--
>   target-mips/translate_init.c |    2 ++
>   5 files changed, 57 insertions(+), 5 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 5afafd7..8ccb3bb 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -243,7 +243,10 @@ struct CPUMIPSState {
>       target_ulong CP0_Context;
>       target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>       int32_t CP0_PageMask;
> +    int32_t CP0_PageGrain_rw_bitmask;
>       int32_t CP0_PageGrain;
> +#define CP0PG_RIE 31
> +#define CP0PG_XIE 30
>       int32_t CP0_Wired;
>       int32_t CP0_SRSConf0_rw_bitmask;
>       int32_t CP0_SRSConf0;
> @@ -377,6 +380,7 @@ struct CPUMIPSState {
>   #define CP0C3_M    31
>   #define CP0C3_ISA_ON_EXC 16
>   #define CP0C3_ULRI 13
> +#define CP0C3_RXI  12
>   #define CP0C3_DSPP 10
>   #define CP0C3_LPA  7
>   #define CP0C3_VEIC 6
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index a127db5..e7e0c8c 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -152,6 +152,11 @@ DEF_HELPER_2(mtc0_datalo, void, env, tl)
>   DEF_HELPER_2(mtc0_taghi, void, env, tl)
>   DEF_HELPER_2(mtc0_datahi, void, env, tl)
>   
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_2(dmtc0_entrylo0, void, env, i64)
> +DEF_HELPER_2(dmtc0_entrylo1, void, env, i64)
> +#endif
> +
>   /* MIPS MT functions */
>   DEF_HELPER_2(mftgpr, tl, env, i32)
>   DEF_HELPER_2(mftlo, tl, env, i32)
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 3f39305..3579bde 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1099,9 +1099,18 @@ void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
>   {
>       /* Large physaddr (PABITS) not implemented */
>       /* 1k pages not implemented */
> -    env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
> +    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> +    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_RI - 31));
rxi << (CP0EnLo_XI - 30) would be natural as CP0PG_XIE is used just above.
Anyway as the result is same, you can ignore.

>   }
>   
> +#if defined(TARGET_MIPS64)
> +void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
> +{

It might be better to have the comments to indicate the mask is 
calculated based on these conditions just like mtc0_entrylo{0,1}.
However you can ignore this issue.

      /* Large physaddr (PABITS) not implemented */
      /* 1k pages not implemented */

> +    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> +    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
> +}
> +#endif
> +
>   void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
>   {
>       uint32_t mask = env->CP0_TCStatus_rw_bitmask;
> @@ -1266,9 +1275,18 @@ void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
>   {
>       /* Large physaddr (PABITS) not implemented */
>       /* 1k pages not implemented */
> -    env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
> +    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> +    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_RI - 31));

Same here.
rxi << (CP0EnLo_XI - 30)

>   }
>   
> +#if defined(TARGET_MIPS64)
> +void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
> +{

same here. it might need the comments.

> +    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> +    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
> +}
> +#endif
> +
>   void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
>   {
>       env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
> @@ -1285,7 +1303,8 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
>       /* SmartMIPS not implemented */
>       /* Large physaddr (PABITS) not implemented */
>       /* 1k pages not implemented */

This comment is not relevant here as the function is not restricting 
because of the issue.
However that information is still valid, you can leave the comment as it 
is.

> -    env->CP0_PageGrain = 0;
> +    env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
> +                         (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
>   }
>   
>   void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index ee18bf3..a8c8318 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1176,6 +1176,7 @@ typedef struct DisasContext {
>       target_ulong btarget;
>       bool ulri;
>       int kscrexist;
> +    bool rxi;
>   } DisasContext;
>   
>   enum {
> @@ -4703,6 +4704,15 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           switch (sel) {
>           case 0:
>               tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
> +#if defined(TARGET_MIPS64)
> +            if (ctx->rxi) {
> +                TCGv tmp = tcg_temp_new();
> +                tcg_gen_andi_tl(tmp, arg, (3ull << 62));
> +                tcg_gen_shri_tl(tmp, tmp, 32);
> +                tcg_gen_or_tl(arg, arg, tmp);
> +                tcg_temp_free(tmp);
> +            }
> +#endif
>               tcg_gen_ext32s_tl(arg, arg);
>               rn = "EntryLo0";
>               break;
> @@ -4749,6 +4759,15 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           switch (sel) {
>           case 0:
>               tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
> +#if defined(TARGET_MIPS64)
> +            if (ctx->rxi) {
> +                TCGv tmp = tcg_temp_new();
> +                tcg_gen_andi_tl(tmp, arg, (3ull << 62));
> +                tcg_gen_shri_tl(tmp, tmp, 32);
> +                tcg_gen_or_tl(arg, arg, tmp);
> +                tcg_temp_free(tmp);
> +            }
> +#endif
>               tcg_gen_ext32s_tl(arg, arg);
>               rn = "EntryLo1";
>               break;
> @@ -6524,7 +6543,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>       case 2:
>           switch (sel) {
>           case 0:
> -            gen_helper_mtc0_entrylo0(cpu_env, arg);
> +            gen_helper_dmtc0_entrylo0(cpu_env, arg);
>               rn = "EntryLo0";
>               break;
>           case 1:
> @@ -6569,7 +6588,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>       case 3:
>           switch (sel) {
>           case 0:
> -            gen_helper_mtc0_entrylo1(cpu_env, arg);
> +            gen_helper_dmtc0_entrylo1(cpu_env, arg);
>               rn = "EntryLo1";
>               break;
>           default:
> @@ -17534,6 +17553,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>       ctx.tb = tb;
>       ctx.bstate = BS_NONE;
>       ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
> +    ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 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);
> @@ -17913,6 +17933,8 @@ void cpu_state_reset(CPUMIPSState *env)
>       env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
>       env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
>       env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
> +    env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
> +    env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
>       env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
>       env->insn_flags = env->cpu_model->insn_flags;
>   
> diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
> index 67b7837..779afff 100644
> --- a/target-mips/translate_init.c
> +++ b/target-mips/translate_init.c
> @@ -96,6 +96,8 @@ struct mips_def_t {
>       int32_t CP0_SRSConf3;
>       int32_t CP0_SRSConf4_rw_bitmask;
>       int32_t CP0_SRSConf4;
> +    int32_t CP0_PageGrain_rw_bitmask;
> +    int32_t CP0_PageGrain;
>       int insn_flags;
>       enum mips_mmu_types mmu_type;
>   };

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/9] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions
  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
  0 siblings, 0 replies; 26+ messages in thread
From: Yongbok Kim @ 2014-10-15 15:39 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok


On 08/07/2014 08:57, Leon Alrae wrote:
> An Execute-Inhibit exception occurs when the virtual address of an instruction
> fetch matches a TLB entry whose XI bit is set. This exception type can only
> occur if the XI bit is implemented within the TLB and is enabled, this is
> denoted by the PageGrain XIE bit.
>
> An Read-Inhibit exception occurs when the virtual address of a memory load
> reference matches a TLB entry whose RI bit is set. This exception type can
> only occur if the RI bit is implemented within the TLB and is enabled, this is
> denoted by the PageGrain RIE bit.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h    |    5 ++++-
>   target-mips/helper.c |   25 ++++++++++++++++++++++++-
>   2 files changed, 28 insertions(+), 2 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 8ccb3bb..40ebca6 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -247,6 +247,7 @@ struct CPUMIPSState {
>       int32_t CP0_PageGrain;
>   #define CP0PG_RIE 31
>   #define CP0PG_XIE 30
> +#define CP0PG_IEC 27
>       int32_t CP0_Wired;
>       int32_t CP0_SRSConf0_rw_bitmask;
>       int32_t CP0_SRSConf0;
> @@ -645,8 +646,10 @@ enum {
>       EXCP_C2E,
>       EXCP_CACHE, /* 32 */
>       EXCP_DSPDIS,
> +    EXCP_TLBXI,
> +    EXCP_TLBRI,
>   
> -    EXCP_LAST = EXCP_DSPDIS,
> +    EXCP_LAST = EXCP_TLBRI,
>   };
>   /* Dummy exception for conditional stores.  */
>   #define EXCP_SC 0x100
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 6aa8c8a..fed28b4 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -273,7 +273,22 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
>           /* TLB match but 'D' bit is cleared */
>           exception = EXCP_LTLBL;
>           break;
> -
> +    case TLBRET_XI:
> +        /* Execute-Inhibit Exception */
> +        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
> +            exception = EXCP_TLBXI;
> +        } else {
> +            exception = EXCP_TLBL;
> +        }
> +        break;
> +    case TLBRET_RI:
> +        /* Read-Inhibit Exception */
> +        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
> +            exception = EXCP_TLBRI;
> +        } else {
> +            exception = EXCP_TLBL;
> +        }
> +        break;
>       }
>       /* Raise exception */
>       env->CP0_BadVAddr = address;
> @@ -404,6 +419,8 @@ static const char * const excp_names[EXCP_LAST + 1] = {
>       [EXCP_MDMX] = "MDMX",
>       [EXCP_C2E] = "precise coprocessor 2",
>       [EXCP_CACHE] = "cache error",
> +    [EXCP_TLBXI] = "TLB execute-inhibit",
> +    [EXCP_TLBRI] = "TLB read-inhibit",
>   };
>   
>   target_ulong exception_resume_pc (CPUMIPSState *env)
> @@ -622,6 +639,12 @@ void mips_cpu_do_interrupt(CPUState *cs)
>       case EXCP_C2E:
>           cause = 18;
>           goto set_EPC;
> +    case EXCP_TLBRI:
> +        cause = 19;
> +        goto set_EPC;
> +    case EXCP_TLBXI:
> +        cause = 20;
> +        goto set_EPC;
>       case EXCP_MDMX:
>           cause = 22;
>           goto set_EPC;

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
  2014-07-08  7:57 ` [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support Leon Alrae
@ 2014-10-16 10:52   ` Yongbok Kim
  2014-10-16 13:03     ` Leon Alrae
  0 siblings, 1 reply; 26+ messages in thread
From: Yongbok Kim @ 2014-10-16 10:52 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Hi Leon,

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

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

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

(((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)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
  2014-10-16 10:52   ` Yongbok Kim
@ 2014-10-16 13:03     ` Leon Alrae
  0 siblings, 0 replies; 26+ messages in thread
From: Leon Alrae @ 2014-10-16 13:03 UTC (permalink / raw)
  To: Yongbok Kim, qemu-devel; +Cc: aurelien

On 16/10/2014 11:52, Yongbok Kim wrote:
>> +    ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 1;
> 
> & 3
> 

Yeah, initially I tested TLBINV using mips64r6-generic cpu where
Config4.IE is set to 3, thus it worked...

Thanks,
Leon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 9/9] target-mips: update cpu_save/cpu_load to support new registers
  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
  0 siblings, 0 replies; 26+ messages in thread
From: Yongbok Kim @ 2014-10-16 13:06 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

EHINV bit from TLB also required to be saved/ restored.

Regards,
Yongbok


On 08/07/2014 08:57, Leon Alrae wrote:
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h     |    2 +-
>   target-mips/machine.c |   14 ++++++++++++++
>   2 files changed, 15 insertions(+), 1 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 656f5ca..23bb22c 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -557,7 +557,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
>   extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
>   extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
>   
> -#define CPU_SAVE_VERSION 4
> +#define CPU_SAVE_VERSION 5
>   
>   /* MMU modes definitions. We carefully match the indices with our
>      hflags layout. */
> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index 0496faa..576dc10 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -26,6 +26,8 @@ static void save_tc(QEMUFile *f, TCState *tc)
>       qemu_put_betls(f, &tc->CP0_TCScheFBack);
>       qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
>       qemu_put_betls(f, &tc->CP0_UserLocal);
> +    qemu_put_be32s(f, &tc->CP0_BadInstr);
> +    qemu_put_be32s(f, &tc->CP0_BadInstrP);
>   }
>   
>   static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> @@ -144,6 +146,9 @@ void cpu_save(QEMUFile *f, void *opaque)
>       qemu_put_sbe32s(f, &env->CP0_DataHi);
>       qemu_put_betls(f, &env->CP0_ErrorEPC);
>       qemu_put_sbe32s(f, &env->CP0_DESAVE);
> +    for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
> +        qemu_put_betls(f, &env->CP0_KScratch[i]);
> +    }
>   
>       /* Save inactive TC state */
>       for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
> @@ -177,6 +182,10 @@ static void load_tc(QEMUFile *f, TCState *tc, int version_id)
>       if (version_id >= 4) {
>           qemu_get_betls(f, &tc->CP0_UserLocal);
>       }
> +    if (version_id >= 5) {
> +        qemu_get_be32s(f, &tc->CP0_BadInstr);
> +        qemu_get_be32s(f, &tc->CP0_BadInstrP);
> +    }
>   }
>   
>   static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
> @@ -301,6 +310,11 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
>       qemu_get_sbe32s(f, &env->CP0_DataHi);
>       qemu_get_betls(f, &env->CP0_ErrorEPC);
>       qemu_get_sbe32s(f, &env->CP0_DESAVE);
> +    if (version_id >= 5) {
> +        for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
> +            qemu_get_betls(f, &env->CP0_KScratch[i]);
> +        }
> +    }
>   
>       /* Load inactive TC state */
>       for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers
  2014-10-14 13:59   ` Yongbok Kim
@ 2014-10-20 12:54     ` Leon Alrae
  0 siblings, 0 replies; 26+ messages in thread
From: Leon Alrae @ 2014-10-20 12:54 UTC (permalink / raw)
  To: Yongbok Kim, qemu-devel; +Cc: aurelien

Hi Yongbok,

On 14/10/2014 14:59, Yongbok Kim wrote:
>> @@ -4611,6 +4612,15 @@ static inline void gen_mtc0_store64 (TCGv arg,
>> target_ulong off)
>>       tcg_gen_st_tl(arg, cpu_env, off);
>>   }
>>   +static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
>> +{
>> +    if (ctx->insn_flags & ISA_MIPS32R6) {
>> +        tcg_gen_movi_tl(arg, 0);
>> +    } else {
>> +        tcg_gen_movi_tl(arg, ~0);
>> +    }
>> +}
>> +
> 
> Not related with KScratch registers. It would be better to be a separate
> patch or
> as part of the patch [PATCH 5/6] target-mips: correctly handle access to
> unimplemented CP0 register.

Actually it is related to all cp0 registers and KScratch is the first
cp0 register added in the series, thus in my opinion this is a good
place for including the definition of gen_mfc0_unimplemented(). The
patch you mentioned is correcting the remaining (existing before this
patch) cp0 registers.

Regards,
Leon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
  2014-10-15 12:24   ` Yongbok Kim
@ 2014-10-24 14:16     ` Leon Alrae
  2014-10-24 14:27       ` Yongbok Kim
  0 siblings, 1 reply; 26+ messages in thread
From: Leon Alrae @ 2014-10-24 14:16 UTC (permalink / raw)
  To: Yongbok Kim, qemu-devel; +Cc: aurelien

On 15/10/2014 13:24, Yongbok Kim wrote:
> 
> On 08/07/2014 08:57, Leon Alrae wrote:
>> In Revision 3 of the architecture, the RI and XI bits were added to
>> the TLB
>> to enable more secure access of memory pages. These bits (along with
>> the Dirty
>> bit) allow the implementation of read-only, write-only, no-execute access
>> policies for mapped pages.
>>
>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>> ---
>>   target-mips/cpu.h       |   11 +++++++++++
>>   target-mips/helper.c    |   11 ++++++++++-
>>   target-mips/op_helper.c |    8 ++++++++
>>   3 files changed, 29 insertions(+), 1 deletions(-)
>>
>> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>> index 4f6aa5b..5afafd7 100644
>> --- a/target-mips/cpu.h
>> +++ b/target-mips/cpu.h
>> @@ -30,6 +30,10 @@ struct r4k_tlb_t {
>>       uint_fast16_t V1:1;
>>       uint_fast16_t D0:1;
>>       uint_fast16_t D1:1;
>> +    uint_fast16_t XI0:1;
>> +    uint_fast16_t XI1:1;
>> +    uint_fast16_t RI0:1;
>> +    uint_fast16_t RI1:1;
>>       target_ulong PFN[2];
>>   };
>>   @@ -229,6 +233,13 @@ struct CPUMIPSState {
>>   #define CP0VPEOpt_DWX0    0
>>       target_ulong CP0_EntryLo0;
>>       target_ulong CP0_EntryLo1;
>> +#if defined(TARGET_MIPS64)
>> +# define CP0EnLo_RI 63
>> +# define CP0EnLo_XI 62
>> +#else
>> +# define CP0EnLo_RI 31
>> +# define CP0EnLo_XI 30
>> +#endif
>>       target_ulong CP0_Context;
>>       target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>>       int32_t CP0_PageMask;
>> diff --git a/target-mips/helper.c b/target-mips/helper.c
>> index 9871273..6aa8c8a 100644
>> --- a/target-mips/helper.c
>> +++ b/target-mips/helper.c
>> @@ -27,6 +27,8 @@
>>   #include "sysemu/kvm.h"
>>     enum {
>> +    TLBRET_XI = -6,
>> +    TLBRET_RI = -5,
>>       TLBRET_DIRTY = -4,
>>       TLBRET_INVALID = -3,
>>       TLBRET_NOMATCH = -2,
>> @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr
>> *physical, int *prot,
>>               /* TLB match */
>>               int n = !!(address & mask & ~(mask >> 1));
>>               /* Check access rights */
>> -            if (!(n ? tlb->V1 : tlb->V0))
>> +            if (!(n ? tlb->V1 : tlb->V0)) {
>>                   return TLBRET_INVALID;
>> +            }
>> +            if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
>> +                return TLBRET_XI;
>> +            }
>> +            if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
>> +                return TLBRET_RI;
> 
> PC relative loads are allowed where execute is allowed (even though RI
> is 1).
> Rather than just return RI here have to check XI and its OP code.

This is true only for MIPS16 PC-relative loads. New R6 PC-relative loads
do cause TLBRI exceptions. Thus in context of Release 6 current
implementation is correct. I agree this will need to be corrected for
MIPS16, but not necessarily in this patchset.

Regards,
Leon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
  2014-10-24 14:16     ` Leon Alrae
@ 2014-10-24 14:27       ` Yongbok Kim
  0 siblings, 0 replies; 26+ messages in thread
From: Yongbok Kim @ 2014-10-24 14:27 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

On 24/10/2014 15:16, Leon Alrae wrote:
> On 15/10/2014 13:24, Yongbok Kim wrote:
>> On 08/07/2014 08:57, Leon Alrae wrote:
>>> In Revision 3 of the architecture, the RI and XI bits were added to
>>> the TLB
>>> to enable more secure access of memory pages. These bits (along with
>>> the Dirty
>>> bit) allow the implementation of read-only, write-only, no-execute access
>>> policies for mapped pages.
>>>
>>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>>> ---
>>>    target-mips/cpu.h       |   11 +++++++++++
>>>    target-mips/helper.c    |   11 ++++++++++-
>>>    target-mips/op_helper.c |    8 ++++++++
>>>    3 files changed, 29 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>>> index 4f6aa5b..5afafd7 100644
>>> --- a/target-mips/cpu.h
>>> +++ b/target-mips/cpu.h
>>> @@ -30,6 +30,10 @@ struct r4k_tlb_t {
>>>        uint_fast16_t V1:1;
>>>        uint_fast16_t D0:1;
>>>        uint_fast16_t D1:1;
>>> +    uint_fast16_t XI0:1;
>>> +    uint_fast16_t XI1:1;
>>> +    uint_fast16_t RI0:1;
>>> +    uint_fast16_t RI1:1;
>>>        target_ulong PFN[2];
>>>    };
>>>    @@ -229,6 +233,13 @@ struct CPUMIPSState {
>>>    #define CP0VPEOpt_DWX0    0
>>>        target_ulong CP0_EntryLo0;
>>>        target_ulong CP0_EntryLo1;
>>> +#if defined(TARGET_MIPS64)
>>> +# define CP0EnLo_RI 63
>>> +# define CP0EnLo_XI 62
>>> +#else
>>> +# define CP0EnLo_RI 31
>>> +# define CP0EnLo_XI 30
>>> +#endif
>>>        target_ulong CP0_Context;
>>>        target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>>>        int32_t CP0_PageMask;
>>> diff --git a/target-mips/helper.c b/target-mips/helper.c
>>> index 9871273..6aa8c8a 100644
>>> --- a/target-mips/helper.c
>>> +++ b/target-mips/helper.c
>>> @@ -27,6 +27,8 @@
>>>    #include "sysemu/kvm.h"
>>>      enum {
>>> +    TLBRET_XI = -6,
>>> +    TLBRET_RI = -5,
>>>        TLBRET_DIRTY = -4,
>>>        TLBRET_INVALID = -3,
>>>        TLBRET_NOMATCH = -2,
>>> @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr
>>> *physical, int *prot,
>>>                /* TLB match */
>>>                int n = !!(address & mask & ~(mask >> 1));
>>>                /* Check access rights */
>>> -            if (!(n ? tlb->V1 : tlb->V0))
>>> +            if (!(n ? tlb->V1 : tlb->V0)) {
>>>                    return TLBRET_INVALID;
>>> +            }
>>> +            if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
>>> +                return TLBRET_XI;
>>> +            }
>>> +            if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
>>> +                return TLBRET_RI;
>> PC relative loads are allowed where execute is allowed (even though RI
>> is 1).
>> Rather than just return RI here have to check XI and its OP code.
> This is true only for MIPS16 PC-relative loads. New R6 PC-relative loads
> do cause TLBRI exceptions. Thus in context of Release 6 current
> implementation is correct. I agree this will need to be corrected for
> MIPS16, but not necessarily in this patchset.
>
> Regards,
> Leon
>
Agreed.

Regards,
Yongbok

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2014-10-24 14:27 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support Leon Alrae
2014-10-16 10:52   ` 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

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.