All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6
@ 2014-06-19 14:45 Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers Leon Alrae
                   ` (11 more replies)
  0 siblings, 12 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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.
The last patch in the series enables them in MIPS64R6 CPU config therefore
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

Leon Alrae (12):
  target-mips: add KScratch registers
  target-mips: update cpu_save/cpu_load to support KScratch registers
  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: save cpu state if instruction can cause an exception
  target-mips: update cpu_save/cpu_load to support BadInstr registers
  target-mips: enable features in MIPS32R5-generic core
  target-mips: enable features in MIPS64R6-generic core

 disas/mips.c                 |    2 +
 target-mips/cpu.h            |   36 ++++++++-
 target-mips/helper.c         |   88 ++++++++++++++++---
 target-mips/helper.h         |    7 ++
 target-mips/machine.c        |   16 ++++
 target-mips/op_helper.c      |   98 +++++++++++++++++++--
 target-mips/translate.c      |  196 ++++++++++++++++++++++++++++++++++++++++--
 target-mips/translate_init.c |   20 ++++-
 8 files changed, 427 insertions(+), 36 deletions(-)

-- 
1.7.5.4

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

* [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-20 22:02   ` Aurelien Jarno
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support " Leon Alrae
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 |   27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 217c09b..fae94ed 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;
@@ -374,6 +376,7 @@ struct CPUMIPSState {
 #define CP0C3_TL   0
     uint32_t CP0_Config4;
     uint32_t CP0_Config4_rw_bitmask;
+#define CP0C4_KScrExist 16
 #define CP0C4_M    31
     uint32_t CP0_Config5;
     uint32_t CP0_Config5_rw_bitmask;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index a8dc529..4e90c08 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1174,6 +1174,7 @@ typedef struct DisasContext {
     int bstate;
     target_ulong btarget;
     bool ulri;
+    int32_t kscrexist;
 } DisasContext;
 
 enum {
@@ -5198,6 +5199,12 @@ 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:
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            tcg_gen_ext32s_tl(arg, arg);
+            rn = "KScratch";
+            break;
         default:
             goto die;
         }
@@ -5806,6 +5813,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;
         }
@@ -6393,6 +6407,11 @@ 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:
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            rn = "KScratch";
+            break;
         default:
             goto die;
         }
@@ -6992,6 +7011,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;
         }
@@ -17499,6 +17525,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.insn_flags = env->insn_flags;
     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] 20+ messages in thread

* [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support KScratch registers
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 17:43   ` Richard Henderson
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 03/12] target-mips: distinguish between data load and instruction fetch Leon Alrae
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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/machine.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/target-mips/machine.c b/target-mips/machine.c
index 0496faa..966c5ef 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -144,6 +144,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++)
@@ -301,6 +304,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 >= 4) {
+        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] 20+ messages in thread

* [Qemu-devel] [PATCH 03/12] target-mips: distinguish between data load and instruction fetch
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support " Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 04/12] target-mips: add RI and XI fields to TLB entry Leon Alrae
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 |   27 ++++++++++++++++-----------
 1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 064622c..b59ac13 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -26,6 +26,12 @@
 #include "cpu.h"
 
 enum {
+    MIPS_DATA_LOAD  = 0,
+    MIPS_DATA_STORE = 1,
+    MIPS_INST_FETCH = 2
+};
+
+enum {
     TLBRET_DIRTY = -4,
     TLBRET_INVALID = -3,
     TLBRET_NOMATCH = -2,
@@ -86,7 +92,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 != MIPS_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
                 *physical = tlb->PFN[n] | (address & (mask >> 1));
                 *prot = PAGE_READ;
                 if (n ? tlb->D1 : tlb->D0)
@@ -212,25 +218,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 == MIPS_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 == MIPS_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 == MIPS_DATA_STORE) {
             exception = EXCP_TLBS;
-        else
+        } else {
             exception = EXCP_TLBL;
+        }
         break;
     case TLBRET_DIRTY:
         /* TLB match but 'D' bit is cleared */
@@ -287,8 +296,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()
@@ -322,8 +329,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] 20+ messages in thread

* [Qemu-devel] [PATCH 04/12] target-mips: add RI and XI fields to TLB entry
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (2 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 03/12] target-mips: distinguish between data load and instruction fetch Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 05/12] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1} Leon Alrae
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 fae94ed..56d7fc8 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 b59ac13..643c7cc 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -32,6 +32,8 @@ enum {
 };
 
 enum {
+    TLBRET_XI = -6,
+    TLBRET_RI = -5,
     TLBRET_DIRTY = -4,
     TLBRET_INVALID = -3,
     TLBRET_NOMATCH = -2,
@@ -90,8 +92,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 == MIPS_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
+                return TLBRET_XI;
+            }
+            if (rw == MIPS_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
+                return TLBRET_RI;
+            }
             if (rw != MIPS_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 b050d15..19d795c 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1850,10 +1850,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;
 }
 
@@ -1965,8 +1969,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] 20+ messages in thread

* [Qemu-devel] [PATCH 05/12] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1}
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (3 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 04/12] target-mips: add RI and XI fields to TLB entry Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 06/12] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions Leon Alrae
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 56d7fc8..6de51b1 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 8af957f..c30104e 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 19d795c..4570af4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1100,9 +1100,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 & (3 << 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;
@@ -1267,9 +1276,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 & (3 << 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);
@@ -1286,7 +1304,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 4e90c08..4ddb83e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1175,6 +1175,7 @@ typedef struct DisasContext {
     target_ulong btarget;
     bool ulri;
     int32_t kscrexist;
+    bool rxi;
 } DisasContext;
 
 enum {
@@ -4699,6 +4700,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;
@@ -4745,6 +4755,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;
@@ -6512,7 +6531,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:
@@ -6557,7 +6576,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:
@@ -17526,6 +17545,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);
@@ -17905,6 +17925,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 0adbb19..71cb350 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] 20+ messages in thread

* [Qemu-devel] [PATCH 06/12] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (4 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 05/12] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1} Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 07/12] target-mips: add TLBINV support Leon Alrae
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 6de51b1..78158bd 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;
@@ -648,8 +649,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 643c7cc..e9f31ca 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -254,7 +254,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;
@@ -385,6 +400,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)
@@ -603,6 +620,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] 20+ messages in thread

* [Qemu-devel] [PATCH 07/12] target-mips: add TLBINV support
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (5 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 06/12] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support Leon Alrae
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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 78158bd..14edf57 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_KScrExist 16
+#define CP0C4_IE   29
 #define CP0C4_M    31
     uint32_t CP0_Config5;
     uint32_t CP0_Config5_rw_bitmask;
@@ -531,6 +536,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 e9f31ca..ab9217f 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -88,7 +88,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 c30104e..cb6e4b4 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -343,6 +343,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 4570af4..dcdeeef 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1362,10 +1362,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
@@ -1859,6 +1863,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;
@@ -1880,6 +1889,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;
@@ -1941,7 +1975,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;
@@ -1985,16 +2019,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)
@@ -2017,6 +2058,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 4ddb83e..e511c75 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,
@@ -1176,6 +1178,7 @@ typedef struct DisasContext {
     bool ulri;
     int32_t kscrexist;
     bool rxi;
+    bool ie;
 } DisasContext;
 
 enum {
@@ -7548,6 +7551,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)
@@ -17546,6 +17567,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 71cb350..561eeb0 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -656,6 +656,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] 20+ messages in thread

* [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (6 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 07/12] target-mips: add TLBINV support Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 22:13   ` Aurelien Jarno
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception Leon Alrae
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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.

The BadInstr and BadInstrP registers are provided to allow acceleration of
instruction emulation.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |    6 +++
 target-mips/helper.c    |   23 +++++++++++
 target-mips/translate.c |  102 ++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 125 insertions(+), 6 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 14edf57..785a29b 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -177,6 +177,10 @@ struct TCState {
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
     target_ulong CP0_UserLocal;
+    uint32_t last_instr;
+    uint32_t CP0_BadInstr;
+    uint32_t last_branch;
+    uint32_t CP0_BadInstrP;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
@@ -383,6 +387,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
diff --git a/target-mips/helper.c b/target-mips/helper.c
index ab9217f..1a3a6af 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -439,6 +439,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
 #if !defined(CONFIG_USER_ONLY)
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
+    int update_badinstr = 0;
     target_ulong offset;
     int cause = -1;
     const char *name;
@@ -547,9 +548,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_LTLBL:
         cause = 1;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_TLBL:
         cause = 2;
+        update_badinstr = 1;
         if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
 #if defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
@@ -567,6 +570,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_TLBS:
         cause = 3;
+        update_badinstr = 1;
         if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
 #if defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
@@ -584,9 +588,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
         goto set_EPC;
     case EXCP_AdEL:
         cause = 4;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_AdES:
         cause = 5;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_IBE:
         cause = 6;
@@ -596,35 +602,44 @@ 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;
+        update_badinstr = 1;
         goto set_EPC;
     case EXCP_MDMX:
         cause = 22;
@@ -650,6 +665,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
             offset = 0x20000100;
         }
  set_EPC:
+        if (env->CP0_Config3 & (1 << CP0C3_BI) && update_badinstr) {
+            env->active_tc.CP0_BadInstr = env->active_tc.last_instr;
+        }
+        if (env->CP0_Config3 & (1 << CP0C3_BP) && update_badinstr &&
+            env->hflags & MIPS_HFLAG_BMASK) {
+            env->active_tc.CP0_BadInstrP = env->active_tc.last_branch;
+        }
+
         if (!(env->CP0_Status & (1 << CP0St_EXL))) {
             env->CP0_EPC = exception_resume_pc(env);
             if (env->hflags & MIPS_HFLAG_BMASK) {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index e511c75..b27d22e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1116,6 +1116,8 @@ static TCGv cpu_dspctrl, btarget, bcond;
 static TCGv_i32 hflags;
 static TCGv_i32 fpu_fcr0, fpu_fcr31;
 static TCGv_i64 fpu_f64[32];
+static TCGv_i32 last_instr;
+static TCGv_i32 last_branch;
 
 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
@@ -1167,7 +1169,8 @@ static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
 typedef struct DisasContext {
     struct TranslationBlock *tb;
     target_ulong pc, saved_pc;
-    uint32_t opcode;
+    uint32_t opcode, saved_opcode;
+    uint32_t opcode_branch, saved_opcode_branch;
     int singlestep_enabled;
     int insn_flags;
     /* Routine used to access memory */
@@ -1179,6 +1182,8 @@ typedef struct DisasContext {
     int32_t kscrexist;
     bool rxi;
     bool ie;
+    bool bi;
+    bool bp;
 } DisasContext;
 
 enum {
@@ -1391,6 +1396,15 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
         gen_save_pc(ctx->pc);
         ctx->saved_pc = ctx->pc;
     }
+    if (ctx->bi && ctx->opcode != ctx->saved_opcode) {
+        tcg_gen_movi_i32(last_instr, ctx->opcode);
+        ctx->saved_opcode = ctx->opcode;
+    }
+    if (ctx->bp && ctx->hflags & MIPS_HFLAG_BMASK &&
+        ctx->opcode_branch != ctx->saved_opcode_branch) {
+        tcg_gen_movi_i32(last_branch, ctx->opcode_branch);
+        ctx->saved_opcode_branch = ctx->opcode_branch;
+    }
     if (ctx->hflags != ctx->saved_hflags) {
         tcg_gen_movi_i32(hflags, ctx->hflags);
         ctx->saved_hflags = ctx->hflags;
@@ -4160,6 +4174,9 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
 #endif
         generate_exception(ctx, EXCP_RI);
         goto out;
+    } else {
+        /* capture branch opcode prior to delay slot */
+        ctx->opcode_branch = ctx->opcode;
     }
 
     /* Load needed operands */
@@ -4868,9 +4885,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ext32s_tl(arg, arg);
             rn = "BadVAddr";
             break;
+        case 1:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstr));
+            rn = "BadInstr";
+            break;
+        case 2:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstrP));
+            rn = "BadInstrP";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 9:
         switch (sel) {
@@ -5464,8 +5491,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) {
@@ -6090,6 +6131,16 @@ 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:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstr));
+            rn = "BadInstr";
+            break;
+        case 2:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstrP));
+            rn = "BadInstrP";
+            break;
         default:
             goto die;
         }
@@ -6671,8 +6722,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) {
@@ -7633,6 +7698,11 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
     const char *opn = "cp1 cond branch";
     TCGv_i32 t0 = tcg_temp_new_i32();
 
+    if (!(ctx->hflags & MIPS_HFLAG_BMASK)) {
+        /* capture branch opcode prior to delay slot */
+        ctx->opcode_branch = ctx->opcode;
+    }
+
     if (cc != 0)
         check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
 
@@ -7747,6 +7817,12 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
     const char *opn = "cp1 cond branch";
 
     TCGv_i64 t0 = tcg_temp_new_i64();
+
+    if (!(ctx->hflags & MIPS_HFLAG_BMASK)) {
+        /* capture branch opcode prior to delay slot */
+        ctx->opcode_branch = ctx->opcode;
+    }
+
     gen_load_fpr64(ctx, t0, ft);
     tcg_gen_andi_i64(t0, t0, 1);
 
@@ -17568,6 +17644,12 @@ 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;
+    ctx.opcode = 0;
+    ctx.saved_opcode = 0;
+    ctx.opcode_branch = 0;
+    ctx.saved_opcode_branch = 0;
     /* 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);
@@ -17869,6 +17951,14 @@ void mips_tcg_init(void)
     fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
                                        offsetof(CPUMIPSState, active_fpu.fcr31),
                                        "fcr31");
+    last_instr = tcg_global_mem_new_i32(TCG_AREG0,
+                                        offsetof(CPUMIPSState,
+                                                 active_tc.last_instr),
+                                        "last_instr");
+    last_branch = tcg_global_mem_new_i32(TCG_AREG0,
+                                         offsetof(CPUMIPSState,
+                                                  active_tc.last_branch),
+                                         "last_branch");
 
     inited = 1;
 }
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (7 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 22:13   ` Aurelien Jarno
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 10/12] target-mips: update cpu_save/cpu_load to support BadInstr registers Leon Alrae
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

Execution of these instructions can trigger exceptions which are supposed
to update BadInstr/BadInstrP. Therefore saving cpu state in order capture
the opcode.

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

diff --git a/target-mips/translate.c b/target-mips/translate.c
index b27d22e..6835504 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1847,11 +1847,13 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_LWU:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
         gen_store_gpr(t0, rt);
         opn = "lwu";
         break;
     case OPC_LD:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
         gen_store_gpr(t0, rt);
         opn = "ld";
@@ -1864,6 +1866,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "lld";
         break;
     case OPC_LDL:
+        save_cpu_state(ctx, 0);
         t1 = tcg_temp_new();
         tcg_gen_andi_tl(t1, t0, 7);
 #ifndef TARGET_WORDS_BIGENDIAN
@@ -1885,6 +1888,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "ldl";
         break;
     case OPC_LDR:
+        save_cpu_state(ctx, 0);
         t1 = tcg_temp_new();
         tcg_gen_andi_tl(t1, t0, 7);
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -1906,6 +1910,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "ldr";
         break;
     case OPC_LDPC:
+        save_cpu_state(ctx, 0);
         t1 = tcg_const_tl(pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
         tcg_temp_free(t1);
@@ -1915,6 +1920,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         break;
 #endif
     case OPC_LWPC:
+        save_cpu_state(ctx, 0);
         t1 = tcg_const_tl(pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
         tcg_temp_free(t1);
@@ -1923,31 +1929,37 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "lwpc";
         break;
     case OPC_LW:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
         gen_store_gpr(t0, rt);
         opn = "lw";
         break;
     case OPC_LH:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
         gen_store_gpr(t0, rt);
         opn = "lh";
         break;
     case OPC_LHU:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
         gen_store_gpr(t0, rt);
         opn = "lhu";
         break;
     case OPC_LB:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
         gen_store_gpr(t0, rt);
         opn = "lb";
         break;
     case OPC_LBU:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
         gen_store_gpr(t0, rt);
         opn = "lbu";
         break;
     case OPC_LWL:
+        save_cpu_state(ctx, 0);
         t1 = tcg_temp_new();
         tcg_gen_andi_tl(t1, t0, 3);
 #ifndef TARGET_WORDS_BIGENDIAN
@@ -1970,6 +1982,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "lwl";
         break;
     case OPC_LWR:
+        save_cpu_state(ctx, 0);
         t1 = tcg_temp_new();
         tcg_gen_andi_tl(t1, t0, 3);
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -2017,6 +2030,7 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_SD:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
         opn = "sd";
         break;
@@ -2032,14 +2046,17 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
         break;
 #endif
     case OPC_SW:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
         opn = "sw";
         break;
     case OPC_SH:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
         opn = "sh";
         break;
     case OPC_SB:
+        save_cpu_state(ctx, 0);
         tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
         opn = "sb";
         break;
@@ -8370,6 +8387,8 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
     enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
     uint32_t func = ctx->opcode & 0x3f;
 
+    save_cpu_state(ctx, 0);
+
     switch (op1) {
     case OPC_ADD_S:
         {
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH 10/12] target-mips: update cpu_save/cpu_load to support BadInstr registers
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (8 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 11/12] target-mips: enable features in MIPS32R5-generic core Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 12/12] target-mips: enable features in MIPS64R6-generic core Leon Alrae
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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/machine.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/target-mips/machine.c b/target-mips/machine.c
index 966c5ef..a51b344 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -26,6 +26,10 @@ 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->last_instr);
+    qemu_put_be32s(f, &tc->CP0_BadInstr);
+    qemu_put_be32s(f, &tc->last_branch);
+    qemu_put_be32s(f, &tc->CP0_BadInstrP);
 }
 
 static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -179,6 +183,10 @@ static void load_tc(QEMUFile *f, TCState *tc, int version_id)
     qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
     if (version_id >= 4) {
         qemu_get_betls(f, &tc->CP0_UserLocal);
+        qemu_get_be32s(f, &tc->last_instr);
+        qemu_get_be32s(f, &tc->CP0_BadInstr);
+        qemu_get_be32s(f, &tc->last_branch);
+        qemu_get_be32s(f, &tc->CP0_BadInstrP);
     }
 }
 
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH 11/12] target-mips: enable features in MIPS32R5-generic core
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (9 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 10/12] target-mips: update cpu_save/cpu_load to support BadInstr registers Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 12/12] target-mips: enable features in MIPS64R6-generic core Leon Alrae
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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/translate_init.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 561eeb0..1f199fd 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -357,8 +357,10 @@ static const mips_def_t mips_defs[] =
                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
                        (1 << CP0C1_CA),
         .CP0_Config2 = MIPS_CONFIG2,
-        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M),
-        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M),
+        .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
+                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
+        .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
+                       (3 << CP0C4_IE) | (1U << CP0C4_M),
         .CP0_Config4_rw_bitmask = 0,
         .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR),
         .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) |
@@ -370,6 +372,9 @@ static const mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x3778FF1F,
+        .CP0_PageGrain = (1 << CP0PG_XIE) | (1 << CP0PG_RIE) | (1 << CP0PG_IEC),
+        .CP0_PageGrain_rw_bitmask = (1 << CP0PG_XIE) | (1 << CP0PG_RIE) |
+                                    (1 << CP0PG_IEC),
         .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) |
                     (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x93 << FCR0_PRID),
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH 12/12] target-mips: enable features in MIPS64R6-generic core
  2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
                   ` (10 preceding siblings ...)
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 11/12] target-mips: enable features in MIPS32R5-generic core Leon Alrae
@ 2014-06-19 14:45 ` Leon Alrae
  11 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-06-19 14:45 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/translate_init.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 1f199fd..0deaee7 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -534,12 +534,17 @@ static const mips_def_t mips_defs[] =
                        (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
                        (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
         .CP0_Config2 = MIPS_CONFIG2,
-        .CP0_Config3 = MIPS_CONFIG3,
+        .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
+                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
+        .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
+                       (3 << CP0C4_IE),
         .CP0_LLAddr_rw_bitmask = 0,
         .CP0_LLAddr_shift = 0,
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x30D8FFFF,
+        .CP0_PageGrain = (1 << CP0PG_XIE) | (1 << CP0PG_RIE) | (1 << CP0PG_IEC),
+        .CP0_PageGrain_rw_bitmask = 0,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
                     (0x0 << FCR0_REV),
-- 
1.7.5.4

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

* Re: [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support KScratch registers
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support " Leon Alrae
@ 2014-06-19 17:43   ` Richard Henderson
  2014-07-08  8:31     ` Leon Alrae
  0 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2014-06-19 17:43 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: yongbok.kim, cristian.cuna, aurelien

You must update CPU_SAVE_VERSION when you change the contents of the save data.

For extra credit, consider updating target-mips to VMStateDescription structure(s).


r~

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

* Re: [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support Leon Alrae
@ 2014-06-19 22:13   ` Aurelien Jarno
  2014-07-08  8:07     ` Leon Alrae
  0 siblings, 1 reply; 20+ messages in thread
From: Aurelien Jarno @ 2014-06-19 22:13 UTC (permalink / raw)
  To: Leon Alrae; +Cc: yongbok.kim, cristian.cuna, qemu-devel

On Thu, Jun 19, 2014 at 03:45:39PM +0100, 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.
> 
> The BadInstr and BadInstrP registers are provided to allow acceleration of
> instruction emulation.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/cpu.h       |    6 +++
>  target-mips/helper.c    |   23 +++++++++++
>  target-mips/translate.c |  102 ++++++++++++++++++++++++++++++++++++++++++++---
>  3 files changed, 125 insertions(+), 6 deletions(-)

I don't think this should implemented that way, as it would have a
significant impact on the performances. Given we have the fault address
(we fill EPC), we can fetch the corresponding opcode. There might be
some code change to do for the branches, so that we can get the
informations we need from re-translation (this might also simplify the
current branches code).

> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 14edf57..785a29b 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -177,6 +177,10 @@ struct TCState {
>      target_ulong CP0_TCScheFBack;
>      int32_t CP0_Debug_tcstatus;
>      target_ulong CP0_UserLocal;
> +    uint32_t last_instr;
> +    uint32_t CP0_BadInstr;
> +    uint32_t last_branch;
> +    uint32_t CP0_BadInstrP;
>  };
>  
>  typedef struct CPUMIPSState CPUMIPSState;
> @@ -383,6 +387,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
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index ab9217f..1a3a6af 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -439,6 +439,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
>  #if !defined(CONFIG_USER_ONLY)
>      MIPSCPU *cpu = MIPS_CPU(cs);
>      CPUMIPSState *env = &cpu->env;
> +    int update_badinstr = 0;
>      target_ulong offset;
>      int cause = -1;
>      const char *name;
> @@ -547,9 +548,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
>          goto set_EPC;
>      case EXCP_LTLBL:
>          cause = 1;
> +        update_badinstr = 1;
>          goto set_EPC;
>      case EXCP_TLBL:
>          cause = 2;
> +        update_badinstr = 1;
>          if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
>  #if defined(TARGET_MIPS64)
>              int R = env->CP0_BadVAddr >> 62;
> @@ -567,6 +570,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
>          goto set_EPC;
>      case EXCP_TLBS:
>          cause = 3;
> +        update_badinstr = 1;
>          if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
>  #if defined(TARGET_MIPS64)
>              int R = env->CP0_BadVAddr >> 62;
> @@ -584,9 +588,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
>          goto set_EPC;
>      case EXCP_AdEL:
>          cause = 4;
> +        update_badinstr = 1;
>          goto set_EPC;
>      case EXCP_AdES:
>          cause = 5;
> +        update_badinstr = 1;
>          goto set_EPC;
>      case EXCP_IBE:
>          cause = 6;
> @@ -596,35 +602,44 @@ 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;
> +        update_badinstr = 1;
>          goto set_EPC;
>      case EXCP_MDMX:
>          cause = 22;
> @@ -650,6 +665,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
>              offset = 0x20000100;
>          }
>   set_EPC:
> +        if (env->CP0_Config3 & (1 << CP0C3_BI) && update_badinstr) {
> +            env->active_tc.CP0_BadInstr = env->active_tc.last_instr;
> +        }
> +        if (env->CP0_Config3 & (1 << CP0C3_BP) && update_badinstr &&
> +            env->hflags & MIPS_HFLAG_BMASK) {
> +            env->active_tc.CP0_BadInstrP = env->active_tc.last_branch;
> +        }
> +
>          if (!(env->CP0_Status & (1 << CP0St_EXL))) {
>              env->CP0_EPC = exception_resume_pc(env);
>              if (env->hflags & MIPS_HFLAG_BMASK) {
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index e511c75..b27d22e 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1116,6 +1116,8 @@ static TCGv cpu_dspctrl, btarget, bcond;
>  static TCGv_i32 hflags;
>  static TCGv_i32 fpu_fcr0, fpu_fcr31;
>  static TCGv_i64 fpu_f64[32];
> +static TCGv_i32 last_instr;
> +static TCGv_i32 last_branch;
>  
>  static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
>  static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
> @@ -1167,7 +1169,8 @@ static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
>  typedef struct DisasContext {
>      struct TranslationBlock *tb;
>      target_ulong pc, saved_pc;
> -    uint32_t opcode;
> +    uint32_t opcode, saved_opcode;
> +    uint32_t opcode_branch, saved_opcode_branch;
>      int singlestep_enabled;
>      int insn_flags;
>      /* Routine used to access memory */
> @@ -1179,6 +1182,8 @@ typedef struct DisasContext {
>      int32_t kscrexist;
>      bool rxi;
>      bool ie;
> +    bool bi;
> +    bool bp;
>  } DisasContext;
>  
>  enum {
> @@ -1391,6 +1396,15 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
>          gen_save_pc(ctx->pc);
>          ctx->saved_pc = ctx->pc;
>      }
> +    if (ctx->bi && ctx->opcode != ctx->saved_opcode) {
> +        tcg_gen_movi_i32(last_instr, ctx->opcode);
> +        ctx->saved_opcode = ctx->opcode;
> +    }
> +    if (ctx->bp && ctx->hflags & MIPS_HFLAG_BMASK &&
> +        ctx->opcode_branch != ctx->saved_opcode_branch) {
> +        tcg_gen_movi_i32(last_branch, ctx->opcode_branch);
> +        ctx->saved_opcode_branch = ctx->opcode_branch;
> +    }
>      if (ctx->hflags != ctx->saved_hflags) {
>          tcg_gen_movi_i32(hflags, ctx->hflags);
>          ctx->saved_hflags = ctx->hflags;
> @@ -4160,6 +4174,9 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
>  #endif
>          generate_exception(ctx, EXCP_RI);
>          goto out;
> +    } else {
> +        /* capture branch opcode prior to delay slot */
> +        ctx->opcode_branch = ctx->opcode;
>      }
>  
>      /* Load needed operands */
> @@ -4868,9 +4885,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              tcg_gen_ext32s_tl(arg, arg);
>              rn = "BadVAddr";
>              break;
> +        case 1:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstr));
> +            rn = "BadInstr";
> +            break;
> +        case 2:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstrP));
> +            rn = "BadInstrP";
> +            break;
>          default:
>              goto die;
> -       }
> +        }
>          break;
>      case 9:
>          switch (sel) {
> @@ -5464,8 +5491,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) {
> @@ -6090,6 +6131,16 @@ 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:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstr));
> +            rn = "BadInstr";
> +            break;
> +        case 2:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstrP));
> +            rn = "BadInstrP";
> +            break;
>          default:
>              goto die;
>          }
> @@ -6671,8 +6722,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) {
> @@ -7633,6 +7698,11 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
>      const char *opn = "cp1 cond branch";
>      TCGv_i32 t0 = tcg_temp_new_i32();
>  
> +    if (!(ctx->hflags & MIPS_HFLAG_BMASK)) {
> +        /* capture branch opcode prior to delay slot */
> +        ctx->opcode_branch = ctx->opcode;
> +    }
> +
>      if (cc != 0)
>          check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
>  
> @@ -7747,6 +7817,12 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
>      const char *opn = "cp1 cond branch";
>  
>      TCGv_i64 t0 = tcg_temp_new_i64();
> +
> +    if (!(ctx->hflags & MIPS_HFLAG_BMASK)) {
> +        /* capture branch opcode prior to delay slot */
> +        ctx->opcode_branch = ctx->opcode;
> +    }
> +
>      gen_load_fpr64(ctx, t0, ft);
>      tcg_gen_andi_i64(t0, t0, 1);
>  
> @@ -17568,6 +17644,12 @@ 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;
> +    ctx.opcode = 0;
> +    ctx.saved_opcode = 0;
> +    ctx.opcode_branch = 0;
> +    ctx.saved_opcode_branch = 0;
>      /* 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);
> @@ -17869,6 +17951,14 @@ void mips_tcg_init(void)
>      fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
>                                         offsetof(CPUMIPSState, active_fpu.fcr31),
>                                         "fcr31");
> +    last_instr = tcg_global_mem_new_i32(TCG_AREG0,
> +                                        offsetof(CPUMIPSState,
> +                                                 active_tc.last_instr),
> +                                        "last_instr");
> +    last_branch = tcg_global_mem_new_i32(TCG_AREG0,
> +                                         offsetof(CPUMIPSState,
> +                                                  active_tc.last_branch),
> +                                         "last_branch");
>  
>      inited = 1;
>  }
> -- 
> 1.7.5.4
> 
> 

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception Leon Alrae
@ 2014-06-19 22:13   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2014-06-19 22:13 UTC (permalink / raw)
  To: Leon Alrae; +Cc: yongbok.kim, cristian.cuna, qemu-devel

On Thu, Jun 19, 2014 at 03:45:40PM +0100, Leon Alrae wrote:
> Execution of these instructions can trigger exceptions which are supposed
> to update BadInstr/BadInstrP. Therefore saving cpu state in order capture
> the opcode.

As said in the previous patch, the performance impact would be quite
significant, now generating a few additional move per load store.

> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/translate.c |   19 +++++++++++++++++++
>  1 files changed, 19 insertions(+), 0 deletions(-)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index b27d22e..6835504 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1847,11 +1847,13 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>      switch (opc) {
>  #if defined(TARGET_MIPS64)
>      case OPC_LWU:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
>          gen_store_gpr(t0, rt);
>          opn = "lwu";
>          break;
>      case OPC_LD:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
>          gen_store_gpr(t0, rt);
>          opn = "ld";
> @@ -1864,6 +1866,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          opn = "lld";
>          break;
>      case OPC_LDL:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_temp_new();
>          tcg_gen_andi_tl(t1, t0, 7);
>  #ifndef TARGET_WORDS_BIGENDIAN
> @@ -1885,6 +1888,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          opn = "ldl";
>          break;
>      case OPC_LDR:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_temp_new();
>          tcg_gen_andi_tl(t1, t0, 7);
>  #ifdef TARGET_WORDS_BIGENDIAN
> @@ -1906,6 +1910,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          opn = "ldr";
>          break;
>      case OPC_LDPC:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_const_tl(pc_relative_pc(ctx));
>          gen_op_addr_add(ctx, t0, t0, t1);
>          tcg_temp_free(t1);
> @@ -1915,6 +1920,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          break;
>  #endif
>      case OPC_LWPC:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_const_tl(pc_relative_pc(ctx));
>          gen_op_addr_add(ctx, t0, t0, t1);
>          tcg_temp_free(t1);
> @@ -1923,31 +1929,37 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          opn = "lwpc";
>          break;
>      case OPC_LW:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
>          gen_store_gpr(t0, rt);
>          opn = "lw";
>          break;
>      case OPC_LH:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
>          gen_store_gpr(t0, rt);
>          opn = "lh";
>          break;
>      case OPC_LHU:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
>          gen_store_gpr(t0, rt);
>          opn = "lhu";
>          break;
>      case OPC_LB:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
>          gen_store_gpr(t0, rt);
>          opn = "lb";
>          break;
>      case OPC_LBU:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
>          gen_store_gpr(t0, rt);
>          opn = "lbu";
>          break;
>      case OPC_LWL:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_temp_new();
>          tcg_gen_andi_tl(t1, t0, 3);
>  #ifndef TARGET_WORDS_BIGENDIAN
> @@ -1970,6 +1982,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
>          opn = "lwl";
>          break;
>      case OPC_LWR:
> +        save_cpu_state(ctx, 0);
>          t1 = tcg_temp_new();
>          tcg_gen_andi_tl(t1, t0, 3);
>  #ifdef TARGET_WORDS_BIGENDIAN
> @@ -2017,6 +2030,7 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
>      switch (opc) {
>  #if defined(TARGET_MIPS64)
>      case OPC_SD:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
>          opn = "sd";
>          break;
> @@ -2032,14 +2046,17 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
>          break;
>  #endif
>      case OPC_SW:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
>          opn = "sw";
>          break;
>      case OPC_SH:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
>          opn = "sh";
>          break;
>      case OPC_SB:
> +        save_cpu_state(ctx, 0);
>          tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
>          opn = "sb";
>          break;
> @@ -8370,6 +8387,8 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
>      enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
>      uint32_t func = ctx->opcode & 0x3f;
>  
> +    save_cpu_state(ctx, 0);
> +
>      switch (op1) {
>      case OPC_ADD_S:
>          {
> -- 
> 1.7.5.4
> 
> 

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers
  2014-06-19 14:45 ` [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers Leon Alrae
@ 2014-06-20 22:02   ` Aurelien Jarno
  2014-07-08  8:18     ` Leon Alrae
  0 siblings, 1 reply; 20+ messages in thread
From: Aurelien Jarno @ 2014-06-20 22:02 UTC (permalink / raw)
  To: Leon Alrae; +Cc: yongbok.kim, cristian.cuna, qemu-devel

On Thu, Jun 19, 2014 at 03:45:32PM +0100, 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 |   27 +++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 0 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 217c09b..fae94ed 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;
> @@ -374,6 +376,7 @@ struct CPUMIPSState {
>  #define CP0C3_TL   0
>      uint32_t CP0_Config4;
>      uint32_t CP0_Config4_rw_bitmask;
> +#define CP0C4_KScrExist 16
>  #define CP0C4_M    31
>      uint32_t CP0_Config5;
>      uint32_t CP0_Config5_rw_bitmask;
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index a8dc529..4e90c08 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1174,6 +1174,7 @@ typedef struct DisasContext {
>      int bstate;
>      target_ulong btarget;
>      bool ulri;
> +    int32_t kscrexist;
>  } DisasContext;
>  
>  enum {
> @@ -5198,6 +5199,12 @@ 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:
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            tcg_gen_ext32s_tl(arg, arg);
> +            rn = "KScratch";
> +            break;

This change the behaviour of existing CPU which don't implement scratch
registers. Before it would generate an RI exception, and after the
patch, it would simply leave the register unchanged.

The architecture manuals says in that case the result is UNDEFINED, so
that might be fine, that said it also says this instruction could
generate an RI exception, and I wouldn't be surprised real silicon
actually generate such an exception.

The best would be to try on a real silicon to decide.

>          default:
>              goto die;
>          }
> @@ -5806,6 +5813,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;
>          }
> @@ -6393,6 +6407,11 @@ 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:
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            rn = "KScratch";
> +            break;
>          default:
>              goto die;
>          }
> @@ -6992,6 +7011,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;
>          }
> @@ -17499,6 +17525,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>      ctx.insn_flags = env->insn_flags;
>      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
> 
> 

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support
  2014-06-19 22:13   ` Aurelien Jarno
@ 2014-07-08  8:07     ` Leon Alrae
  0 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-07-08  8:07 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: yongbok.kim, cristian.cuna, qemu-devel

On 19/06/2014 23:13, Aurelien Jarno wrote:
> I don't think this should implemented that way, as it would have a
> significant impact on the performances. Given we have the fault address
> (we fill EPC), we can fetch the corresponding opcode. There might be
> some code change to do for the branches, so that we can get the
> informations we need from re-translation (this might also simplify the
> current branches code).

I changed the BadInstr implementation in v2. Now the instruction word is
fetched when we have the exception (and the valid instruction word is
available), so we don't have to generate code to save the last
instruction. The same has been done for BadInstrP and the branch prior
to the delay slot.

Thanks,
Leon

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

* Re: [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers
  2014-06-20 22:02   ` Aurelien Jarno
@ 2014-07-08  8:18     ` Leon Alrae
  0 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-07-08  8:18 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: yongbok.kim, cristian.cuna, qemu-devel

On 20/06/2014 23:02, Aurelien Jarno wrote:
>> @@ -5198,6 +5199,12 @@ 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:
>> +            tcg_gen_ld_tl(arg, cpu_env,
>> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
>> +            tcg_gen_ext32s_tl(arg, arg);
>> +            rn = "KScratch";
>> +            break;
> 
> This change the behaviour of existing CPU which don't implement scratch
> registers. Before it would generate an RI exception, and after the
> patch, it would simply leave the register unchanged.
> 
> The architecture manuals says in that case the result is UNDEFINED, so
> that might be fine, that said it also says this instruction could
> generate an RI exception, and I wouldn't be surprised real silicon
> actually generate such an exception.

On the real HW - reads from an unimplemented cp0 register return
0xffffffff (in R6 it will be 0) and writes are just ignored, there is no
RI exception. In v2 I updated the behaviour for the new registers only.
I think the same changes will be needed for the existing registers, but
this is out of the current patch series scope - I plan to do this later.

Thanks,
Leon

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

* Re: [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support KScratch registers
  2014-06-19 17:43   ` Richard Henderson
@ 2014-07-08  8:31     ` Leon Alrae
  0 siblings, 0 replies; 20+ messages in thread
From: Leon Alrae @ 2014-07-08  8:31 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: yongbok.kim, cristian.cuna, aurelien

On 19/06/2014 18:43, Richard Henderson wrote:
> You must update CPU_SAVE_VERSION when you change the contents of the save data.
> 
> For extra credit, consider updating target-mips to VMStateDescription structure(s).
> 
> 
> r~
> 

v2 contains updated CPU_SAVE_VERSION.

VMStateDescription structures sound like nice to have in target-mips -
at the moment I'm not able to look at this, but I'll keep that in mind.

Thanks,
Leon

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

end of thread, other threads:[~2014-07-08  8:31 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-19 14:45 [Qemu-devel] [PATCH 00/12] implement features required in MIPS64 Release 6 Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 01/12] target-mips: add KScratch registers Leon Alrae
2014-06-20 22:02   ` Aurelien Jarno
2014-07-08  8:18     ` Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 02/12] target-mips: update cpu_save/cpu_load to support " Leon Alrae
2014-06-19 17:43   ` Richard Henderson
2014-07-08  8:31     ` Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 03/12] target-mips: distinguish between data load and instruction fetch Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 04/12] target-mips: add RI and XI fields to TLB entry Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 05/12] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1} Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 06/12] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 07/12] target-mips: add TLBINV support Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 08/12] target-mips: add BadInstr and BadInstrP support Leon Alrae
2014-06-19 22:13   ` Aurelien Jarno
2014-07-08  8:07     ` Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 09/12] target-mips: save cpu state if instruction can cause an exception Leon Alrae
2014-06-19 22:13   ` Aurelien Jarno
2014-06-19 14:45 ` [Qemu-devel] [PATCH 10/12] target-mips: update cpu_save/cpu_load to support BadInstr registers Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 11/12] target-mips: enable features in MIPS32R5-generic core Leon Alrae
2014-06-19 14:45 ` [Qemu-devel] [PATCH 12/12] target-mips: enable features in MIPS64R6-generic core Leon Alrae

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.