qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
@ 2023-03-25 10:54 Richard Henderson
  2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
                   ` (29 more replies)
  0 siblings, 30 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.

  * Reclaim 5 TB_FLAGS bits, since we nearly ran out.

  * Using cpu_mmu_index(env, true) is insufficient to implement
    HLVX properly.  While that chooses the correct mmu_idx, it
    does not perform the read with execute permission.
    I add a new tcg interface to perform a read-for-execute with
    an arbitrary mmu_idx.  This is still not 100% compliant, but
    it's closer.

  * Handle mstatus.MPV in cpu_mmu_index.
  * Use vsstatus.SUM when required for MMUIdx_S_SUM.
  * Cleanups for get_physical_address.

While this passes check-avocado, I'm sure that's insufficient.
Please have a close look.


r~


Fei Wu (2):
  target/riscv: Separate priv from mmu_idx
  target/riscv: Reduce overhead of MSTATUS_SUM change

LIU Zhiwei (4):
  target/riscv: Extract virt enabled state from tb flags
  target/riscv: Add a general status enum for extensions
  target/riscv: Encode the FS and VS on a normal way for tb flags
  target/riscv: Add a tb flags field for vstart

Richard Henderson (19):
  target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
  accel/tcg: Add cpu_ld*_code_mmu
  target/riscv: Use cpu_ld*_code_mmu for HLVX
  target/riscv: Handle HLV, HSV via helpers
  target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
  target/riscv: Introduce mmuidx_sum
  target/riscv: Introduce mmuidx_priv
  target/riscv: Introduce mmuidx_2stage
  target/riscv: Move hstatus.spvp check to check_access_hlsv
  target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
  target/riscv: Check SUM in the correct register
  target/riscv: Hoist second stage mode change to callers
  target/riscv: Hoist pbmte and hade out of the level loop
  target/riscv: Move leaf pte processing out of level loop
  target/riscv: Suppress pte update with is_debug
  target/riscv: Don't modify SUM with is_debug
  target/riscv: Merge checks for reserved pte flags
  target/riscv: Reorg access check in get_physical_address
  target/riscv: Reorg sum check in get_physical_address

 include/exec/cpu_ldst.h                       |   9 +
 target/riscv/cpu.h                            |  47 ++-
 target/riscv/cpu_bits.h                       |  12 +-
 target/riscv/helper.h                         |  12 +-
 target/riscv/internals.h                      |  35 ++
 accel/tcg/cputlb.c                            |  48 +++
 accel/tcg/user-exec.c                         |  58 +++
 target/riscv/cpu.c                            |   2 +-
 target/riscv/cpu_helper.c                     | 393 +++++++++---------
 target/riscv/csr.c                            |  21 +-
 target/riscv/op_helper.c                      | 113 ++++-
 target/riscv/translate.c                      |  72 ++--
 .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
 target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
 target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
 target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
 target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
 17 files changed, 595 insertions(+), 395 deletions(-)

-- 
2.34.1



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

* [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-06  2:35   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, Weiwei Li

From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Virt enabled state is not a constant. So we should put it into tb flags.
Thus we can use it like a constant condition at translation phase.

Reported-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Message-Id: <20230324143031.1093-2-zhiwei_liu@linux.alibaba.com>
---
 target/riscv/cpu.h        |  2 ++
 target/riscv/cpu_helper.c |  2 ++
 target/riscv/translate.c  | 10 +---------
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 638e47c75a..12fe8d8546 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -650,6 +650,8 @@ FIELD(TB_FLAGS, VTA, 24, 1)
 FIELD(TB_FLAGS, VMA, 25, 1)
 /* Native debug itrigger */
 FIELD(TB_FLAGS, ITRIGGER, 26, 1)
+/* Virtual mode enabled */
+FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f88c503cf4..9d50e7bbb6 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -104,6 +104,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
 
         flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
                            get_field(env->mstatus_hs, MSTATUS_VS));
+        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
+                           get_field(env->virt, VIRT_ONOFF));
     }
     if (cpu->cfg.debug && !icount_enabled()) {
         flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0ee8ee147d..880f6318aa 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1156,15 +1156,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
     ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
     ctx->priv_ver = env->priv_ver;
-#if !defined(CONFIG_USER_ONLY)
-    if (riscv_has_ext(env, RVH)) {
-        ctx->virt_enabled = riscv_cpu_virt_enabled(env);
-    } else {
-        ctx->virt_enabled = false;
-    }
-#else
-    ctx->virt_enabled = false;
-#endif
+    ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
     ctx->misa_ext = env->misa_ext;
     ctx->frm = -1;  /* unknown rounding mode */
     ctx->cfg_ptr = &(cpu->cfg);
-- 
2.34.1



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

* [PATCH v6 02/25] target/riscv: Add a general status enum for extensions
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
  2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-03-26 12:54   ` liweiwei
  2023-04-11  2:05   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags Richard Henderson
                   ` (27 subsequent siblings)
  29 siblings, 2 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

The pointer masking is the only extension that directly use status.
The vector or float extension uses the status in an indirect way.

Replace the pointer masking extension special status fields with
the general status.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Message-Id: <20230324143031.1093-3-zhiwei_liu@linux.alibaba.com>
[rth: Add a typedef for the enum]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu.h      |  8 ++++++++
 target/riscv/cpu_bits.h | 12 ++++--------
 target/riscv/cpu.c      |  2 +-
 target/riscv/csr.c      | 14 +++++++-------
 4 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 12fe8d8546..30d9828d59 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -99,6 +99,14 @@ enum {
     TRANSLATE_G_STAGE_FAIL
 };
 
+/* Extension context status */
+typedef enum {
+    EXT_STATUS_DISABLED = 0,
+    EXT_STATUS_INITIAL,
+    EXT_STATUS_CLEAN,
+    EXT_STATUS_DIRTY,
+} RISCVExtStatus;
+
 #define MMU_USER_IDX 3
 
 #define MAX_RISCV_PMPS (16)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fca7ef0cef..b84f62f8d6 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -9,6 +9,9 @@
                  (((uint64_t)(val) * ((mask) & ~((mask) << 1))) & \
                  (uint64_t)(mask)))
 
+/* Extension context status mask */
+#define EXT_STATUS_MASK     0x3ULL
+
 /* Floating point round mode */
 #define FSR_RD_SHIFT        5
 #define FSR_RD              (0x7 << FSR_RD_SHIFT)
@@ -734,13 +737,6 @@ typedef enum RISCVException {
 #define PM_ENABLE       0x00000001ULL
 #define PM_CURRENT      0x00000002ULL
 #define PM_INSN         0x00000004ULL
-#define PM_XS_MASK      0x00000003ULL
-
-/* PointerMasking XS bits values */
-#define PM_EXT_DISABLE  0x00000000ULL
-#define PM_EXT_INITIAL  0x00000001ULL
-#define PM_EXT_CLEAN    0x00000002ULL
-#define PM_EXT_DIRTY    0x00000003ULL
 
 /* Execution enviornment configuration bits */
 #define MENVCFG_FIOM                       BIT(0)
@@ -780,7 +776,7 @@ typedef enum RISCVException {
 #define S_OFFSET     5ULL
 #define M_OFFSET     8ULL
 
-#define PM_XS_BITS   (PM_XS_MASK << XS_OFFSET)
+#define PM_XS_BITS   (EXT_STATUS_MASK << XS_OFFSET)
 #define U_PM_ENABLE  (PM_ENABLE  << U_OFFSET)
 #define U_PM_CURRENT (PM_CURRENT << U_OFFSET)
 #define U_PM_INSN    (PM_INSN    << U_OFFSET)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e97473af2..1135106b3e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -764,7 +764,7 @@ static void riscv_cpu_reset_hold(Object *obj)
         i++;
     }
     /* mmte is supposed to have pm.current hardwired to 1 */
-    env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
+    env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
 #endif
     env->xl = riscv_cpu_mxl(env);
     riscv_cpu_update_mask(env);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d522efc0b6..abea7b749e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3513,7 +3513,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno,
 
     /* hardwiring pm.instruction bit to 0, since it's not supported yet */
     wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
-    env->mmte = wpri_val | PM_EXT_DIRTY;
+    env->mmte = wpri_val | EXT_STATUS_DIRTY;
     riscv_cpu_update_mask(env);
 
     /* Set XS and SD bits, since PM CSRs are dirty */
@@ -3593,7 +3593,7 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
         env->cur_pmmask = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
@@ -3621,7 +3621,7 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
         env->cur_pmmask = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
@@ -3649,7 +3649,7 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
         env->cur_pmmask = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
@@ -3673,7 +3673,7 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
         env->cur_pmbase = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
@@ -3701,7 +3701,7 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
         env->cur_pmbase = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
@@ -3729,7 +3729,7 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
     if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
         env->cur_pmbase = val;
     }
-    env->mmte |= PM_EXT_DIRTY;
+    env->mmte |= EXT_STATUS_DIRTY;
 
     /* Set XS and SD bits, since PM CSRs are dirty */
     mstatus = env->mstatus | MSTATUS_XS;
-- 
2.34.1



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

* [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
  2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
  2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  1:59   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, Weiwei Li

From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Reuse the MSTATUS_FS and MSTATUS_VS for the tb flags positions is not a
normal way.

It will make it hard to change the tb flags layout. And even worse, if we
want to keep tb flags for a same extension togather without a hole.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Message-Id: <20230324143031.1093-4-zhiwei_liu@linux.alibaba.com>
[rth: Adjust trans_rvf.c.inc as well; use the typedef]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu.h                      | 15 +++++------
 target/riscv/cpu_helper.c               | 11 ++++----
 target/riscv/translate.c                | 34 ++++++++++++-------------
 target/riscv/insn_trans/trans_rvf.c.inc |  2 +-
 target/riscv/insn_trans/trans_rvv.c.inc |  8 +++---
 5 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 30d9828d59..f787145a21 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -633,18 +633,17 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
 
 #define TB_FLAGS_PRIV_MMU_MASK                3
 #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
-#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
-#define TB_FLAGS_MSTATUS_VS MSTATUS_VS
 
 #include "exec/cpu-all.h"
 
 FIELD(TB_FLAGS, MEM_IDX, 0, 3)
-FIELD(TB_FLAGS, LMUL, 3, 3)
-FIELD(TB_FLAGS, SEW, 6, 3)
-/* Skip MSTATUS_VS (0x600) bits */
-FIELD(TB_FLAGS, VL_EQ_VLMAX, 11, 1)
-FIELD(TB_FLAGS, VILL, 12, 1)
-/* Skip MSTATUS_FS (0x6000) bits */
+FIELD(TB_FLAGS, FS, 3, 2)
+/* Vector flags */
+FIELD(TB_FLAGS, VS, 5, 2)
+FIELD(TB_FLAGS, LMUL, 7, 3)
+FIELD(TB_FLAGS, SEW, 10, 3)
+FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
+FIELD(TB_FLAGS, VILL, 14, 1)
 /* Is a Hypervisor instruction load/store allowed? */
 FIELD(TB_FLAGS, HLSX, 15, 1)
 FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9d50e7bbb6..1e7ee9aa30 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -79,16 +79,17 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     }
 
 #ifdef CONFIG_USER_ONLY
-    flags |= TB_FLAGS_MSTATUS_FS;
-    flags |= TB_FLAGS_MSTATUS_VS;
+    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
+    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
 #else
     flags |= cpu_mmu_index(env, 0);
     if (riscv_cpu_fp_enabled(env)) {
-        flags |= env->mstatus & MSTATUS_FS;
+        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
+                            get_field(env->mstatus,  MSTATUS_FS));
     }
-
     if (riscv_cpu_vector_enabled(env)) {
-        flags |= env->mstatus & MSTATUS_VS;
+        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
+                            get_field(env->mstatus, MSTATUS_VS));
     }
 
     if (riscv_has_ext(env, RVH)) {
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 880f6318aa..b897bf6006 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -64,10 +64,10 @@ typedef struct DisasContext {
     RISCVMXL xl;
     uint32_t misa_ext;
     uint32_t opcode;
-    uint32_t mstatus_fs;
-    uint32_t mstatus_vs;
-    uint32_t mstatus_hs_fs;
-    uint32_t mstatus_hs_vs;
+    RISCVExtStatus mstatus_fs;
+    RISCVExtStatus mstatus_vs;
+    RISCVExtStatus mstatus_hs_fs;
+    RISCVExtStatus mstatus_hs_vs;
     uint32_t mem_idx;
     /* Remember the rounding mode encoded in the previous fp instruction,
        which we have already installed into env->fp_status.  Or -1 for
@@ -598,8 +598,7 @@ static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
 }
 
 #ifndef CONFIG_USER_ONLY
-/* The states of mstatus_fs are:
- * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
+/*
  * We will have already diagnosed disabled state,
  * and need to turn initial/clean into dirty.
  */
@@ -611,9 +610,9 @@ static void mark_fs_dirty(DisasContext *ctx)
         return;
     }
 
-    if (ctx->mstatus_fs != MSTATUS_FS) {
+    if (ctx->mstatus_fs != EXT_STATUS_DIRTY) {
         /* Remember the state change for the rest of the TB. */
-        ctx->mstatus_fs = MSTATUS_FS;
+        ctx->mstatus_fs = EXT_STATUS_DIRTY;
 
         tmp = tcg_temp_new();
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
@@ -621,9 +620,9 @@ static void mark_fs_dirty(DisasContext *ctx)
         tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
     }
 
-    if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
+    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
         /* Remember the stage change for the rest of the TB. */
-        ctx->mstatus_hs_fs = MSTATUS_FS;
+        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
 
         tmp = tcg_temp_new();
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
@@ -636,8 +635,7 @@ static inline void mark_fs_dirty(DisasContext *ctx) { }
 #endif
 
 #ifndef CONFIG_USER_ONLY
-/* The states of mstatus_vs are:
- * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
+/*
  * We will have already diagnosed disabled state,
  * and need to turn initial/clean into dirty.
  */
@@ -645,9 +643,9 @@ static void mark_vs_dirty(DisasContext *ctx)
 {
     TCGv tmp;
 
-    if (ctx->mstatus_vs != MSTATUS_VS) {
+    if (ctx->mstatus_vs != EXT_STATUS_DIRTY) {
         /* Remember the state change for the rest of the TB.  */
-        ctx->mstatus_vs = MSTATUS_VS;
+        ctx->mstatus_vs = EXT_STATUS_DIRTY;
 
         tmp = tcg_temp_new();
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
@@ -655,9 +653,9 @@ static void mark_vs_dirty(DisasContext *ctx)
         tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
     }
 
-    if (ctx->virt_enabled && ctx->mstatus_hs_vs != MSTATUS_VS) {
+    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
         /* Remember the stage change for the rest of the TB. */
-        ctx->mstatus_hs_vs = MSTATUS_VS;
+        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
 
         tmp = tcg_temp_new();
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
@@ -1153,8 +1151,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 
     ctx->pc_succ_insn = ctx->base.pc_first;
     ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
-    ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
-    ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
+    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
+    ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
     ctx->priv_ver = env->priv_ver;
     ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
     ctx->misa_ext = env->misa_ext;
diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc
index 052408f45c..31cd3d0e05 100644
--- a/target/riscv/insn_trans/trans_rvf.c.inc
+++ b/target/riscv/insn_trans/trans_rvf.c.inc
@@ -19,7 +19,7 @@
  */
 
 #define REQUIRE_FPU do {\
-    if (ctx->mstatus_fs == 0) \
+    if (ctx->mstatus_fs == EXT_STATUS_DISABLED) \
         if (!ctx->cfg_ptr->ext_zfinx) \
             return false; \
 } while (0)
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
index f2e3d38515..6297c3b50d 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -29,12 +29,12 @@ static inline bool is_overlapped(const int8_t astart, int8_t asize,
 
 static bool require_rvv(DisasContext *s)
 {
-    return s->mstatus_vs != 0;
+    return s->mstatus_vs != EXT_STATUS_DISABLED;
 }
 
 static bool require_rvf(DisasContext *s)
 {
-    if (s->mstatus_fs == 0) {
+    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
         return false;
     }
 
@@ -52,7 +52,7 @@ static bool require_rvf(DisasContext *s)
 
 static bool require_scale_rvf(DisasContext *s)
 {
-    if (s->mstatus_fs == 0) {
+    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
         return false;
     }
 
@@ -70,7 +70,7 @@ static bool require_scale_rvf(DisasContext *s)
 
 static bool require_scale_rvfmin(DisasContext *s)
 {
-    if (s->mstatus_fs == 0) {
+    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
         return false;
     }
 
-- 
2.34.1



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

* [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (2 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-03-27  1:34   ` liweiwei
                     ` (2 more replies)
  2023-03-25 10:54 ` [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart Richard Henderson
                   ` (25 subsequent siblings)
  29 siblings, 3 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Merge with mstatus_{fs,vs}.  We might perform a redundant
assignment to one or the other field, but it's a trivial
and saves 4 bits from TB_FLAGS.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu.h        | 16 +++++++---------
 target/riscv/cpu_helper.c | 34 ++++++++++++++++------------------
 target/riscv/translate.c  | 32 ++++++++++----------------------
 3 files changed, 33 insertions(+), 49 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f787145a21..d9e0eaaf9b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -646,19 +646,17 @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
 FIELD(TB_FLAGS, VILL, 14, 1)
 /* Is a Hypervisor instruction load/store allowed? */
 FIELD(TB_FLAGS, HLSX, 15, 1)
-FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
-FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2)
 /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
-FIELD(TB_FLAGS, XL, 20, 2)
+FIELD(TB_FLAGS, XL, 16, 2)
 /* If PointerMasking should be applied */
-FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
-FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
-FIELD(TB_FLAGS, VTA, 24, 1)
-FIELD(TB_FLAGS, VMA, 25, 1)
+FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1)
+FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1)
+FIELD(TB_FLAGS, VTA, 20, 1)
+FIELD(TB_FLAGS, VMA, 21, 1)
 /* Native debug itrigger */
-FIELD(TB_FLAGS, ITRIGGER, 26, 1)
+FIELD(TB_FLAGS, ITRIGGER, 22, 1)
 /* Virtual mode enabled */
-FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
+FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 1e7ee9aa30..4fdd6fe021 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -45,7 +45,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
 {
     CPUState *cs = env_cpu(env);
     RISCVCPU *cpu = RISCV_CPU(cs);
-
+    RISCVExtStatus fs, vs;
     uint32_t flags = 0;
 
     *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
@@ -79,18 +79,12 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     }
 
 #ifdef CONFIG_USER_ONLY
-    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
-    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
+    fs = EXT_STATUS_DIRTY;
+    vs = EXT_STATUS_DIRTY;
 #else
     flags |= cpu_mmu_index(env, 0);
-    if (riscv_cpu_fp_enabled(env)) {
-        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
-                            get_field(env->mstatus,  MSTATUS_FS));
-    }
-    if (riscv_cpu_vector_enabled(env)) {
-        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
-                            get_field(env->mstatus, MSTATUS_VS));
-    }
+    fs = get_field(env->mstatus, MSTATUS_FS);
+    vs = get_field(env->mstatus, MSTATUS_VS);
 
     if (riscv_has_ext(env, RVH)) {
         if (env->priv == PRV_M ||
@@ -100,19 +94,23 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
             flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
         }
 
-        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
-                           get_field(env->mstatus_hs, MSTATUS_FS));
-
-        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
-                           get_field(env->mstatus_hs, MSTATUS_VS));
-        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
-                           get_field(env->virt, VIRT_ONOFF));
+        if (riscv_cpu_virt_enabled(env)) {
+            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
+            /*
+             * Merge DISABLED and !DIRTY states using MIN.
+             * We will set both fields when dirtying.
+             */
+            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
+            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
+        }
     }
     if (cpu->cfg.debug && !icount_enabled()) {
         flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
     }
 #endif
 
+    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
+    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
     flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
     if (env->cur_pmmask < (env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX)) {
         flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index b897bf6006..74d0b9889d 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -66,8 +66,6 @@ typedef struct DisasContext {
     uint32_t opcode;
     RISCVExtStatus mstatus_fs;
     RISCVExtStatus mstatus_vs;
-    RISCVExtStatus mstatus_hs_fs;
-    RISCVExtStatus mstatus_hs_vs;
     uint32_t mem_idx;
     /* Remember the rounding mode encoded in the previous fp instruction,
        which we have already installed into env->fp_status.  Or -1 for
@@ -618,16 +616,12 @@ static void mark_fs_dirty(DisasContext *ctx)
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
         tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
         tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
-    }
 
-    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
-        /* Remember the stage change for the rest of the TB. */
-        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
-
-        tmp = tcg_temp_new();
-        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
-        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
-        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+        if (ctx->virt_enabled) {
+            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+            tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
+            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+        }
     }
 }
 #else
@@ -651,16 +645,12 @@ static void mark_vs_dirty(DisasContext *ctx)
         tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
         tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
         tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
-    }
 
-    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
-        /* Remember the stage change for the rest of the TB. */
-        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
-
-        tmp = tcg_temp_new();
-        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
-        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
-        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+        if (ctx->virt_enabled) {
+            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+            tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
+            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+        }
     }
 }
 #else
@@ -1158,8 +1148,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->misa_ext = env->misa_ext;
     ctx->frm = -1;  /* unknown rounding mode */
     ctx->cfg_ptr = &(cpu->cfg);
-    ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
-    ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
     ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
     ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
     ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
-- 
2.34.1



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

* [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (3 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  2:07   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
                   ` (24 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, Weiwei Li

From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Once we mistook the vstart directly from the env->vstart. As env->vstart is not
a constant, we should record it in the tb flags if we want to use
it in translation.

Reported-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Message-Id: <20230324143031.1093-5-zhiwei_liu@linux.alibaba.com>
---
 target/riscv/cpu.h                      |  1 +
 target/riscv/cpu_helper.c               |  1 +
 target/riscv/translate.c                |  4 ++--
 target/riscv/insn_trans/trans_rvv.c.inc | 14 +++++++-------
 4 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d9e0eaaf9b..86a82e25dc 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -657,6 +657,7 @@ FIELD(TB_FLAGS, VMA, 21, 1)
 FIELD(TB_FLAGS, ITRIGGER, 22, 1)
 /* Virtual mode enabled */
 FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
+FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4fdd6fe021..4f0999d50b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -74,6 +74,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
                     FIELD_EX64(env->vtype, VTYPE, VTA));
         flags = FIELD_DP32(flags, TB_FLAGS, VMA,
                     FIELD_EX64(env->vtype, VTYPE, VMA));
+        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
     } else {
         flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
     }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 74d0b9889d..f8c077525c 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -97,7 +97,7 @@ typedef struct DisasContext {
     uint8_t vta;
     uint8_t vma;
     bool cfg_vta_all_1s;
-    target_ulong vstart;
+    bool vstart_eq_zero;
     bool vl_eq_vlmax;
     CPUState *cs;
     TCGv zero;
@@ -1155,7 +1155,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
     ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s;
     ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
-    ctx->vstart = env->vstart;
+    ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
     ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
     ctx->misa_mxl_max = env->misa_mxl_max;
     ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
index 6297c3b50d..32b3b9a8e5 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -547,7 +547,7 @@ static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
  */
 static bool vext_check_reduction(DisasContext *s, int vs2)
 {
-    return require_align(vs2, s->lmul) && (s->vstart == 0);
+    return require_align(vs2, s->lmul) && s->vstart_eq_zero;
 }
 
 /*
@@ -3083,7 +3083,7 @@ static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
 {
     if (require_rvv(s) &&
         vext_check_isa_ill(s) &&
-        s->vstart == 0) {
+        s->vstart_eq_zero) {
         TCGv_ptr src2, mask;
         TCGv dst;
         TCGv_i32 desc;
@@ -3112,7 +3112,7 @@ static bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
 {
     if (require_rvv(s) &&
         vext_check_isa_ill(s) &&
-        s->vstart == 0) {
+        s->vstart_eq_zero) {
         TCGv_ptr src2, mask;
         TCGv dst;
         TCGv_i32 desc;
@@ -3146,7 +3146,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
         vext_check_isa_ill(s) &&                                   \
         require_vm(a->vm, a->rd) &&                                \
         (a->rd != a->rs2) &&                                       \
-        (s->vstart == 0)) {                                        \
+        s->vstart_eq_zero) {                                       \
         uint32_t data = 0;                                         \
         gen_helper_gvec_3_ptr *fn = gen_helper_##NAME;             \
         TCGLabel *over = gen_new_label();                          \
@@ -3187,7 +3187,7 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
         !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
         require_vm(a->vm, a->rd) &&
         require_align(a->rd, s->lmul) &&
-        (s->vstart == 0)) {
+        s->vstart_eq_zero) {
         uint32_t data = 0;
         TCGLabel *over = gen_new_label();
         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
@@ -3636,7 +3636,7 @@ static bool vcompress_vm_check(DisasContext *s, arg_r *a)
            require_align(a->rs2, s->lmul) &&
            (a->rd != a->rs2) &&
            !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1) &&
-           (s->vstart == 0);
+           s->vstart_eq_zero;
 }
 
 static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
@@ -3675,7 +3675,7 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a)               \
         QEMU_IS_ALIGNED(a->rd, LEN) &&                                  \
         QEMU_IS_ALIGNED(a->rs2, LEN)) {                                 \
         uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN;                 \
-        if (s->vstart == 0) {                                           \
+        if (s->vstart_eq_zero) {                                        \
             /* EEW = 8 */                                               \
             tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd),                  \
                              vreg_ofs(s, a->rs2), maxsz, maxsz);        \
-- 
2.34.1



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

* [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (4 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-03-28  2:39   ` LIU Zhiwei
  2023-04-11  2:08   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
                   ` (23 subsequent siblings)
  29 siblings, 2 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

From: Fei Wu <fei2.wu@intel.com>

Currently it's assumed the 2 low bits of mmu_idx map to privilege mode,
this assumption won't last as we are about to add more mmu_idx. Here an
individual priv field is added into TB_FLAGS.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
Message-Id: <20230324054154.414846-2-fei2.wu@intel.com>
---
 target/riscv/cpu.h                             | 2 +-
 target/riscv/cpu_helper.c                      | 4 +++-
 target/riscv/translate.c                       | 2 ++
 target/riscv/insn_trans/trans_privileged.c.inc | 2 +-
 target/riscv/insn_trans/trans_xthead.c.inc     | 7 +------
 5 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 86a82e25dc..3e59dbb3fd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -631,7 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
 target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
 
-#define TB_FLAGS_PRIV_MMU_MASK                3
 #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
 
 #include "exec/cpu-all.h"
@@ -658,6 +657,7 @@ FIELD(TB_FLAGS, ITRIGGER, 22, 1)
 /* Virtual mode enabled */
 FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
 FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
+FIELD(TB_FLAGS, PRIV, 25, 2)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4f0999d50b..5753126c7a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -83,6 +83,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     fs = EXT_STATUS_DIRTY;
     vs = EXT_STATUS_DIRTY;
 #else
+    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
+
     flags |= cpu_mmu_index(env, 0);
     fs = get_field(env->mstatus, MSTATUS_FS);
     vs = get_field(env->mstatus, MSTATUS_VS);
@@ -764,7 +766,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
      * (riscv_cpu_do_interrupt) is correct */
     MemTxResult res;
     MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
-    int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
+    int mode = env->priv;
     bool use_background = false;
     hwaddr ppn;
     RISCVCPU *cpu = env_archcpu(env);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index f8c077525c..abfc152553 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -67,6 +67,7 @@ typedef struct DisasContext {
     RISCVExtStatus mstatus_fs;
     RISCVExtStatus mstatus_vs;
     uint32_t mem_idx;
+    uint32_t priv;
     /* Remember the rounding mode encoded in the previous fp instruction,
        which we have already installed into env->fp_status.  Or -1 for
        no previous fp instruction.  Note that we exit the TB when writing
@@ -1140,6 +1141,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     uint32_t tb_flags = ctx->base.tb->flags;
 
     ctx->pc_succ_insn = ctx->base.pc_first;
+    ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
     ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
     ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
     ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 59501b2780..9305b18299 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -52,7 +52,7 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
      * that no exception will be raised when fetching them.
      */
 
-    if (semihosting_enabled(ctx->mem_idx < PRV_S) &&
+    if (semihosting_enabled(ctx->priv < PRV_S) &&
         (pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
         pre    = opcode_at(&ctx->base, pre_addr);
         ebreak = opcode_at(&ctx->base, ebreak_addr);
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
index df504c3f2c..adfb53cb4c 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -265,12 +265,7 @@ static bool trans_th_tst(DisasContext *ctx, arg_th_tst *a)
 
 static inline int priv_level(DisasContext *ctx)
 {
-#ifdef CONFIG_USER_ONLY
-    return PRV_U;
-#else
-     /* Priv level is part of mem_idx. */
-    return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
-#endif
+    return ctx->priv;
 }
 
 /* Test if priv level is M, S, or U (cannot fail). */
-- 
2.34.1



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

* [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (5 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-03-28  2:41   ` LIU Zhiwei
  2023-04-11  2:11   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu Richard Henderson
                   ` (22 subsequent siblings)
  29 siblings, 2 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

From: Fei Wu <fei2.wu@intel.com>

Kernel needs to access user mode memory e.g. during syscalls, the window
is usually opened up for a very limited time through MSTATUS.SUM, the
overhead is too much if tlb_flush() gets called for every SUM change.

This patch creates a separate MMU index for S+SUM, so that it's not
necessary to flush tlb anymore when SUM changes. This is similar to how
ARM handles Privileged Access Never (PAN).

Result of 'pipe 10' from unixbench boosts from 223656 to 1705006. Many
other syscalls benefit a lot from this too.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
Message-Id: <20230324054154.414846-3-fei2.wu@intel.com>
---
 target/riscv/cpu.h                      |  2 --
 target/riscv/internals.h                | 14 ++++++++++++++
 target/riscv/cpu_helper.c               | 17 +++++++++++++++--
 target/riscv/csr.c                      |  3 +--
 target/riscv/op_helper.c                |  5 +++--
 target/riscv/insn_trans/trans_rvh.c.inc |  4 ++--
 6 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 3e59dbb3fd..5e589db106 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -631,8 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
 target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
 
-#define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
-
 #include "exec/cpu-all.h"
 
 FIELD(TB_FLAGS, MEM_IDX, 0, 3)
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 5620fbffb6..b55152a7dc 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -21,6 +21,20 @@
 
 #include "hw/registerfields.h"
 
+/*
+ * The current MMU Modes are:
+ *  - U                 0b000
+ *  - S                 0b001
+ *  - S+SUM             0b010
+ *  - M                 0b011
+ *  - HLV/HLVX/HSV adds 0b100
+ */
+#define MMUIdx_U            0
+#define MMUIdx_S            1
+#define MMUIdx_S_SUM        2
+#define MMUIdx_M            3
+#define MMU_HYP_ACCESS_BIT  (1 << 2)
+
 /* share data between vector helpers and decode code */
 FIELD(VDATA, VM, 0, 1)
 FIELD(VDATA, LMUL, 1, 3)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 5753126c7a..052fdd2d9d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -21,6 +21,7 @@
 #include "qemu/log.h"
 #include "qemu/main-loop.h"
 #include "cpu.h"
+#include "internals.h"
 #include "pmu.h"
 #include "exec/exec-all.h"
 #include "instmap.h"
@@ -36,7 +37,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifdef CONFIG_USER_ONLY
     return 0;
 #else
-    return env->priv;
+    if (ifetch) {
+        return env->priv;
+    }
+
+    /* All priv -> mmu_idx mapping are here */
+    int mode = env->priv;
+    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+        mode = get_field(env->mstatus, MSTATUS_MPP);
+    }
+    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
+        return MMUIdx_S_SUM;
+    }
+    return mode;
 #endif
 }
 
@@ -600,7 +613,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
 
 bool riscv_cpu_two_stage_lookup(int mmu_idx)
 {
-    return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    return mmu_idx & MMU_HYP_ACCESS_BIT;
 }
 
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index abea7b749e..b79758a606 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1246,8 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
     RISCVMXL xl = riscv_cpu_mxl(env);
 
     /* flush tlb on mstatus fields that affect VM */
-    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
-            MSTATUS_MPRV | MSTATUS_SUM)) {
+    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) {
         tlb_flush(env_cpu(env));
     }
     mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 84ee018f7d..962a061228 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "internals.h"
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
@@ -428,14 +429,14 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
 
 target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
 {
-    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
 
     return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
 }
 
 target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
 {
-    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
 
     return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
 }
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
index 9248b48c36..15842f4282 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -40,7 +40,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
     if (check_access(ctx)) {
         TCGv dest = dest_gpr(ctx, a->rd);
         TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
         tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
         gen_set_gpr(ctx, a->rd, dest);
     }
@@ -87,7 +87,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
     if (check_access(ctx)) {
         TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
         TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
-        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
         tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
     }
     return true;
-- 
2.34.1



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

* [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (6 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:10   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX Richard Henderson
                   ` (21 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

At least RISC-V has the need to be able to perform a read
using execute permissions, outside of translation.
Add helpers to facilitate this.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu_ldst.h |  9 +++++++
 accel/tcg/cputlb.c      | 48 ++++++++++++++++++++++++++++++++++
 accel/tcg/user-exec.c   | 58 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 115 insertions(+)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 09b55cc0ee..c141f0394f 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -445,6 +445,15 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
 # define cpu_stq_mmu          cpu_stq_le_mmu
 #endif
 
+uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
+                         MemOpIdx oi, uintptr_t ra);
+uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra);
+uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra);
+uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra);
+
 uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr);
 uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr);
 uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr);
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index e984a98dc4..e62c8f3c3f 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2768,3 +2768,51 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
     MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
     return full_ldq_code(env, addr, oi, 0);
 }
+
+uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
+                         MemOpIdx oi, uintptr_t retaddr)
+{
+    return full_ldub_code(env, addr, oi, retaddr);
+}
+
+uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t retaddr)
+{
+    MemOp mop = get_memop(oi);
+    int idx = get_mmuidx(oi);
+    uint16_t ret;
+
+    ret = full_lduw_code(env, addr, make_memop_idx(MO_TEUW, idx), retaddr);
+    if ((mop & MO_BSWAP) != MO_TE) {
+        ret = bswap16(ret);
+    }
+    return ret;
+}
+
+uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t retaddr)
+{
+    MemOp mop = get_memop(oi);
+    int idx = get_mmuidx(oi);
+    uint32_t ret;
+
+    ret = full_ldl_code(env, addr, make_memop_idx(MO_TEUL, idx), retaddr);
+    if ((mop & MO_BSWAP) != MO_TE) {
+        ret = bswap32(ret);
+    }
+    return ret;
+}
+
+uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t retaddr)
+{
+    MemOp mop = get_memop(oi);
+    int idx = get_mmuidx(oi);
+    uint64_t ret;
+
+    ret = full_ldq_code(env, addr, make_memop_idx(MO_TEUQ, idx), retaddr);
+    if ((mop & MO_BSWAP) != MO_TE) {
+        ret = bswap64(ret);
+    }
+    return ret;
+}
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 7b37fd229e..44e0ea55ba 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -1222,6 +1222,64 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
     return ret;
 }
 
+uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
+                         MemOpIdx oi, uintptr_t ra)
+{
+    void *haddr;
+    uint8_t ret;
+
+    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
+    ret = ldub_p(haddr);
+    clear_helper_retaddr();
+    return ret;
+}
+
+uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra)
+{
+    void *haddr;
+    uint16_t ret;
+
+    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
+    ret = lduw_p(haddr);
+    clear_helper_retaddr();
+    if (get_memop(oi) & MO_BSWAP) {
+        ret = bswap16(ret);
+    }
+    return ret;
+}
+
+uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra)
+{
+    void *haddr;
+    uint32_t ret;
+
+    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
+    ret = ldl_p(haddr);
+    clear_helper_retaddr();
+    if (get_memop(oi) & MO_BSWAP) {
+        ret = bswap32(ret);
+    }
+    return ret;
+}
+
+uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
+                          MemOpIdx oi, uintptr_t ra)
+{
+    void *haddr;
+    uint64_t ret;
+
+    validate_memop(oi, MO_BEUQ);
+    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+    ret = ldq_p(haddr);
+    clear_helper_retaddr();
+    if (get_memop(oi) & MO_BSWAP) {
+        ret = bswap64(ret);
+    }
+    return ret;
+}
+
 #include "ldst_common.c.inc"
 
 /*
-- 
2.34.1



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

* [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (7 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:12   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers Richard Henderson
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Use the new functions to properly check execute permission
for the read rather than read permission.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/op_helper.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 962a061228..b2169a99ff 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -427,18 +427,27 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
     helper_hyp_tlb_flush(env);
 }
 
+/*
+ * TODO: These implementations are not quite correct.  They perform the
+ * access using execute permission just fine, but the final PMP check
+ * is supposed to have read permission as well.  Without replicating
+ * a fair fraction of cputlb.c, fixing this requires adding new mmu_idx
+ * which would imply that exact check in tlb_fill.
+ */
 target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
 {
     int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
+    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
 
-    return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
+    return cpu_ldw_code_mmu(env, address, oi, GETPC());
 }
 
 target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
 {
     int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
+    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
 
-    return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
+    return cpu_ldl_code_mmu(env, address, oi, GETPC());
 }
 
 #endif /* !CONFIG_USER_ONLY */
-- 
2.34.1



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

* [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (8 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:34   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT Richard Henderson
                   ` (19 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Implement these instructions via helpers, in expectation
of determining the mmu_idx to use at runtime.  This allows
the permission check to also be moved out of line, which
allows HLSX to be removed from TB_FLAGS.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu.h                      |   6 +-
 target/riscv/helper.h                   |  12 ++-
 target/riscv/cpu_helper.c               |  26 ++---
 target/riscv/op_helper.c                |  99 +++++++++++++++--
 target/riscv/translate.c                |   2 -
 target/riscv/insn_trans/trans_rvh.c.inc | 135 ++++++++++--------------
 6 files changed, 169 insertions(+), 111 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5e589db106..f03ff1f10c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -641,8 +641,7 @@ FIELD(TB_FLAGS, LMUL, 7, 3)
 FIELD(TB_FLAGS, SEW, 10, 3)
 FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
 FIELD(TB_FLAGS, VILL, 14, 1)
-/* Is a Hypervisor instruction load/store allowed? */
-FIELD(TB_FLAGS, HLSX, 15, 1)
+FIELD(TB_FLAGS, VSTART_EQ_ZERO, 15, 1)
 /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
 FIELD(TB_FLAGS, XL, 16, 2)
 /* If PointerMasking should be applied */
@@ -654,8 +653,7 @@ FIELD(TB_FLAGS, VMA, 21, 1)
 FIELD(TB_FLAGS, ITRIGGER, 22, 1)
 /* Virtual mode enabled */
 FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
-FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
-FIELD(TB_FLAGS, PRIV, 25, 2)
+FIELD(TB_FLAGS, PRIV, 24, 2)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 37b54e0991..be60bd1525 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -123,8 +123,16 @@ DEF_HELPER_1(itrigger_match, void, env)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_1(hyp_tlb_flush, void, env)
 DEF_HELPER_1(hyp_gvma_tlb_flush, void, env)
-DEF_HELPER_2(hyp_hlvx_hu, tl, env, tl)
-DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlv_bu, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlv_hu, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlv_wu, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlv_d, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlvx_hu, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_2(hyp_hlvx_wu, TCG_CALL_NO_WG, tl, env, tl)
+DEF_HELPER_FLAGS_3(hyp_hsv_b, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(hyp_hsv_h, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(hyp_hsv_w, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(hyp_hsv_d, TCG_CALL_NO_WG, void, env, tl, tl)
 #endif
 
 /* Vector functions */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 052fdd2d9d..9bb84be4e1 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -102,24 +102,16 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     fs = get_field(env->mstatus, MSTATUS_FS);
     vs = get_field(env->mstatus, MSTATUS_VS);
 
-    if (riscv_has_ext(env, RVH)) {
-        if (env->priv == PRV_M ||
-            (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
-            (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
-                get_field(env->hstatus, HSTATUS_HU))) {
-            flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
-        }
-
-        if (riscv_cpu_virt_enabled(env)) {
-            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
-            /*
-             * Merge DISABLED and !DIRTY states using MIN.
-             * We will set both fields when dirtying.
-             */
-            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
-            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
-        }
+    if (riscv_cpu_virt_enabled(env)) {
+        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
+        /*
+         * Merge DISABLED and !DIRTY states using MIN.
+         * We will set both fields when dirtying.
+         */
+        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
+        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
     }
+
     if (cpu->cfg.debug && !icount_enabled()) {
         flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
     }
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index b2169a99ff..0f81645adf 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -427,6 +427,91 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
     helper_hyp_tlb_flush(env);
 }
 
+static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
+{
+    if (env->priv == PRV_M) {
+        /* always allowed */
+    } else if (riscv_cpu_virt_enabled(env)) {
+        riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, ra);
+    } else if (env->priv == PRV_U && !get_field(env->hstatus, HSTATUS_HU)) {
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
+    }
+
+    return cpu_mmu_index(env, x) | MMU_HYP_ACCESS_BIT;
+}
+
+target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
+
+    return cpu_ldb_mmu(env, addr, oi, ra);
+}
+
+target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
+
+    return cpu_ldw_mmu(env, addr, oi, ra);
+}
+
+target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
+
+    return cpu_ldl_mmu(env, addr, oi, ra);
+}
+
+target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
+
+    return cpu_ldq_mmu(env, addr, oi, ra);
+}
+
+void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
+
+    cpu_stb_mmu(env, addr, val, oi, ra);
+}
+
+void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
+
+    cpu_stw_mmu(env, addr, val, oi, ra);
+}
+
+void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
+
+    cpu_stl_mmu(env, addr, val, oi, ra);
+}
+
+void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
+{
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, false, ra);
+    MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
+
+    cpu_stq_mmu(env, addr, val, oi, ra);
+}
+
 /*
  * TODO: These implementations are not quite correct.  They perform the
  * access using execute permission just fine, but the final PMP check
@@ -434,20 +519,22 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
  * a fair fraction of cputlb.c, fixing this requires adding new mmu_idx
  * which would imply that exact check in tlb_fill.
  */
-target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
+target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong addr)
 {
-    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, true, ra);
     MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
 
-    return cpu_ldw_code_mmu(env, address, oi, GETPC());
+    return cpu_ldw_code_mmu(env, addr, oi, GETPC());
 }
 
-target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
+target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr)
 {
-    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
+    uintptr_t ra = GETPC();
+    int mmu_idx = check_access_hlsv(env, true, ra);
     MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
 
-    return cpu_ldl_code_mmu(env, address, oi, GETPC());
+    return cpu_ldl_code_mmu(env, addr, oi, ra);
 }
 
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index abfc152553..5282588247 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -78,7 +78,6 @@ typedef struct DisasContext {
     bool virt_inst_excp;
     bool virt_enabled;
     const RISCVCPUConfig *cfg_ptr;
-    bool hlsx;
     /* vector extension */
     bool vill;
     /*
@@ -1150,7 +1149,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->misa_ext = env->misa_ext;
     ctx->frm = -1;  /* unknown rounding mode */
     ctx->cfg_ptr = &(cpu->cfg);
-    ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
     ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
     ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
     ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
index 15842f4282..3e9322130f 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -16,156 +16,131 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef CONFIG_USER_ONLY
-static bool check_access(DisasContext *ctx)
-{
-    if (!ctx->hlsx) {
-        if (ctx->virt_enabled) {
-            generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
-        } else {
-            generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
-        }
-        return false;
-    }
-    return true;
-}
-#endif
-
-static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
-{
 #ifdef CONFIG_USER_ONLY
-    return false;
+#define do_hlv(ctx, a, func)  false
+#define do_hsv(ctx, a, func)  false
 #else
-    decode_save_opc(ctx);
-    if (check_access(ctx)) {
-        TCGv dest = dest_gpr(ctx, a->rd);
-        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
-        tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
-        gen_set_gpr(ctx, a->rd, dest);
-    }
-    return true;
-#endif
+static void gen_helper_hyp_hlv_b(TCGv r, TCGv_env e, TCGv a)
+{
+    gen_helper_hyp_hlv_bu(r, e, a);
+    tcg_gen_ext8s_tl(r, r);
 }
 
+static void gen_helper_hyp_hlv_h(TCGv r, TCGv_env e, TCGv a)
+{
+    gen_helper_hyp_hlv_hu(r, e, a);
+    tcg_gen_ext16s_tl(r, r);
+}
+
+static void gen_helper_hyp_hlv_w(TCGv r, TCGv_env e, TCGv a)
+{
+    gen_helper_hyp_hlv_wu(r, e, a);
+    tcg_gen_ext32s_tl(r, r);
+}
+
+static bool do_hlv(DisasContext *ctx, arg_r2 *a,
+                   void (*func)(TCGv, TCGv_env, TCGv))
+{
+    TCGv dest = dest_gpr(ctx, a->rd);
+    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
+
+    decode_save_opc(ctx);
+    func(dest, cpu_env, addr);
+    gen_set_gpr(ctx, a->rd, dest);
+    return true;
+}
+
+static bool do_hsv(DisasContext *ctx, arg_r2_s *a,
+                   void (*func)(TCGv_env, TCGv, TCGv))
+{
+    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
+    TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
+
+    decode_save_opc(ctx);
+    func(cpu_env, addr, data);
+    return true;
+}
+#endif /* CONFIG_USER_ONLY */
+
 static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_SB);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_b);
 }
 
 static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_TESW);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_h);
 }
 
 static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_TESL);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_w);
 }
 
 static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_UB);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_bu);
 }
 
 static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_TEUW);
-}
-
-static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
-{
-#ifdef CONFIG_USER_ONLY
-    return false;
-#else
-    decode_save_opc(ctx);
-    if (check_access(ctx)) {
-        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-        TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
-        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
-        tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
-    }
-    return true;
-#endif
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_hu);
 }
 
 static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hsv(ctx, a, MO_SB);
+    return do_hsv(ctx, a, gen_helper_hyp_hsv_b);
 }
 
 static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hsv(ctx, a, MO_TESW);
+    return do_hsv(ctx, a, gen_helper_hyp_hsv_h);
 }
 
 static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
 {
     REQUIRE_EXT(ctx, RVH);
-    return do_hsv(ctx, a, MO_TESL);
+    return do_hsv(ctx, a, gen_helper_hyp_hsv_w);
 }
 
 static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
 {
     REQUIRE_64BIT(ctx);
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_TEUL);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_wu);
 }
 
 static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
 {
     REQUIRE_64BIT(ctx);
     REQUIRE_EXT(ctx, RVH);
-    return do_hlv(ctx, a, MO_TEUQ);
+    return do_hlv(ctx, a, gen_helper_hyp_hlv_d);
 }
 
 static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
 {
     REQUIRE_64BIT(ctx);
     REQUIRE_EXT(ctx, RVH);
-    return do_hsv(ctx, a, MO_TEUQ);
+    return do_hsv(ctx, a, gen_helper_hyp_hsv_d);
 }
 
-#ifndef CONFIG_USER_ONLY
-static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
-                    void (*func)(TCGv, TCGv_env, TCGv))
-{
-    decode_save_opc(ctx);
-    if (check_access(ctx)) {
-        TCGv dest = dest_gpr(ctx, a->rd);
-        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-        func(dest, cpu_env, addr);
-        gen_set_gpr(ctx, a->rd, dest);
-    }
-    return true;
-}
-#endif
-
 static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
 {
     REQUIRE_EXT(ctx, RVH);
-#ifndef CONFIG_USER_ONLY
-    return do_hlvx(ctx, a, gen_helper_hyp_hlvx_hu);
-#else
-    return false;
-#endif
+    return do_hlv(ctx, a, gen_helper_hyp_hlvx_hu);
 }
 
 static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
 {
     REQUIRE_EXT(ctx, RVH);
-#ifndef CONFIG_USER_ONLY
-    return do_hlvx(ctx, a, gen_helper_hyp_hlvx_wu);
-#else
-    return false;
-#endif
+    return do_hlv(ctx, a, gen_helper_hyp_hlvx_wu);
 }
 
 static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
-- 
2.34.1



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

* [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (9 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:36   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum Richard Henderson
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

We will enable more uses of this bit in the future.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/internals.h  | 6 ++++--
 target/riscv/cpu_helper.c | 2 +-
 target/riscv/op_helper.c  | 2 +-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index b55152a7dc..7b63c0f1b6 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -27,13 +27,15 @@
  *  - S                 0b001
  *  - S+SUM             0b010
  *  - M                 0b011
- *  - HLV/HLVX/HSV adds 0b100
+ *  - U+2STAGE          0b100
+ *  - S+2STAGE          0b101
+ *  - S+SUM+2STAGE      0b110
  */
 #define MMUIdx_U            0
 #define MMUIdx_S            1
 #define MMUIdx_S_SUM        2
 #define MMUIdx_M            3
-#define MMU_HYP_ACCESS_BIT  (1 << 2)
+#define MMU_2STAGE_BIT      (1 << 2)
 
 /* share data between vector helpers and decode code */
 FIELD(VDATA, VM, 0, 1)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9bb84be4e1..888f7ae0ef 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -605,7 +605,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
 
 bool riscv_cpu_two_stage_lookup(int mmu_idx)
 {
-    return mmu_idx & MMU_HYP_ACCESS_BIT;
+    return mmu_idx & MMU_2STAGE_BIT;
 }
 
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 0f81645adf..81362537b6 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -437,7 +437,7 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
     }
 
-    return cpu_mmu_index(env, x) | MMU_HYP_ACCESS_BIT;
+    return cpu_mmu_index(env, x) | MMU_2STAGE_BIT;
 }
 
 target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
-- 
2.34.1



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

* [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (10 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:39   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
                   ` (17 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

In get_physical_address, we should use the setting passed
via mmu_idx rather than checking env->mstatus directly.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/internals.h  | 5 +++++
 target/riscv/cpu_helper.c | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 7b63c0f1b6..0b61f337dd 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -37,6 +37,11 @@
 #define MMUIdx_M            3
 #define MMU_2STAGE_BIT      (1 << 2)
 
+static inline bool mmuidx_sum(int mmu_idx)
+{
+    return (mmu_idx & 3) == MMUIdx_S_SUM;
+}
+
 /* share data between vector helpers and decode code */
 FIELD(VDATA, VM, 0, 1)
 FIELD(VDATA, LMUL, 1, 3)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 888f7ae0ef..7e6cd8e0fd 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -852,7 +852,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         widened = 2;
     }
     /* status.SUM will be ignored if execute on background */
-    sum = get_field(env->mstatus, MSTATUS_SUM) || use_background || is_debug;
+    sum = mmuidx_sum(mmu_idx) || use_background || is_debug;
     switch (vm) {
     case VM_1_10_SV32:
       levels = 2; ptidxbits = 10; ptesize = 4; break;
-- 
2.34.1



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

* [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (11 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-03-27  2:07   ` LIU Zhiwei
  2023-04-11  3:53   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage Richard Henderson
                   ` (16 subsequent siblings)
  29 siblings, 2 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Use the priv level encoded into the mmu_idx, rather than
starting from env->priv.  We have already checked MPRV+MPP
in riscv_cpu_mmu_index -- no need to repeat that.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/internals.h  | 9 +++++++++
 target/riscv/cpu_helper.c | 6 +-----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 0b61f337dd..4aa1cb409f 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -37,6 +37,15 @@
 #define MMUIdx_M            3
 #define MMU_2STAGE_BIT      (1 << 2)
 
+static inline int mmuidx_priv(int mmu_idx)
+{
+    int ret = mmu_idx & 3;
+    if (ret == MMUIdx_S_SUM) {
+        ret = PRV_S;
+    }
+    return ret;
+}
+
 static inline bool mmuidx_sum(int mmu_idx)
 {
     return (mmu_idx & 3) == MMUIdx_S_SUM;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 7e6cd8e0fd..cb260b88ea 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -771,7 +771,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
      * (riscv_cpu_do_interrupt) is correct */
     MemTxResult res;
     MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
-    int mode = env->priv;
+    int mode = mmuidx_priv(mmu_idx);
     bool use_background = false;
     hwaddr ppn;
     RISCVCPU *cpu = env_archcpu(env);
@@ -793,10 +793,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
        instructions, HLV, HLVX, and HSV. */
     if (riscv_cpu_two_stage_lookup(mmu_idx)) {
         mode = get_field(env->hstatus, HSTATUS_SPVP);
-    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
-        if (get_field(env->mstatus, MSTATUS_MPRV)) {
-            mode = get_field(env->mstatus, MSTATUS_MPP);
-        }
     }
 
     if (first_stage == false) {
-- 
2.34.1



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

* [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (12 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:55   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv Richard Henderson
                   ` (15 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Move and rename riscv_cpu_two_stage_lookup, to match
the other mmuidx_* functions.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu.h        |  1 -
 target/riscv/internals.h  |  5 +++++
 target/riscv/cpu_helper.c | 17 ++++++-----------
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f03ff1f10c..b6bcfb3834 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -586,7 +586,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
 bool riscv_cpu_vector_enabled(CPURISCVState *env);
 bool riscv_cpu_virt_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
-bool riscv_cpu_two_stage_lookup(int mmu_idx);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
                                                MMUAccessType access_type, int mmu_idx,
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 4aa1cb409f..b5f823c7ec 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -51,6 +51,11 @@ static inline bool mmuidx_sum(int mmu_idx)
     return (mmu_idx & 3) == MMUIdx_S_SUM;
 }
 
+static inline bool mmuidx_2stage(int mmu_idx)
+{
+    return mmu_idx & MMU_2STAGE_BIT;
+}
+
 /* share data between vector helpers and decode code */
 FIELD(VDATA, VM, 0, 1)
 FIELD(VDATA, LMUL, 1, 3)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index cb260b88ea..8a124888cd 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -603,11 +603,6 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
     }
 }
 
-bool riscv_cpu_two_stage_lookup(int mmu_idx)
-{
-    return mmu_idx & MMU_2STAGE_BIT;
-}
-
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
 {
     CPURISCVState *env = &cpu->env;
@@ -791,7 +786,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 
     /* MPRV does not affect the virtual-machine load/store
        instructions, HLV, HLVX, and HSV. */
-    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
+    if (mmuidx_2stage(mmu_idx)) {
         mode = get_field(env->hstatus, HSTATUS_SPVP);
     }
 
@@ -1177,7 +1172,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
 
     env->badaddr = addr;
     env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
-                            riscv_cpu_two_stage_lookup(mmu_idx);
+                            mmuidx_2stage(mmu_idx);
     env->two_stage_indirect_lookup = false;
     cpu_loop_exit_restore(cs, retaddr);
 }
@@ -1203,7 +1198,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
     }
     env->badaddr = addr;
     env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
-                            riscv_cpu_two_stage_lookup(mmu_idx);
+                            mmuidx_2stage(mmu_idx);
     env->two_stage_indirect_lookup = false;
     cpu_loop_exit_restore(cs, retaddr);
 }
@@ -1255,7 +1250,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 
     /* MPRV does not affect the virtual-machine load/store
        instructions, HLV, HLVX, and HSV. */
-    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
+    if (mmuidx_2stage(mmu_idx)) {
         mode = get_field(env->hstatus, HSTATUS_SPVP);
     } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
                get_field(env->mstatus, MSTATUS_MPRV)) {
@@ -1267,7 +1262,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 
     pmu_tlb_fill_incr_ctr(cpu, access_type);
     if (riscv_cpu_virt_enabled(env) ||
-        ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
+        ((mmuidx_2stage(mmu_idx) || two_stage_lookup) &&
          access_type != MMU_INST_FETCH)) {
         /* Two stage lookup */
         ret = get_physical_address(env, &pa, &prot, address,
@@ -1365,7 +1360,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
         raise_mmu_exception(env, address, access_type, pmp_violation,
                             first_stage_error,
                             riscv_cpu_virt_enabled(env) ||
-                                riscv_cpu_two_stage_lookup(mmu_idx),
+                                mmuidx_2stage(mmu_idx),
                             two_stage_indirect_error);
         cpu_loop_exit_restore(cs, retaddr);
     }
-- 
2.34.1



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

* [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (13 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  3:56   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index Richard Henderson
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

The current cpu_mmu_index value is really irrelevant to
the HLV/HSV lookup.  Provide the correct priv level directly.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 8 +-------
 target/riscv/op_helper.c  | 2 +-
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8a124888cd..0adfd4a12b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -784,12 +784,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         use_background = true;
     }
 
-    /* MPRV does not affect the virtual-machine load/store
-       instructions, HLV, HLVX, and HSV. */
-    if (mmuidx_2stage(mmu_idx)) {
-        mode = get_field(env->hstatus, HSTATUS_SPVP);
-    }
-
     if (first_stage == false) {
         /* We are in stage 2 translation, this is similar to stage 1. */
         /* Stage 2 is always taken as U-mode */
@@ -1251,7 +1245,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     /* MPRV does not affect the virtual-machine load/store
        instructions, HLV, HLVX, and HSV. */
     if (mmuidx_2stage(mmu_idx)) {
-        mode = get_field(env->hstatus, HSTATUS_SPVP);
+        ;
     } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
                get_field(env->mstatus, MSTATUS_MPRV)) {
         mode = get_field(env->mstatus, MSTATUS_MPP);
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 81362537b6..db7252e09d 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -437,7 +437,7 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
     }
 
-    return cpu_mmu_index(env, x) | MMU_2STAGE_BIT;
+    return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT;
 }
 
 target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
-- 
2.34.1



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

* [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (14 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:02   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 17/25] target/riscv: Check SUM in the correct register Richard Henderson
                   ` (13 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Incorporate the virt_enabled and MPV checks into the cpu_mmu_index
function, so we don't have to keep doing it within tlb_fill and
subroutines.  This also elides a flush on changes to MPV.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 50 +++++++++++++--------------------------
 target/riscv/csr.c        |  6 +----
 2 files changed, 18 insertions(+), 38 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 0adfd4a12b..6c42f9c6fd 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -37,19 +37,21 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifdef CONFIG_USER_ONLY
     return 0;
 #else
-    if (ifetch) {
-        return env->priv;
-    }
+    bool virt = riscv_cpu_virt_enabled(env);
+    int mode = env->priv;
 
     /* All priv -> mmu_idx mapping are here */
-    int mode = env->priv;
-    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
-        mode = get_field(env->mstatus, MSTATUS_MPP);
+    if (!ifetch) {
+        if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+            mode = get_field(env->mstatus, MSTATUS_MPP);
+            virt = get_field(env->mstatus, MSTATUS_MPV);
+        }
+        if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
+            mode = MMUIdx_S_SUM;
+        }
     }
-    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
-        return MMUIdx_S_SUM;
-    }
-    return mode;
+
+    return mode | (virt ? MMU_2STAGE_BIT : 0);
 #endif
 }
 
@@ -1165,8 +1167,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
     }
 
     env->badaddr = addr;
-    env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
-                            mmuidx_2stage(mmu_idx);
+    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
     env->two_stage_indirect_lookup = false;
     cpu_loop_exit_restore(cs, retaddr);
 }
@@ -1191,8 +1192,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
         g_assert_not_reached();
     }
     env->badaddr = addr;
-    env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
-                            mmuidx_2stage(mmu_idx);
+    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
     env->two_stage_indirect_lookup = false;
     cpu_loop_exit_restore(cs, retaddr);
 }
@@ -1230,7 +1230,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     int prot, prot2, prot_pmp;
     bool pmp_violation = false;
     bool first_stage_error = true;
-    bool two_stage_lookup = false;
+    bool two_stage_lookup = mmuidx_2stage(mmu_idx);
     bool two_stage_indirect_error = false;
     int ret = TRANSLATE_FAIL;
     int mode = mmu_idx;
@@ -1242,22 +1242,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
                   __func__, address, access_type, mmu_idx);
 
-    /* MPRV does not affect the virtual-machine load/store
-       instructions, HLV, HLVX, and HSV. */
-    if (mmuidx_2stage(mmu_idx)) {
-        ;
-    } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
-               get_field(env->mstatus, MSTATUS_MPRV)) {
-        mode = get_field(env->mstatus, MSTATUS_MPP);
-        if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) {
-            two_stage_lookup = true;
-        }
-    }
-
     pmu_tlb_fill_incr_ctr(cpu, access_type);
-    if (riscv_cpu_virt_enabled(env) ||
-        ((mmuidx_2stage(mmu_idx) || two_stage_lookup) &&
-         access_type != MMU_INST_FETCH)) {
+    if (two_stage_lookup) {
         /* Two stage lookup */
         ret = get_physical_address(env, &pa, &prot, address,
                                    &env->guest_phys_fault_addr, access_type,
@@ -1352,9 +1338,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
         return false;
     } else {
         raise_mmu_exception(env, address, access_type, pmp_violation,
-                            first_stage_error,
-                            riscv_cpu_virt_enabled(env) ||
-                                mmuidx_2stage(mmu_idx),
+                            first_stage_error, two_stage_lookup,
                             two_stage_indirect_error);
         cpu_loop_exit_restore(cs, retaddr);
     }
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b79758a606..1b635373c6 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1246,7 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
     RISCVMXL xl = riscv_cpu_mxl(env);
 
     /* flush tlb on mstatus fields that affect VM */
-    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) {
+    if ((val ^ mstatus) & MSTATUS_MXR) {
         tlb_flush(env_cpu(env));
     }
     mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
@@ -1294,10 +1294,6 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
     uint64_t valh = (uint64_t)val << 32;
     uint64_t mask = MSTATUS_MPV | MSTATUS_GVA;
 
-    if ((valh ^ env->mstatus) & (MSTATUS_MPV)) {
-        tlb_flush(env_cpu(env));
-    }
-
     env->mstatus = (env->mstatus & ~mask) | (valh & mask);
 
     return RISCV_EXCP_NONE;
-- 
2.34.1



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

* [PATCH v6 17/25] target/riscv: Check SUM in the correct register
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (15 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:25   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers Richard Henderson
                   ` (12 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Table 9.5 "Effect of MPRV..." specifies that MPV=1 uses VS-level
vsstatus.SUM instead of HS-level sstatus.SUM.

For HLV/HSV instructions, the HS-level register does not apply, but
the VS-level register presumably does, though this is not mentioned
explicitly in the manual.  However, it matches the behavior for MPV.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 12 ++++++++----
 target/riscv/op_helper.c  |  6 +++++-
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6c42f9c6fd..0017ecbf37 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -42,11 +42,16 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 
     /* All priv -> mmu_idx mapping are here */
     if (!ifetch) {
-        if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+        uint64_t status = env->mstatus;
+
+        if (mode == PRV_M && get_field(status, MSTATUS_MPRV)) {
             mode = get_field(env->mstatus, MSTATUS_MPP);
             virt = get_field(env->mstatus, MSTATUS_MPV);
+            if (virt) {
+                status = env->vsstatus;
+            }
         }
-        if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
+        if (mode == PRV_S && get_field(status, MSTATUS_SUM)) {
             mode = MMUIdx_S_SUM;
         }
     }
@@ -838,8 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         }
         widened = 2;
     }
-    /* status.SUM will be ignored if execute on background */
-    sum = mmuidx_sum(mmu_idx) || use_background || is_debug;
+    sum = mmuidx_sum(mmu_idx) || is_debug;
     switch (vm) {
     case VM_1_10_SV32:
       levels = 2; ptidxbits = 10; ptesize = 4; break;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index db7252e09d..93d4ae8b3e 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -437,7 +437,11 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
     }
 
-    return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT;
+    int mode = get_field(env->hstatus, HSTATUS_SPVP);
+    if (!x && mode == PRV_S && get_field(env->vsstatus, MSTATUS_SUM)) {
+        mode = MMUIdx_S_SUM;
+    }
+    return mode | MMU_2STAGE_BIT;
 }
 
 target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
-- 
2.34.1



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

* [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (16 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 17/25] target/riscv: Check SUM in the correct register Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:25   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop Richard Henderson
                   ` (11 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Move the check from the top of get_physical_address to
the two callers, where passing mmu_idx makes no sense.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 0017ecbf37..833ea6d3fa 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -791,12 +791,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         use_background = true;
     }
 
-    if (first_stage == false) {
-        /* We are in stage 2 translation, this is similar to stage 1. */
-        /* Stage 2 is always taken as U-mode */
-        mode = PRV_U;
-    }
-
     if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
         *physical = addr;
         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -902,7 +896,7 @@ restart:
             /* Do the second stage translation on the base PTE address. */
             int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
                                                  base, NULL, MMU_DATA_LOAD,
-                                                 mmu_idx, false, true,
+                                                 MMUIdx_U, false, true,
                                                  is_debug);
 
             if (vbase_ret != TRANSLATE_SUCCESS) {
@@ -1274,7 +1268,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
             im_address = pa;
 
             ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
-                                       access_type, mmu_idx, false, true,
+                                       access_type, MMUIdx_U, false, true,
                                        false);
 
             qemu_log_mask(CPU_LOG_MMU,
-- 
2.34.1



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

* [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (17 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:26   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 20/25] target/riscv: Move leaf pte processing out of " Richard Henderson
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

These values are constant for every level of pte lookup.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 833ea6d3fa..00f70a3dd5 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -870,6 +870,14 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         return TRANSLATE_FAIL;
     }
 
+    bool pbmte = env->menvcfg & MENVCFG_PBMTE;
+    bool hade = env->menvcfg & MENVCFG_HADE;
+
+    if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
+        pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
+        hade = hade && (env->henvcfg & HENVCFG_HADE);
+    }
+
     int ptshift = (levels - 1) * ptidxbits;
     int i;
 
@@ -930,14 +938,6 @@ restart:
             return TRANSLATE_FAIL;
         }
 
-        bool pbmte = env->menvcfg & MENVCFG_PBMTE;
-        bool hade = env->menvcfg & MENVCFG_HADE;
-
-        if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
-            pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
-            hade = hade && (env->henvcfg & HENVCFG_HADE);
-        }
-
         if (riscv_cpu_sxl(env) == MXL_RV32) {
             ppn = pte >> PTE_PPN_SHIFT;
         } else if (pbmte || cpu->cfg.ext_svnapot) {
-- 
2.34.1



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

* [PATCH v6 20/25] target/riscv: Move leaf pte processing out of level loop
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (18 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:30   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug Richard Henderson
                   ` (9 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Move the code that never loops outside of the loop.
Unchain the if-return-else statements.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 234 +++++++++++++++++++++-----------------
 1 file changed, 127 insertions(+), 107 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 00f70a3dd5..ce12dcec1d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -879,6 +879,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     }
 
     int ptshift = (levels - 1) * ptidxbits;
+    target_ulong pte;
+    hwaddr pte_addr;
     int i;
 
 #if !TCG_OVERSIZED_GUEST
@@ -895,7 +897,6 @@ restart:
         }
 
         /* check that physical address of PTE is legal */
-        hwaddr pte_addr;
 
         if (two_stage && first_stage) {
             int vbase_prot;
@@ -927,7 +928,6 @@ restart:
             return TRANSLATE_PMP_FAIL;
         }
 
-        target_ulong pte;
         if (riscv_cpu_mxl(env) == MXL_RV32) {
             pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
         } else {
@@ -952,120 +952,140 @@ restart:
         if (!(pte & PTE_V)) {
             /* Invalid PTE */
             return TRANSLATE_FAIL;
-        } else if (!pbmte && (pte & PTE_PBMT)) {
+        }
+        if (pte & (PTE_R | PTE_W | PTE_X)) {
+            goto leaf;
+        }
+
+        /* Inner PTE, continue walking */
+        if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
             return TRANSLATE_FAIL;
-        } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
-            /* Inner PTE, continue walking */
-            if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
-                return TRANSLATE_FAIL;
-            }
-            base = ppn << PGSHIFT;
-        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
-            /* Reserved leaf PTE flags: PTE_W */
-            return TRANSLATE_FAIL;
-        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
-            /* Reserved leaf PTE flags: PTE_W + PTE_X */
-            return TRANSLATE_FAIL;
-        } else if ((pte & PTE_U) && ((mode != PRV_U) &&
-                   (!sum || access_type == MMU_INST_FETCH))) {
-            /* User PTE flags when not U mode and mstatus.SUM is not set,
-               or the access type is an instruction fetch */
-            return TRANSLATE_FAIL;
-        } else if (!(pte & PTE_U) && (mode != PRV_S)) {
-            /* Supervisor PTE flags when not S mode */
-            return TRANSLATE_FAIL;
-        } else if (ppn & ((1ULL << ptshift) - 1)) {
-            /* Misaligned PPN */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
-                   ((pte & PTE_X) && mxr))) {
-            /* Read access check failed */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
-            /* Write access check failed */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
-            /* Fetch access check failed */
-            return TRANSLATE_FAIL;
-        } else {
-            /* if necessary, set accessed and dirty bits. */
-            target_ulong updated_pte = pte | PTE_A |
+        }
+        base = ppn << PGSHIFT;
+    }
+
+    /* No leaf pte at any translation level. */
+    return TRANSLATE_FAIL;
+
+ leaf:
+    if (ppn & ((1ULL << ptshift) - 1)) {
+        /* Misaligned PPN */
+        return TRANSLATE_FAIL;
+    }
+    if (!pbmte && (pte & PTE_PBMT)) {
+        /* Reserved without Svpbmt. */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
+        /* Reserved leaf PTE flags: PTE_W */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
+        /* Reserved leaf PTE flags: PTE_W + PTE_X */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & PTE_U) &&
+        ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
+        /*
+         * User PTE flags when not U mode and mstatus.SUM is not set,
+         * or the access type is an instruction fetch.
+         */
+        return TRANSLATE_FAIL;
+    }
+    if (!(pte & PTE_U) && (mode != PRV_S)) {
+        /* Supervisor PTE flags when not S mode */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_DATA_LOAD &&
+        !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
+        /* Read access check failed */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
+        /* Write access check failed */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
+        /* Fetch access check failed */
+        return TRANSLATE_FAIL;
+    }
+
+    /* If necessary, set accessed and dirty bits. */
+    target_ulong updated_pte = pte | PTE_A |
                 (access_type == MMU_DATA_STORE ? PTE_D : 0);
 
-            /* Page table updates need to be atomic with MTTCG enabled */
-            if (updated_pte != pte) {
-                if (!hade) {
-                    return TRANSLATE_FAIL;
-                }
+    /* Page table updates need to be atomic with MTTCG enabled */
+    if (updated_pte != pte) {
+        if (!hade) {
+            return TRANSLATE_FAIL;
+        }
 
-                /*
-                 * - if accessed or dirty bits need updating, and the PTE is
-                 *   in RAM, then we do so atomically with a compare and swap.
-                 * - if the PTE is in IO space or ROM, then it can't be updated
-                 *   and we return TRANSLATE_FAIL.
-                 * - if the PTE changed by the time we went to update it, then
-                 *   it is no longer valid and we must re-walk the page table.
-                 */
-                MemoryRegion *mr;
-                hwaddr l = sizeof(target_ulong), addr1;
-                mr = address_space_translate(cs->as, pte_addr,
-                    &addr1, &l, false, MEMTXATTRS_UNSPECIFIED);
-                if (memory_region_is_ram(mr)) {
-                    target_ulong *pte_pa =
-                        qemu_map_ram_ptr(mr->ram_block, addr1);
+        /*
+         * - if accessed or dirty bits need updating, and the PTE is
+         *   in RAM, then we do so atomically with a compare and swap.
+         * - if the PTE is in IO space or ROM, then it can't be updated
+         *   and we return TRANSLATE_FAIL.
+         * - if the PTE changed by the time we went to update it, then
+         *   it is no longer valid and we must re-walk the page table.
+         */
+        MemoryRegion *mr;
+        hwaddr l = sizeof(target_ulong), addr1;
+        mr = address_space_translate(cs->as, pte_addr, &addr1, &l, false,
+                                     MEMTXATTRS_UNSPECIFIED);
+        if (memory_region_is_ram(mr)) {
+            target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
 #if TCG_OVERSIZED_GUEST
-                    /* MTTCG is not enabled on oversized TCG guests so
-                     * page table updates do not need to be atomic */
-                    *pte_pa = pte = updated_pte;
+            /*
+             * MTTCG is not enabled on oversized TCG guests so
+             * page table updates do not need to be atomic.
+             */
+            *pte_pa = pte = updated_pte;
 #else
-                    target_ulong old_pte =
-                        qatomic_cmpxchg(pte_pa, pte, updated_pte);
-                    if (old_pte != pte) {
-                        goto restart;
-                    } else {
-                        pte = updated_pte;
-                    }
+            target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+            if (old_pte != pte) {
+                goto restart;
+            }
+            pte = updated_pte;
 #endif
-                } else {
-                    /* misconfigured PTE in ROM (AD bits are not preset) or
-                     * PTE is in IO space and can't be updated atomically */
-                    return TRANSLATE_FAIL;
-                }
-            }
-
-            /* for superpage mappings, make a fake leaf PTE for the TLB's
-               benefit. */
-            target_ulong vpn = addr >> PGSHIFT;
-
-            if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
-                napot_bits = ctzl(ppn) + 1;
-                if ((i != (levels - 1)) || (napot_bits != 4)) {
-                    return TRANSLATE_FAIL;
-                }
-            }
-
-            napot_mask = (1 << napot_bits) - 1;
-            *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
-                          (vpn & (((target_ulong)1 << ptshift) - 1))
-                         ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
-
-            /* set permissions on the TLB entry */
-            if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
-                *prot |= PAGE_READ;
-            }
-            if ((pte & PTE_X)) {
-                *prot |= PAGE_EXEC;
-            }
-            /* add write permission on stores or if the page is already dirty,
-               so that we TLB miss on later writes to update the dirty bit */
-            if ((pte & PTE_W) &&
-                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
-                *prot |= PAGE_WRITE;
-            }
-            return TRANSLATE_SUCCESS;
+        } else {
+            /*
+             * Misconfigured PTE in ROM (AD bits are not preset) or
+             * PTE is in IO space and can't be updated atomically.
+             */
+            return TRANSLATE_FAIL;
         }
     }
-    return TRANSLATE_FAIL;
+
+    /* For superpage mappings, make a fake leaf PTE for the TLB's benefit. */
+    target_ulong vpn = addr >> PGSHIFT;
+
+    if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
+        napot_bits = ctzl(ppn) + 1;
+        if ((i != (levels - 1)) || (napot_bits != 4)) {
+            return TRANSLATE_FAIL;
+        }
+    }
+
+    napot_mask = (1 << napot_bits) - 1;
+    *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
+                  (vpn & (((target_ulong)1 << ptshift) - 1))
+                 ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
+
+    /* set permissions on the TLB entry */
+    if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
+        *prot |= PAGE_READ;
+    }
+    if (pte & PTE_X) {
+        *prot |= PAGE_EXEC;
+    }
+    /*
+     * Add write permission on stores or if the page is already dirty,
+     * so that we TLB miss on later writes to update the dirty bit.
+     */
+    if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
+        *prot |= PAGE_WRITE;
+    }
+    return TRANSLATE_SUCCESS;
 }
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
-- 
2.34.1



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

* [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (19 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 20/25] target/riscv: Move leaf pte processing out of " Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:30   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 22/25] target/riscv: Don't modify SUM " Richard Henderson
                   ` (8 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

The debugger should not modify PTE_A or PTE_D.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index ce12dcec1d..b26840e46c 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1015,7 +1015,7 @@ restart:
                 (access_type == MMU_DATA_STORE ? PTE_D : 0);
 
     /* Page table updates need to be atomic with MTTCG enabled */
-    if (updated_pte != pte) {
+    if (updated_pte != pte && !is_debug) {
         if (!hade) {
             return TRANSLATE_FAIL;
         }
-- 
2.34.1



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

* [PATCH v6 22/25] target/riscv: Don't modify SUM with is_debug
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (20 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:31   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags Richard Henderson
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

If we want to give the debugger a greater view of memory than
the cpu, we should simply disable the access check entirely,
not simply for this one corner case.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b26840e46c..850817edfd 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -837,7 +837,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         }
         widened = 2;
     }
-    sum = mmuidx_sum(mmu_idx) || is_debug;
+    sum = mmuidx_sum(mmu_idx);
     switch (vm) {
     case VM_1_10_SV32:
       levels = 2; ptidxbits = 10; ptesize = 4; break;
-- 
2.34.1



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

* [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (21 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 22/25] target/riscv: Don't modify SUM " Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:32   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address Richard Henderson
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 850817edfd..82a7c5f9dd 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -976,14 +976,14 @@ restart:
         /* Reserved without Svpbmt. */
         return TRANSLATE_FAIL;
     }
-    if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
-        /* Reserved leaf PTE flags: PTE_W */
-        return TRANSLATE_FAIL;
-    }
-    if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
-        /* Reserved leaf PTE flags: PTE_W + PTE_X */
+
+    /* Check for reserved combinations of RWX flags. */
+    switch (pte & (PTE_R | PTE_W | PTE_X)) {
+    case PTE_W:
+    case PTE_W | PTE_X:
         return TRANSLATE_FAIL;
     }
+
     if ((pte & PTE_U) &&
         ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
         /*
-- 
2.34.1



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

* [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (22 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  4:55   ` Alistair Francis
  2023-03-25 10:54 ` [PATCH v6 25/25] target/riscv: Reorg sum " Richard Henderson
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

We were effectively computing the protection bits twice,
once while performing access checks and once while returning
the valid bits to the caller.  Reorg so we do this once.

Move the computation of mxr close to its single use.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 69 ++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 82a7c5f9dd..725ca45106 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -762,7 +762,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
  * @is_debug: Is this access from a debugger or the monitor?
  */
 static int get_physical_address(CPURISCVState *env, hwaddr *physical,
-                                int *prot, target_ulong addr,
+                                int *ret_prot, target_ulong addr,
                                 target_ulong *fault_pte_addr,
                                 int access_type, int mmu_idx,
                                 bool first_stage, bool two_stage,
@@ -793,20 +793,14 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 
     if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
         *physical = addr;
-        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         return TRANSLATE_SUCCESS;
     }
 
-    *prot = 0;
+    *ret_prot = 0;
 
     hwaddr base;
-    int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
-
-    if (first_stage == true) {
-        mxr = get_field(env->mstatus, MSTATUS_MXR);
-    } else {
-        mxr = get_field(env->vsstatus, MSTATUS_MXR);
-    }
+    int levels, ptidxbits, ptesize, vm, sum, widened;
 
     if (first_stage == true) {
         if (use_background) {
@@ -849,7 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
       levels = 5; ptidxbits = 9; ptesize = 8; break;
     case VM_1_10_MBARE:
         *physical = addr;
-        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         return TRANSLATE_SUCCESS;
     default:
       g_assert_not_reached();
@@ -984,6 +978,27 @@ restart:
         return TRANSLATE_FAIL;
     }
 
+    int prot = 0;
+    if (pte & PTE_R) {
+        prot |= PAGE_READ;
+    }
+    if (pte & PTE_W) {
+        prot |= PAGE_WRITE;
+    }
+    if (pte & PTE_X) {
+        bool mxr;
+
+        if (first_stage == true) {
+            mxr = get_field(env->mstatus, MSTATUS_MXR);
+        } else {
+            mxr = get_field(env->vsstatus, MSTATUS_MXR);
+        }
+        if (mxr) {
+            prot |= PAGE_READ;
+        }
+        prot |= PAGE_EXEC;
+    }
+
     if ((pte & PTE_U) &&
         ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
         /*
@@ -996,17 +1011,9 @@ restart:
         /* Supervisor PTE flags when not S mode */
         return TRANSLATE_FAIL;
     }
-    if (access_type == MMU_DATA_LOAD &&
-        !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
-        /* Read access check failed */
-        return TRANSLATE_FAIL;
-    }
-    if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
-        /* Write access check failed */
-        return TRANSLATE_FAIL;
-    }
-    if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
-        /* Fetch access check failed */
+
+    if (!((prot >> access_type) & 1)) {
+        /* Access check failed */
         return TRANSLATE_FAIL;
     }
 
@@ -1071,20 +1078,16 @@ restart:
                   (vpn & (((target_ulong)1 << ptshift) - 1))
                  ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
 
-    /* set permissions on the TLB entry */
-    if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
-        *prot |= PAGE_READ;
-    }
-    if (pte & PTE_X) {
-        *prot |= PAGE_EXEC;
-    }
     /*
-     * Add write permission on stores or if the page is already dirty,
-     * so that we TLB miss on later writes to update the dirty bit.
+     * Remove write permission unless this is a store, or the page is
+     * already dirty, so that we TLB miss on later writes to update
+     * the dirty bit.
      */
-    if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
-        *prot |= PAGE_WRITE;
+    if (access_type != MMU_DATA_STORE && !(pte & PTE_D)) {
+        prot &= ~PAGE_WRITE;
     }
+    *ret_prot = prot;
+
     return TRANSLATE_SUCCESS;
 }
 
-- 
2.34.1



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

* [PATCH v6 25/25] target/riscv: Reorg sum check in get_physical_address
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (23 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address Richard Henderson
@ 2023-03-25 10:54 ` Richard Henderson
  2023-04-11  5:36   ` Alistair Francis
  2023-03-26  5:17 ` [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (4 subsequent siblings)
  29 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-25 10:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

Implement this by adjusting prot, which reduces the set of
checks required.  This prevents exec to be set for U pages
in MMUIdx_S_SUM.  While it had been technically incorrect,
it did not manifest as a bug, because we will never attempt
to execute from MMUIdx_S_SUM.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 725ca45106..7336d1273b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -800,7 +800,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     *ret_prot = 0;
 
     hwaddr base;
-    int levels, ptidxbits, ptesize, vm, sum, widened;
+    int levels, ptidxbits, ptesize, vm, widened;
 
     if (first_stage == true) {
         if (use_background) {
@@ -831,7 +831,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         }
         widened = 2;
     }
-    sum = mmuidx_sum(mmu_idx);
+
     switch (vm) {
     case VM_1_10_SV32:
       levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -999,15 +999,15 @@ restart:
         prot |= PAGE_EXEC;
     }
 
-    if ((pte & PTE_U) &&
-        ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
-        /*
-         * User PTE flags when not U mode and mstatus.SUM is not set,
-         * or the access type is an instruction fetch.
-         */
-        return TRANSLATE_FAIL;
-    }
-    if (!(pte & PTE_U) && (mode != PRV_S)) {
+    if (pte & PTE_U) {
+        if (mode != PRV_U) {
+            if (!mmuidx_sum(mmu_idx)) {
+                return TRANSLATE_FAIL;
+            }
+            /* SUM allows only read+write, not execute. */
+            prot &= PAGE_READ | PAGE_WRITE;
+        }
+    } else if (mode != PRV_S) {
         /* Supervisor PTE flags when not S mode */
         return TRANSLATE_FAIL;
     }
-- 
2.34.1



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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (24 preceding siblings ...)
  2023-03-25 10:54 ` [PATCH v6 25/25] target/riscv: Reorg sum " Richard Henderson
@ 2023-03-26  5:17 ` Richard Henderson
  2023-03-26 14:18 ` liweiwei
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-26  5:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On 3/25/23 03:54, Richard Henderson wrote:
> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
> 
>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
> 
>    * Using cpu_mmu_index(env, true) is insufficient to implement
>      HLVX properly.  While that chooses the correct mmu_idx, it
>      does not perform the read with execute permission.
>      I add a new tcg interface to perform a read-for-execute with
>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>      it's closer.
> 
>    * Handle mstatus.MPV in cpu_mmu_index.
>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>    * Cleanups for get_physical_address.
> 
> While this passes check-avocado, I'm sure that's insufficient.
> Please have a close look.

Somewhere after either patch 16 or 17, when env->virt is considered in riscv_cpu_mmu_index 
and a few other bugs are fixed, we can do

--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -591,11 +591,6 @@ void riscv_cpu_set_virt_enabled
          return;
      }

-    /* Flush the TLB on all virt mode changes. */
-    if (get_field(env->virt, VIRT_ONOFF) != enable) {
-        tlb_flush(env_cpu(env));
-    }
-
      env->virt = set_field(env->virt, VIRT_ONOFF, enable);

      if (enable) {
-- %< --

Because we're no longer trying to overlap the VS and HS tlbs on the same mmuidx.

I have been pondering additional changes that would avoid flushing for MXR changes, so 
that user-lookups from M-mode firmware gets the same advantage as has just been done for 
SUM.  But this is complicated by needing 12 (!) more mmuidx, which cannot currently be 
represented, nor does it even seem like the best idea.


r~


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

* Re: [PATCH v6 02/25] target/riscv: Add a general status enum for extensions
  2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
@ 2023-03-26 12:54   ` liweiwei
  2023-04-11  2:05   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: liweiwei @ 2023-03-26 12:54 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, liweiwei


On 2023/3/25 18:54, Richard Henderson wrote:
> From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> The pointer masking is the only extension that directly use status.
> The vector or float extension uses the status in an indirect way.
>
> Replace the pointer masking extension special status fields with
> the general status.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
> Message-Id: <20230324143031.1093-3-zhiwei_liu@linux.alibaba.com>
> [rth: Add a typedef for the enum]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>

Weiwei Li
>   target/riscv/cpu.h      |  8 ++++++++
>   target/riscv/cpu_bits.h | 12 ++++--------
>   target/riscv/cpu.c      |  2 +-
>   target/riscv/csr.c      | 14 +++++++-------
>   4 files changed, 20 insertions(+), 16 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 12fe8d8546..30d9828d59 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -99,6 +99,14 @@ enum {
>       TRANSLATE_G_STAGE_FAIL
>   };
>   
> +/* Extension context status */
> +typedef enum {
> +    EXT_STATUS_DISABLED = 0,
> +    EXT_STATUS_INITIAL,
> +    EXT_STATUS_CLEAN,
> +    EXT_STATUS_DIRTY,
> +} RISCVExtStatus;
> +
>   #define MMU_USER_IDX 3
>   
>   #define MAX_RISCV_PMPS (16)
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index fca7ef0cef..b84f62f8d6 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -9,6 +9,9 @@
>                    (((uint64_t)(val) * ((mask) & ~((mask) << 1))) & \
>                    (uint64_t)(mask)))
>   
> +/* Extension context status mask */
> +#define EXT_STATUS_MASK     0x3ULL
> +
>   /* Floating point round mode */
>   #define FSR_RD_SHIFT        5
>   #define FSR_RD              (0x7 << FSR_RD_SHIFT)
> @@ -734,13 +737,6 @@ typedef enum RISCVException {
>   #define PM_ENABLE       0x00000001ULL
>   #define PM_CURRENT      0x00000002ULL
>   #define PM_INSN         0x00000004ULL
> -#define PM_XS_MASK      0x00000003ULL
> -
> -/* PointerMasking XS bits values */
> -#define PM_EXT_DISABLE  0x00000000ULL
> -#define PM_EXT_INITIAL  0x00000001ULL
> -#define PM_EXT_CLEAN    0x00000002ULL
> -#define PM_EXT_DIRTY    0x00000003ULL
>   
>   /* Execution enviornment configuration bits */
>   #define MENVCFG_FIOM                       BIT(0)
> @@ -780,7 +776,7 @@ typedef enum RISCVException {
>   #define S_OFFSET     5ULL
>   #define M_OFFSET     8ULL
>   
> -#define PM_XS_BITS   (PM_XS_MASK << XS_OFFSET)
> +#define PM_XS_BITS   (EXT_STATUS_MASK << XS_OFFSET)
>   #define U_PM_ENABLE  (PM_ENABLE  << U_OFFSET)
>   #define U_PM_CURRENT (PM_CURRENT << U_OFFSET)
>   #define U_PM_INSN    (PM_INSN    << U_OFFSET)
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1e97473af2..1135106b3e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -764,7 +764,7 @@ static void riscv_cpu_reset_hold(Object *obj)
>           i++;
>       }
>       /* mmte is supposed to have pm.current hardwired to 1 */
> -    env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
> +    env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
>   #endif
>       env->xl = riscv_cpu_mxl(env);
>       riscv_cpu_update_mask(env);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index d522efc0b6..abea7b749e 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3513,7 +3513,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno,
>   
>       /* hardwiring pm.instruction bit to 0, since it's not supported yet */
>       wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
> -    env->mmte = wpri_val | PM_EXT_DIRTY;
> +    env->mmte = wpri_val | EXT_STATUS_DIRTY;
>       riscv_cpu_update_mask(env);
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -3593,7 +3593,7 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
>           env->cur_pmmask = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;
> @@ -3621,7 +3621,7 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
>           env->cur_pmmask = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;
> @@ -3649,7 +3649,7 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
>           env->cur_pmmask = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;
> @@ -3673,7 +3673,7 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
>           env->cur_pmbase = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;
> @@ -3701,7 +3701,7 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
>           env->cur_pmbase = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;
> @@ -3729,7 +3729,7 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
>       if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
>           env->cur_pmbase = val;
>       }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>   
>       /* Set XS and SD bits, since PM CSRs are dirty */
>       mstatus = env->mstatus | MSTATUS_XS;



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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (25 preceding siblings ...)
  2023-03-26  5:17 ` [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
@ 2023-03-26 14:18 ` liweiwei
  2023-03-27 16:43 ` Daniel Henrique Barboza
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 70+ messages in thread
From: liweiwei @ 2023-03-26 14:18 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, liweiwei

[-- Attachment #1: Type: text/plain, Size: 3545 bytes --]


On 2023/3/25 18:54, Richard Henderson wrote:
> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
>
>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
>
>    * Using cpu_mmu_index(env, true) is insufficient to implement
>      HLVX properly.  While that chooses the correct mmu_idx, it
>      does not perform the read with execute permission.
>      I add a new tcg interface to perform a read-for-execute with
>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>      it's closer.
>
>    * Handle mstatus.MPV in cpu_mmu_index.
>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>    * Cleanups for get_physical_address.
>
> While this passes check-avocado, I'm sure that's insufficient.
> Please have a close look.
>
>
> r~
>
>
> Fei Wu (2):
>    target/riscv: Separate priv from mmu_idx
>    target/riscv: Reduce overhead of MSTATUS_SUM change
>
> LIU Zhiwei (4):
>    target/riscv: Extract virt enabled state from tb flags
>    target/riscv: Add a general status enum for extensions
>    target/riscv: Encode the FS and VS on a normal way for tb flags
>    target/riscv: Add a tb flags field for vstart
>
> Richard Henderson (19):
>    target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>    accel/tcg: Add cpu_ld*_code_mmu
>    target/riscv: Use cpu_ld*_code_mmu for HLVX
>    target/riscv: Handle HLV, HSV via helpers
>    target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>    target/riscv: Introduce mmuidx_sum
>    target/riscv: Introduce mmuidx_priv
>    target/riscv: Introduce mmuidx_2stage
>    target/riscv: Move hstatus.spvp check to check_access_hlsv
>    target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>    target/riscv: Check SUM in the correct register
>    target/riscv: Hoist second stage mode change to callers
>    target/riscv: Hoist pbmte and hade out of the level loop
>    target/riscv: Move leaf pte processing out of level loop
>    target/riscv: Suppress pte update with is_debug
>    target/riscv: Don't modify SUM with is_debug
>    target/riscv: Merge checks for reserved pte flags
>    target/riscv: Reorg access check in get_physical_address
>    target/riscv: Reorg sum check in get_physical_address
>
>   include/exec/cpu_ldst.h                       |   9 +
>   target/riscv/cpu.h                            |  47 ++-
>   target/riscv/cpu_bits.h                       |  12 +-
>   target/riscv/helper.h                         |  12 +-
>   target/riscv/internals.h                      |  35 ++
>   accel/tcg/cputlb.c                            |  48 +++
>   accel/tcg/user-exec.c                         |  58 +++
>   target/riscv/cpu.c                            |   2 +-
>   target/riscv/cpu_helper.c                     | 393 +++++++++---------
>   target/riscv/csr.c                            |  21 +-
>   target/riscv/op_helper.c                      | 113 ++++-
>   target/riscv/translate.c                      |  72 ++--
>   .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>   target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>   target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>   target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>   target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>   17 files changed, 595 insertions(+), 395 deletions(-)

This patchset is LGTM.  Patch 16 seems fix a bug in the two_stage 
parameter of raise_mmu_exception

called when translation fails,  it didn't take MPV into consideration in 
original implementation.

Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>

Weiwei Li

>

[-- Attachment #2: Type: text/html, Size: 4166 bytes --]

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

* Re: [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags
  2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
@ 2023-03-27  1:34   ` liweiwei
  2023-03-27 16:22     ` Richard Henderson
  2023-03-28  2:34   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs,vs} " LIU Zhiwei
  2023-04-11  2:02   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} " Alistair Francis
  2 siblings, 1 reply; 70+ messages in thread
From: liweiwei @ 2023-03-27  1:34 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu, liweiwei


On 2023/3/25 18:54, Richard Henderson wrote:
> Merge with mstatus_{fs,vs}.  We might perform a redundant
> assignment to one or the other field, but it's a trivial
> and saves 4 bits from TB_FLAGS.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/riscv/cpu.h        | 16 +++++++---------
>   target/riscv/cpu_helper.c | 34 ++++++++++++++++------------------
>   target/riscv/translate.c  | 32 ++++++++++----------------------
>   3 files changed, 33 insertions(+), 49 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index f787145a21..d9e0eaaf9b 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -646,19 +646,17 @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
>   FIELD(TB_FLAGS, VILL, 14, 1)
>   /* Is a Hypervisor instruction load/store allowed? */
>   FIELD(TB_FLAGS, HLSX, 15, 1)
> -FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
> -FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2)
>   /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
> -FIELD(TB_FLAGS, XL, 20, 2)
> +FIELD(TB_FLAGS, XL, 16, 2)
>   /* If PointerMasking should be applied */
> -FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
> -FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
> -FIELD(TB_FLAGS, VTA, 24, 1)
> -FIELD(TB_FLAGS, VMA, 25, 1)
> +FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1)
> +FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1)
> +FIELD(TB_FLAGS, VTA, 20, 1)
> +FIELD(TB_FLAGS, VMA, 21, 1)
>   /* Native debug itrigger */
> -FIELD(TB_FLAGS, ITRIGGER, 26, 1)
> +FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>   /* Virtual mode enabled */
> -FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
> +FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>   
>   #ifdef TARGET_RISCV32
>   #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 1e7ee9aa30..4fdd6fe021 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -45,7 +45,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>   {
>       CPUState *cs = env_cpu(env);
>       RISCVCPU *cpu = RISCV_CPU(cs);
> -
> +    RISCVExtStatus fs, vs;
>       uint32_t flags = 0;
>   
>       *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
> @@ -79,18 +79,12 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>       }
>   
>   #ifdef CONFIG_USER_ONLY
> -    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
> -    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
> +    fs = EXT_STATUS_DIRTY;
> +    vs = EXT_STATUS_DIRTY;
>   #else
>       flags |= cpu_mmu_index(env, 0);
> -    if (riscv_cpu_fp_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
> -                            get_field(env->mstatus,  MSTATUS_FS));
> -    }
> -    if (riscv_cpu_vector_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
> -                            get_field(env->mstatus, MSTATUS_VS));
> -    }
> +    fs = get_field(env->mstatus, MSTATUS_FS);
> +    vs = get_field(env->mstatus, MSTATUS_VS);
>   
>       if (riscv_has_ext(env, RVH)) {
>           if (env->priv == PRV_M ||
> @@ -100,19 +94,23 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>               flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
>           }
>   
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
> -                           get_field(env->mstatus_hs, MSTATUS_FS));
> -
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
> -                           get_field(env->mstatus_hs, MSTATUS_VS));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
> -                           get_field(env->virt, VIRT_ONOFF));
> +        if (riscv_cpu_virt_enabled(env)) {
> +            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +            /*
> +             * Merge DISABLED and !DIRTY states using MIN.
> +             * We will set both fields when dirtying.
> +             */
> +            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> +            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> +        }
>       }
>       if (cpu->cfg.debug && !icount_enabled()) {
>           flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>       }
>   #endif
>   
> +    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
>       flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
>       if (env->cur_pmmask < (env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX)) {
>           flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index b897bf6006..74d0b9889d 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -66,8 +66,6 @@ typedef struct DisasContext {
>       uint32_t opcode;
>       RISCVExtStatus mstatus_fs;
>       RISCVExtStatus mstatus_vs;
> -    RISCVExtStatus mstatus_hs_fs;
> -    RISCVExtStatus mstatus_hs_vs;
>       uint32_t mem_idx;
>       /* Remember the rounding mode encoded in the previous fp instruction,
>          which we have already installed into env->fp_status.  Or -1 for
> @@ -618,16 +616,12 @@ static void mark_fs_dirty(DisasContext *ctx)
>           tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>           tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
>           tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>   
> -    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }

We seems only need to know whether fs/vs is dirty,  so maybe we can just 
use a bool for them to save more bits from TB_FLAGS.

Regards,

Weiwei Li

>       }
>   }
>   #else
> @@ -651,16 +645,12 @@ static void mark_vs_dirty(DisasContext *ctx)
>           tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>           tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
>           tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>   
> -    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }
>       }
>   }
>   #else
> @@ -1158,8 +1148,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       ctx->misa_ext = env->misa_ext;
>       ctx->frm = -1;  /* unknown rounding mode */
>       ctx->cfg_ptr = &(cpu->cfg);
> -    ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
> -    ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
>       ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
>       ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
>       ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);



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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
@ 2023-03-27  2:07   ` LIU Zhiwei
  2023-03-27 16:29     ` Richard Henderson
  2023-04-11  3:53   ` Alistair Francis
  1 sibling, 1 reply; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-27  2:07 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, fei2.wu


On 2023/3/25 18:54, Richard Henderson wrote:
> Use the priv level encoded into the mmu_idx, rather than
> starting from env->priv.  We have already checked MPRV+MPP
> in riscv_cpu_mmu_index -- no need to repeat that.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/riscv/internals.h  | 9 +++++++++
>   target/riscv/cpu_helper.c | 6 +-----
>   2 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 0b61f337dd..4aa1cb409f 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -37,6 +37,15 @@
>   #define MMUIdx_M            3
>   #define MMU_2STAGE_BIT      (1 << 2)
>   
> +static inline int mmuidx_priv(int mmu_idx)
> +{
> +    int ret = mmu_idx & 3;
> +    if (ret == MMUIdx_S_SUM) {
> +        ret = PRV_S;
> +    }
> +    return ret;
> +}
> +

Can we remove the PRIV from the tb flags after we have this function?

Best Regards,
Zhiwei

>   static inline bool mmuidx_sum(int mmu_idx)
>   {
>       return (mmu_idx & 3) == MMUIdx_S_SUM;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 7e6cd8e0fd..cb260b88ea 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -771,7 +771,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>        * (riscv_cpu_do_interrupt) is correct */
>       MemTxResult res;
>       MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
> -    int mode = env->priv;
> +    int mode = mmuidx_priv(mmu_idx);
>       bool use_background = false;
>       hwaddr ppn;
>       RISCVCPU *cpu = env_archcpu(env);
> @@ -793,10 +793,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          instructions, HLV, HLVX, and HSV. */
>       if (riscv_cpu_two_stage_lookup(mmu_idx)) {
>           mode = get_field(env->hstatus, HSTATUS_SPVP);
> -    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> -            mode = get_field(env->mstatus, MSTATUS_MPP);
> -        }
>       }
>   
>       if (first_stage == false) {


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

* Re: [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags
  2023-03-27  1:34   ` liweiwei
@ 2023-03-27 16:22     ` Richard Henderson
  0 siblings, 0 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-27 16:22 UTC (permalink / raw)
  To: liweiwei, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On 3/26/23 18:34, liweiwei wrote:
> We seems only need to know whether fs/vs is dirty,  so maybe we can just use a bool for 
> them to save more bits from TB_FLAGS.

No, we also need disabled.  That is checked in REQUIRE_FPU, require_rvv, etc.


r~


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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-27  2:07   ` LIU Zhiwei
@ 2023-03-27 16:29     ` Richard Henderson
  2023-03-28  1:33       ` LIU Zhiwei
  0 siblings, 1 reply; 70+ messages in thread
From: Richard Henderson @ 2023-03-27 16:29 UTC (permalink / raw)
  To: LIU Zhiwei, qemu-devel; +Cc: qemu-riscv, alistair.francis, palmer, fei2.wu

On 3/26/23 19:07, LIU Zhiwei wrote:
>> +static inline int mmuidx_priv(int mmu_idx)
>> +{
>> +    int ret = mmu_idx & 3;
>> +    if (ret == MMUIdx_S_SUM) {
>> +        ret = PRV_S;
>> +    }
>> +    return ret;
>> +}
>> +
> 
> Can we remove the PRIV from the tb flags after we have this function?

No, because this is the priv of the memory operation as modified by e.g. MPRV, not the 
true cpu priv.


r~


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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (26 preceding siblings ...)
  2023-03-26 14:18 ` liweiwei
@ 2023-03-27 16:43 ` Daniel Henrique Barboza
  2023-03-28  1:22   ` Wu, Fei
  2023-04-04  6:42 ` Wu, Fei
  2023-04-11  5:38 ` Alistair Francis
  29 siblings, 1 reply; 70+ messages in thread
From: Daniel Henrique Barboza @ 2023-03-27 16:43 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu



On 3/25/23 07:54, Richard Henderson wrote:
> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
> 
>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
> 
>    * Using cpu_mmu_index(env, true) is insufficient to implement
>      HLVX properly.  While that chooses the correct mmu_idx, it
>      does not perform the read with execute permission.
>      I add a new tcg interface to perform a read-for-execute with
>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>      it's closer.
> 
>    * Handle mstatus.MPV in cpu_mmu_index.
>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>    * Cleanups for get_physical_address.
> 
> While this passes check-avocado, I'm sure that's insufficient.
> Please have a close look.

Tested fine in my end with some buildroot tests and 'stress-ng' in a 'virt'
machine with Ubuntu.

Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

> 
> 
> r~
> 
> 
> Fei Wu (2):
>    target/riscv: Separate priv from mmu_idx
>    target/riscv: Reduce overhead of MSTATUS_SUM change
> 
> LIU Zhiwei (4):
>    target/riscv: Extract virt enabled state from tb flags
>    target/riscv: Add a general status enum for extensions
>    target/riscv: Encode the FS and VS on a normal way for tb flags
>    target/riscv: Add a tb flags field for vstart
> 
> Richard Henderson (19):
>    target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>    accel/tcg: Add cpu_ld*_code_mmu
>    target/riscv: Use cpu_ld*_code_mmu for HLVX
>    target/riscv: Handle HLV, HSV via helpers
>    target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>    target/riscv: Introduce mmuidx_sum
>    target/riscv: Introduce mmuidx_priv
>    target/riscv: Introduce mmuidx_2stage
>    target/riscv: Move hstatus.spvp check to check_access_hlsv
>    target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>    target/riscv: Check SUM in the correct register
>    target/riscv: Hoist second stage mode change to callers
>    target/riscv: Hoist pbmte and hade out of the level loop
>    target/riscv: Move leaf pte processing out of level loop
>    target/riscv: Suppress pte update with is_debug
>    target/riscv: Don't modify SUM with is_debug
>    target/riscv: Merge checks for reserved pte flags
>    target/riscv: Reorg access check in get_physical_address
>    target/riscv: Reorg sum check in get_physical_address
> 
>   include/exec/cpu_ldst.h                       |   9 +
>   target/riscv/cpu.h                            |  47 ++-
>   target/riscv/cpu_bits.h                       |  12 +-
>   target/riscv/helper.h                         |  12 +-
>   target/riscv/internals.h                      |  35 ++
>   accel/tcg/cputlb.c                            |  48 +++
>   accel/tcg/user-exec.c                         |  58 +++
>   target/riscv/cpu.c                            |   2 +-
>   target/riscv/cpu_helper.c                     | 393 +++++++++---------
>   target/riscv/csr.c                            |  21 +-
>   target/riscv/op_helper.c                      | 113 ++++-
>   target/riscv/translate.c                      |  72 ++--
>   .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>   target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>   target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>   target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>   target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>   17 files changed, 595 insertions(+), 395 deletions(-)
> 


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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-27 16:43 ` Daniel Henrique Barboza
@ 2023-03-28  1:22   ` Wu, Fei
  0 siblings, 0 replies; 70+ messages in thread
From: Wu, Fei @ 2023-03-28  1:22 UTC (permalink / raw)
  To: Daniel Henrique Barboza, Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu

On 3/28/2023 12:43 AM, Daniel Henrique Barboza wrote:
> 
> 
> On 3/25/23 07:54, Richard Henderson wrote:
>> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
>>
>>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
>>
>>    * Using cpu_mmu_index(env, true) is insufficient to implement
>>      HLVX properly.  While that chooses the correct mmu_idx, it
>>      does not perform the read with execute permission.
>>      I add a new tcg interface to perform a read-for-execute with
>>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>>      it's closer.
>>
>>    * Handle mstatus.MPV in cpu_mmu_index.
>>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>>    * Cleanups for get_physical_address.
>>
>> While this passes check-avocado, I'm sure that's insufficient.
>> Please have a close look.
> 
> Tested fine in my end with some buildroot tests and 'stress-ng' in a 'virt'
> machine with Ubuntu.
> 
> Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> 
Great. I suppose class 'os' in stress-ng should see performance boost too.

btw, Is there any public URL for us to check QEMU regressions and
performance data?

Thanks,
Fei.

>>
>>
>> r~
>>
>>
>> Fei Wu (2):
>>    target/riscv: Separate priv from mmu_idx
>>    target/riscv: Reduce overhead of MSTATUS_SUM change
>>
>> LIU Zhiwei (4):
>>    target/riscv: Extract virt enabled state from tb flags
>>    target/riscv: Add a general status enum for extensions
>>    target/riscv: Encode the FS and VS on a normal way for tb flags
>>    target/riscv: Add a tb flags field for vstart
>>
>> Richard Henderson (19):
>>    target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>>    accel/tcg: Add cpu_ld*_code_mmu
>>    target/riscv: Use cpu_ld*_code_mmu for HLVX
>>    target/riscv: Handle HLV, HSV via helpers
>>    target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>>    target/riscv: Introduce mmuidx_sum
>>    target/riscv: Introduce mmuidx_priv
>>    target/riscv: Introduce mmuidx_2stage
>>    target/riscv: Move hstatus.spvp check to check_access_hlsv
>>    target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>>    target/riscv: Check SUM in the correct register
>>    target/riscv: Hoist second stage mode change to callers
>>    target/riscv: Hoist pbmte and hade out of the level loop
>>    target/riscv: Move leaf pte processing out of level loop
>>    target/riscv: Suppress pte update with is_debug
>>    target/riscv: Don't modify SUM with is_debug
>>    target/riscv: Merge checks for reserved pte flags
>>    target/riscv: Reorg access check in get_physical_address
>>    target/riscv: Reorg sum check in get_physical_address
>>
>>   include/exec/cpu_ldst.h                       |   9 +
>>   target/riscv/cpu.h                            |  47 ++-
>>   target/riscv/cpu_bits.h                       |  12 +-
>>   target/riscv/helper.h                         |  12 +-
>>   target/riscv/internals.h                      |  35 ++
>>   accel/tcg/cputlb.c                            |  48 +++
>>   accel/tcg/user-exec.c                         |  58 +++
>>   target/riscv/cpu.c                            |   2 +-
>>   target/riscv/cpu_helper.c                     | 393 +++++++++---------
>>   target/riscv/csr.c                            |  21 +-
>>   target/riscv/op_helper.c                      | 113 ++++-
>>   target/riscv/translate.c                      |  72 ++--
>>   .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>>   target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>>   target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>>   target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>>   target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>>   17 files changed, 595 insertions(+), 395 deletions(-)
>>



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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-27 16:29     ` Richard Henderson
@ 2023-03-28  1:33       ` LIU Zhiwei
  2023-03-28  1:54         ` LIU Zhiwei
  0 siblings, 1 reply; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-28  1:33 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, fei2.wu


On 2023/3/28 0:29, Richard Henderson wrote:
> On 3/26/23 19:07, LIU Zhiwei wrote:
>>> +static inline int mmuidx_priv(int mmu_idx)
>>> +{
>>> +    int ret = mmu_idx & 3;
>>> +    if (ret == MMUIdx_S_SUM) {
>>> +        ret = PRV_S;
>>> +    }
>>> +    return ret;
>>> +}
>>> +
>>
>> Can we remove the PRIV from the tb flags after we have this function?
>
> No, because this is the priv of the memory operation as modified by 
> e.g. MPRV, not the true cpu priv.

For this implementation, we explicitly use the tb flags for mmu index. I 
think it is the reason why we have to maintain the redundant privilege 
in tb flags.
It may be better to only store machine states into tb flags. Can we just 
pass everything that we need, for example, the priv and sum, and then 
implicitly
calculate the ctx->mem_idx in disas_init_fn?

I remember that you give the similar suggestion in the comment process

https://mail.gnu.org/archive/html/qemu-riscv/2023-03/msg00566.html

Best Regards,
Zhiwei

>
>
> r~


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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-28  1:33       ` LIU Zhiwei
@ 2023-03-28  1:54         ` LIU Zhiwei
  2023-03-28 14:27           ` Richard Henderson
  0 siblings, 1 reply; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-28  1:54 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel


On 2023/3/28 9:33, LIU Zhiwei wrote:
>
> On 2023/3/28 0:29, Richard Henderson wrote:
>> On 3/26/23 19:07, LIU Zhiwei wrote:
>>>> +static inline int mmuidx_priv(int mmu_idx)
>>>> +{
>>>> +    int ret = mmu_idx & 3;
>>>> +    if (ret == MMUIdx_S_SUM) {
>>>> +        ret = PRV_S;
>>>> +    }
>>>> +    return ret;
>>>> +}
>>>> +
>>>
>>> Can we remove the PRIV from the tb flags after we have this function?
>>
>> No, because this is the priv of the memory operation as modified by 
>> e.g. MPRV, not the true cpu priv.
>
> For this implementation, we explicitly use the tb flags for mmu index. 
> I think it is the reason why we have to maintain the redundant 
> privilege in tb flags.
> It may be better to only store machine states into tb flags. Can we 
> just pass everything that we need, for example, the priv and sum, and 
> then implicitly
> calculate the ctx->mem_idx in disas_init_fn?
>
> I remember that you give the similar suggestion in the comment process
>
> https://mail.gnu.org/archive/html/qemu-riscv/2023-03/msg00566.html
>
> Best Regards,
> Zhiwei
>
To make this comment clear, I paste a simple implementatioin here. But 
it is just for discussing, not a normal patch for merging.

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 623288e6f9..d4506be5be 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -632,12 +632,10 @@ G_NORETURN void 
riscv_raise_exception(CPURISCVState *env,
  target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
  void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);

-#define TB_FLAGS_PRIV_MMU_MASK                3
-#define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
-
  #include "exec/cpu-all.h"

-FIELD(TB_FLAGS, MEM_IDX, 0, 3)
+FIELD(TB_FLAGS, PRIV, 0, 2)
+FIELD(TB_FLAGS, SUM, 2, 1)
  FIELD(TB_FLAGS, FS, 3, 2)
  /* Vector flags */
  FIELD(TB_FLAGS, VS, 5, 2)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f80d069884..b11f583643 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -30,6 +30,7 @@
  #include "sysemu/cpu-timers.h"
  #include "cpu_bits.h"
  #include "debug.h"
+#include "internals.h"

  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
  {
@@ -40,6 +41,20 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
  #endif
  }

+#ifndef CONFIG_USER_ONLY
+static bool riscv_cpu_sum_enabled(CPURISCVState *env)
+{
+    int mode = env->priv;
+    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+        mode = get_field(env->mstatus, MSTATUS_MPP);
+    }
+    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
+        return true;
+    }
+    return false;
+}
+#endif
+
  void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
                            target_ulong *cs_base, uint32_t *pflags)
  {
@@ -80,10 +95,11 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, 
target_ulong *pc,
      }

  #ifdef CONFIG_USER_ONLY
     flags =  FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
     flags =  FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
  #else
-    flags |= cpu_mmu_index(env, 0);
+    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
+    flags = FIELD_DP32(flags, TB_FLAGS, SUM, riscv_cpu_sum_enabled(env));
      if (riscv_cpu_fp_enabled(env)) {
          flags =  FIELD_DP32(flags, TB_FLAGS, FS,
                              get_field(env->mstatus, MSTATUS_FS));
@@ -600,7 +616,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, 
bool enable)

  bool riscv_cpu_two_stage_lookup(int mmu_idx)
  {
-    return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    return mmu_idx & MMU_HYP_ACCESS_BIT;
  }

  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
@@ -766,7 +782,7 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
       * (riscv_cpu_do_interrupt) is correct */
      MemTxResult res;
      MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
-    int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
+    int mode = mmu_idx;
      bool use_background = false;
      hwaddr ppn;
      RISCVCPU *cpu = env_archcpu(env);
@@ -788,10 +804,8 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
         instructions, HLV, HLVX, and HSV. */
      if (riscv_cpu_two_stage_lookup(mmu_idx)) {
          mode = get_field(env->hstatus, HSTATUS_SPVP);
-    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
-        if (get_field(env->mstatus, MSTATUS_MPRV)) {
-            mode = get_field(env->mstatus, MSTATUS_MPP);
-        }
+    } else if (mmu_idx == MMUIdx_S_SUM) {
+        mode = PRV_S;
      }
      if (first_stage == false) {
@@ -847,7 +861,7 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
          widened = 2;
      }
      /* status.SUM will be ignored if execute on background */
-    sum = get_field(env->mstatus, MSTATUS_SUM) || use_background || 
is_debug;
+    sum = (mmu_idx == MMUIdx_S_SUM) || use_background || is_debug;
      switch (vm) {
      case VM_1_10_SV32:
        levels = 2; ptidxbits = 10; ptesize = 4; break;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index abea7b749e..dd5f774b2f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1247,7 +1247,7 @@ static RISCVException write_mstatus(CPURISCVState 
*env, int csrno,

      /* flush tlb on mstatus fields that affect VM */
      if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
-            MSTATUS_MPRV | MSTATUS_SUM)) {
+            MSTATUS_MPRV)) {
          tlb_flush(env_cpu(env));
      }
      mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc 
b/target/riscv/insn_trans/trans_privileged.c.inc
index 59501b2780..9305b18299 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -52,7 +52,7 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
       * that no exception will be raised when fetching them.
       */

-    if (semihosting_enabled(ctx->mem_idx < PRV_S) &&
+    if (semihosting_enabled(ctx->priv < PRV_S) &&
          (pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
          pre    = opcode_at(&ctx->base, pre_addr);
          ebreak = opcode_at(&ctx->base, ebreak_addr);
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
b/target/riscv/insn_trans/trans_rvh.c.inc
index 9248b48c36..15842f4282 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -40,7 +40,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp 
mop)
      if (check_access(ctx)) {
          TCGv dest = dest_gpr(ctx, a->rd);
          TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
          tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
          gen_set_gpr(ctx, a->rd, dest);
      }
@@ -87,7 +87,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, 
MemOp mop)
      if (check_access(ctx)) {
          TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
          TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
-        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
          tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
      }
      return true;
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc 
b/target/riscv/insn_trans/trans_xthead.c.inc
index df504c3f2c..a6d823b382 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -263,23 +263,13 @@ static bool trans_th_tst(DisasContext *ctx, 
arg_th_tst *a)

  /* XTheadCmo */

-static inline int priv_level(DisasContext *ctx)
-{
-#ifdef CONFIG_USER_ONLY
-    return PRV_U;
-#else
-     /* Priv level is part of mem_idx. */
-    return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
-#endif
-}
-
  /* Test if priv level is M, S, or U (cannot fail). */
  #define REQUIRE_PRIV_MSU(ctx)

  /* Test if priv level is M or S. */
  #define REQUIRE_PRIV_MS(ctx)                                    \
  do {                                                            \
-    int priv = priv_level(ctx);                                 \
+    int priv = ctx->priv;                                       \
      if (!(priv == PRV_M ||                                      \
            priv == PRV_S)) {                                     \
          return false;                                           \
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 5620fbffb6..b55152a7dc 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -21,6 +21,20 @@

  #include "hw/registerfields.h"

+/*
+ * The current MMU Modes are:
+ *  - U                 0b000
+ *  - S                 0b001
+ *  - S+SUM             0b010
+ *  - M                 0b011
+ *  - HLV/HLVX/HSV adds 0b100
+ */
+#define MMUIdx_U            0
+#define MMUIdx_S            1
+#define MMUIdx_S_SUM        2
+#define MMUIdx_M            3
+#define MMU_HYP_ACCESS_BIT  (1 << 2)
+
  /* share data between vector helpers and decode code */
  FIELD(VDATA, VM, 0, 1)
  FIELD(VDATA, LMUL, 1, 3)
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 84ee018f7d..8a0ddb91b5 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -23,6 +23,7 @@
  #include "qemu/main-loop.h"
  #include "exec/exec-all.h"
  #include "exec/helper-proto.h"
+#include "internals.h"

  /* Exceptions processing helpers */
  G_NORETURN void riscv_raise_exception(CPURISCVState *env,
@@ -428,14 +429,14 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)

  target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
  {
-    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;

      return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
  }

  target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
  {
-    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
+    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;

      return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
  }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index e8bac1b470..f32cd7143a 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -69,6 +69,7 @@ typedef struct DisasContext {
      uint32_t mstatus_hs_fs;
      uint32_t mstatus_hs_vs;
      uint32_t mem_idx;
+    uint32_t priv;
      /* Remember the rounding mode encoded in the previous fp instruction,
         which we have already installed into env->fp_status. Or -1 for
         no previous fp instruction.  Note that we exit the TB when writing
@@ -1152,7 +1153,12 @@ static void 
riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
      uint32_t tb_flags = ctx->base.tb->flags;

      ctx->pc_succ_insn = ctx->base.pc_first;
-    ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
+    ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
+    if (FIELD_EX32(tb_flags, TB_FLAGS, SUM)) {
+        ctx->mem_idx = MMUIdx_S_SUM;
+    } else {
+        ctx->mem_idx = ctx->priv;
+    }
      ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
      ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
      ctx->priv_ver = env->priv_ver;

Best Regards,
Zhiwei

>>
>>
>> r~


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

* Re: [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
  2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
  2023-03-27  1:34   ` liweiwei
@ 2023-03-28  2:34   ` LIU Zhiwei
  2023-04-11  2:02   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} " Alistair Francis
  2 siblings, 0 replies; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-28  2:34 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, fei2.wu


On 2023/3/25 18:54, Richard Henderson wrote:
> Merge with mstatus_{fs,vs}.  We might perform a redundant
> assignment to one or the other field, but it's a trivial
> and saves 4 bits from TB_FLAGS.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Zhiwei

> ---
>   target/riscv/cpu.h        | 16 +++++++---------
>   target/riscv/cpu_helper.c | 34 ++++++++++++++++------------------
>   target/riscv/translate.c  | 32 ++++++++++----------------------
>   3 files changed, 33 insertions(+), 49 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index f787145a21..d9e0eaaf9b 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -646,19 +646,17 @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
>   FIELD(TB_FLAGS, VILL, 14, 1)
>   /* Is a Hypervisor instruction load/store allowed? */
>   FIELD(TB_FLAGS, HLSX, 15, 1)
> -FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
> -FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2)
>   /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
> -FIELD(TB_FLAGS, XL, 20, 2)
> +FIELD(TB_FLAGS, XL, 16, 2)
>   /* If PointerMasking should be applied */
> -FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
> -FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
> -FIELD(TB_FLAGS, VTA, 24, 1)
> -FIELD(TB_FLAGS, VMA, 25, 1)
> +FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1)
> +FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1)
> +FIELD(TB_FLAGS, VTA, 20, 1)
> +FIELD(TB_FLAGS, VMA, 21, 1)
>   /* Native debug itrigger */
> -FIELD(TB_FLAGS, ITRIGGER, 26, 1)
> +FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>   /* Virtual mode enabled */
> -FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
> +FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>   
>   #ifdef TARGET_RISCV32
>   #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 1e7ee9aa30..4fdd6fe021 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -45,7 +45,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>   {
>       CPUState *cs = env_cpu(env);
>       RISCVCPU *cpu = RISCV_CPU(cs);
> -
> +    RISCVExtStatus fs, vs;
>       uint32_t flags = 0;
>   
>       *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
> @@ -79,18 +79,12 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>       }
>   
>   #ifdef CONFIG_USER_ONLY
> -    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
> -    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
> +    fs = EXT_STATUS_DIRTY;
> +    vs = EXT_STATUS_DIRTY;
>   #else
>       flags |= cpu_mmu_index(env, 0);
> -    if (riscv_cpu_fp_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
> -                            get_field(env->mstatus,  MSTATUS_FS));
> -    }
> -    if (riscv_cpu_vector_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
> -                            get_field(env->mstatus, MSTATUS_VS));
> -    }
> +    fs = get_field(env->mstatus, MSTATUS_FS);
> +    vs = get_field(env->mstatus, MSTATUS_VS);
>   
>       if (riscv_has_ext(env, RVH)) {
>           if (env->priv == PRV_M ||
> @@ -100,19 +94,23 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>               flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
>           }
>   
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
> -                           get_field(env->mstatus_hs, MSTATUS_FS));
> -
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
> -                           get_field(env->mstatus_hs, MSTATUS_VS));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
> -                           get_field(env->virt, VIRT_ONOFF));
> +        if (riscv_cpu_virt_enabled(env)) {
> +            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +            /*
> +             * Merge DISABLED and !DIRTY states using MIN.
> +             * We will set both fields when dirtying.
> +             */
> +            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> +            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> +        }
>       }
>       if (cpu->cfg.debug && !icount_enabled()) {
>           flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>       }
>   #endif
>   
> +    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
>       flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
>       if (env->cur_pmmask < (env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX)) {
>           flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index b897bf6006..74d0b9889d 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -66,8 +66,6 @@ typedef struct DisasContext {
>       uint32_t opcode;
>       RISCVExtStatus mstatus_fs;
>       RISCVExtStatus mstatus_vs;
> -    RISCVExtStatus mstatus_hs_fs;
> -    RISCVExtStatus mstatus_hs_vs;
>       uint32_t mem_idx;
>       /* Remember the rounding mode encoded in the previous fp instruction,
>          which we have already installed into env->fp_status.  Or -1 for
> @@ -618,16 +616,12 @@ static void mark_fs_dirty(DisasContext *ctx)
>           tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>           tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
>           tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>   
> -    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }
>       }
>   }
>   #else
> @@ -651,16 +645,12 @@ static void mark_vs_dirty(DisasContext *ctx)
>           tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>           tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
>           tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>   
> -    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }
>       }
>   }
>   #else
> @@ -1158,8 +1148,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       ctx->misa_ext = env->misa_ext;
>       ctx->frm = -1;  /* unknown rounding mode */
>       ctx->cfg_ptr = &(cpu->cfg);
> -    ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
> -    ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
>       ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
>       ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
>       ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);


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

* Re: [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx
  2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
@ 2023-03-28  2:39   ` LIU Zhiwei
  2023-04-11  2:08   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-28  2:39 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, fei2.wu


On 2023/3/25 18:54, Richard Henderson wrote:
> From: Fei Wu <fei2.wu@intel.com>
>
> Currently it's assumed the 2 low bits of mmu_idx map to privilege mode,
> this assumption won't last as we are about to add more mmu_idx. Here an
> individual priv field is added into TB_FLAGS.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Message-Id: <20230324054154.414846-2-fei2.wu@intel.com>
> ---
>   target/riscv/cpu.h                             | 2 +-
>   target/riscv/cpu_helper.c                      | 4 +++-
>   target/riscv/translate.c                       | 2 ++
>   target/riscv/insn_trans/trans_privileged.c.inc | 2 +-
>   target/riscv/insn_trans/trans_xthead.c.inc     | 7 +------
>   5 files changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 86a82e25dc..3e59dbb3fd 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -631,7 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
>   target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
>   void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>   
> -#define TB_FLAGS_PRIV_MMU_MASK                3
>   #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
>   
>   #include "exec/cpu-all.h"
> @@ -658,6 +657,7 @@ FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>   /* Virtual mode enabled */
>   FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>   FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
> +FIELD(TB_FLAGS, PRIV, 25, 2)
Though I am not prefer this.  It is acceptable as the other patches will 
explicitly encode the mem_index in tb flags.
After that, this is necessary.
>   
>   #ifdef TARGET_RISCV32
>   #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 4f0999d50b..5753126c7a 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -83,6 +83,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>       fs = EXT_STATUS_DIRTY;
>       vs = EXT_STATUS_DIRTY;
>   #else
> +    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
> +
>       flags |= cpu_mmu_index(env, 0);
>       fs = get_field(env->mstatus, MSTATUS_FS);
>       vs = get_field(env->mstatus, MSTATUS_VS);
> @@ -764,7 +766,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>        * (riscv_cpu_do_interrupt) is correct */
>       MemTxResult res;
>       MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
> -    int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
> +    int mode = env->priv;
>       bool use_background = false;
>       hwaddr ppn;
>       RISCVCPU *cpu = env_archcpu(env);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index f8c077525c..abfc152553 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -67,6 +67,7 @@ typedef struct DisasContext {
>       RISCVExtStatus mstatus_fs;
>       RISCVExtStatus mstatus_vs;
>       uint32_t mem_idx;
> +    uint32_t priv;
>       /* Remember the rounding mode encoded in the previous fp instruction,
>          which we have already installed into env->fp_status.  Or -1 for
>          no previous fp instruction.  Note that we exit the TB when writing
> @@ -1140,6 +1141,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       uint32_t tb_flags = ctx->base.tb->flags;
>   
>       ctx->pc_succ_insn = ctx->base.pc_first;
> +    ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
>       ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
>       ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
>       ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
> diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
> index 59501b2780..9305b18299 100644
> --- a/target/riscv/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> @@ -52,7 +52,7 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
>        * that no exception will be raised when fetching them.
>        */
>   
> -    if (semihosting_enabled(ctx->mem_idx < PRV_S) &&
> +    if (semihosting_enabled(ctx->priv < PRV_S) &&
>           (pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
>           pre    = opcode_at(&ctx->base, pre_addr);
>           ebreak = opcode_at(&ctx->base, ebreak_addr);
> diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
> index df504c3f2c..adfb53cb4c 100644
> --- a/target/riscv/insn_trans/trans_xthead.c.inc
> +++ b/target/riscv/insn_trans/trans_xthead.c.inc
> @@ -265,12 +265,7 @@ static bool trans_th_tst(DisasContext *ctx, arg_th_tst *a)
>   
>   static inline int priv_level(DisasContext *ctx)
>   {
> -#ifdef CONFIG_USER_ONLY
> -    return PRV_U;
> -#else
> -     /* Priv level is part of mem_idx. */
> -    return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
> -#endif
> +    return ctx->priv;
>   }

Could you  remove the priv_level and use ctx->priv directly in this file

Otherwise,

Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Zhiwei

>   
>   /* Test if priv level is M, S, or U (cannot fail). */


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

* Re: [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change
  2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
@ 2023-03-28  2:41   ` LIU Zhiwei
  2023-04-11  2:11   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: LIU Zhiwei @ 2023-03-28  2:41 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, fei2.wu


On 2023/3/25 18:54, Richard Henderson wrote:
> From: Fei Wu <fei2.wu@intel.com>
>
> Kernel needs to access user mode memory e.g. during syscalls, the window
> is usually opened up for a very limited time through MSTATUS.SUM, the
> overhead is too much if tlb_flush() gets called for every SUM change.
>
> This patch creates a separate MMU index for S+SUM, so that it's not
> necessary to flush tlb anymore when SUM changes. This is similar to how
> ARM handles Privileged Access Never (PAN).
>
> Result of 'pipe 10' from unixbench boosts from 223656 to 1705006. Many
> other syscalls benefit a lot from this too.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Message-Id: <20230324054154.414846-3-fei2.wu@intel.com>
> ---
>   target/riscv/cpu.h                      |  2 --
>   target/riscv/internals.h                | 14 ++++++++++++++
>   target/riscv/cpu_helper.c               | 17 +++++++++++++++--
>   target/riscv/csr.c                      |  3 +--
>   target/riscv/op_helper.c                |  5 +++--
>   target/riscv/insn_trans/trans_rvh.c.inc |  4 ++--
>   6 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 3e59dbb3fd..5e589db106 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -631,8 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
>   target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
>   void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>   
> -#define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
> -
>   #include "exec/cpu-all.h"
>   
>   FIELD(TB_FLAGS, MEM_IDX, 0, 3)
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 5620fbffb6..b55152a7dc 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -21,6 +21,20 @@
>   
>   #include "hw/registerfields.h"
>   
> +/*
> + * The current MMU Modes are:
> + *  - U                 0b000
> + *  - S                 0b001
> + *  - S+SUM             0b010
> + *  - M                 0b011
> + *  - HLV/HLVX/HSV adds 0b100

Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>

Zhiwei

> + */
> +#define MMUIdx_U            0
> +#define MMUIdx_S            1
> +#define MMUIdx_S_SUM        2
> +#define MMUIdx_M            3
> +#define MMU_HYP_ACCESS_BIT  (1 << 2)
> +
>   /* share data between vector helpers and decode code */
>   FIELD(VDATA, VM, 0, 1)
>   FIELD(VDATA, LMUL, 1, 3)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 5753126c7a..052fdd2d9d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -21,6 +21,7 @@
>   #include "qemu/log.h"
>   #include "qemu/main-loop.h"
>   #include "cpu.h"
> +#include "internals.h"
>   #include "pmu.h"
>   #include "exec/exec-all.h"
>   #include "instmap.h"
> @@ -36,7 +37,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>   #ifdef CONFIG_USER_ONLY
>       return 0;
>   #else
> -    return env->priv;
> +    if (ifetch) {
> +        return env->priv;
> +    }
> +
> +    /* All priv -> mmu_idx mapping are here */
> +    int mode = env->priv;
> +    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> +        mode = get_field(env->mstatus, MSTATUS_MPP);
> +    }
> +    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
> +        return MMUIdx_S_SUM;
> +    }
> +    return mode;
>   #endif
>   }
>   
> @@ -600,7 +613,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
>   
>   bool riscv_cpu_two_stage_lookup(int mmu_idx)
>   {
> -    return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    return mmu_idx & MMU_HYP_ACCESS_BIT;
>   }
>   
>   int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index abea7b749e..b79758a606 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1246,8 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
>       RISCVMXL xl = riscv_cpu_mxl(env);
>   
>       /* flush tlb on mstatus fields that affect VM */
> -    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
> -            MSTATUS_MPRV | MSTATUS_SUM)) {
> +    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) {
>           tlb_flush(env_cpu(env));
>       }
>       mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 84ee018f7d..962a061228 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -20,6 +20,7 @@
>   
>   #include "qemu/osdep.h"
>   #include "cpu.h"
> +#include "internals.h"
>   #include "qemu/main-loop.h"
>   #include "exec/exec-all.h"
>   #include "exec/helper-proto.h"
> @@ -428,14 +429,14 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
>   
>   target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
>   {
> -    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
>   
>       return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
>   }
>   
>   target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
>   {
> -    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
>   
>       return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
>   }
> diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
> index 9248b48c36..15842f4282 100644
> --- a/target/riscv/insn_trans/trans_rvh.c.inc
> +++ b/target/riscv/insn_trans/trans_rvh.c.inc
> @@ -40,7 +40,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
>       if (check_access(ctx)) {
>           TCGv dest = dest_gpr(ctx, a->rd);
>           TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
>           tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
>           gen_set_gpr(ctx, a->rd, dest);
>       }
> @@ -87,7 +87,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
>       if (check_access(ctx)) {
>           TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
>           TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
>           tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
>       }
>       return true;


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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-28  1:54         ` LIU Zhiwei
@ 2023-03-28 14:27           ` Richard Henderson
  0 siblings, 0 replies; 70+ messages in thread
From: Richard Henderson @ 2023-03-28 14:27 UTC (permalink / raw)
  To: LIU Zhiwei, qemu-devel

On 3/27/23 18:54, LIU Zhiwei wrote:
>>>> Can we remove the PRIV from the tb flags after we have this function?
>>>
>>> No, because this is the priv of the memory operation as modified by e.g. MPRV, not the 
>>> true cpu priv.
>>
>> For this implementation, we explicitly use the tb flags for mmu index. I think it is the 
>> reason why we have to maintain the redundant privilege in tb flags.
>> It may be better to only store machine states into tb flags. Can we just pass everything 
>> that we need, for example, the priv and sum, and then implicitly
>> calculate the ctx->mem_idx in disas_init_fn?
>>
>> I remember that you give the similar suggestion in the comment process
>>
>> https://mail.gnu.org/archive/html/qemu-riscv/2023-03/msg00566.html
>>
>> Best Regards,
>> Zhiwei
>>
> To make this comment clear, I paste a simple implementatioin here. But it is just for 
> discussing, not a normal patch for merging.
> 
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 623288e6f9..d4506be5be 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -632,12 +632,10 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
>   target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
>   void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
> 
> -#define TB_FLAGS_PRIV_MMU_MASK                3
> -#define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
> -
>   #include "exec/cpu-all.h"
> 
> -FIELD(TB_FLAGS, MEM_IDX, 0, 3)
> +FIELD(TB_FLAGS, PRIV, 0, 2)
> +FIELD(TB_FLAGS, SUM, 2, 1)

We would need to include MPRV, MPP, MPV, VIRT_ENABLED as well.  With SUM, that would be 6 
bits in tb_flags instead of 3 bits for MEM_IDX.


r~


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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (27 preceding siblings ...)
  2023-03-27 16:43 ` Daniel Henrique Barboza
@ 2023-04-04  6:42 ` Wu, Fei
  2023-04-04  7:11   ` LIU Zhiwei
  2023-04-11  5:38 ` Alistair Francis
  29 siblings, 1 reply; 70+ messages in thread
From: Wu, Fei @ 2023-04-04  6:42 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer, zhiwei_liu

On 3/25/2023 6:54 PM, Richard Henderson wrote:
> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
> 
>   * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
> 
>   * Using cpu_mmu_index(env, true) is insufficient to implement
>     HLVX properly.  While that chooses the correct mmu_idx, it
>     does not perform the read with execute permission.
>     I add a new tcg interface to perform a read-for-execute with
>     an arbitrary mmu_idx.  This is still not 100% compliant, but
>     it's closer.
> 
>   * Handle mstatus.MPV in cpu_mmu_index.
>   * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>   * Cleanups for get_physical_address.
> 
> While this passes check-avocado, I'm sure that's insufficient.
> Please have a close look.
> 
I tested stress-ng to get the feeling of performance gain, although
stress-ng is not designed to be a performance workload. btw, I had to
revert commit 0ee342256af9 which is unrelated to this series, or qemu
exited during the test.
    ./stress-ng --timeout 5 --metrics-brief --class os --sequential 1

Here is the result, in general most of the tests benefit from these
series, but please note that not all the results are necessary to be
consistent across multiple runs, and some regressions are not real but I
haven't checked it one by one.

             master(60ca584b)   master + this      speedup

stressor           bogo ops/s      bogo ops/s
               (usr+sys time)  (usr+sys time)
sigsuspend            19430.09      1492746.34     76.8265
utime                  8779.64       271023.89     30.8696
chmod                  1728.26        27050.50     15.6519
vdso               23527136.74    246955742.76     10.4966
signal               584521.13      5470775.44     9.35941
sigtrap              822935.76      7190973.63     8.7382
signest              802706.93      6969509.05     8.68251
sockpair             501188.08      4242275.08     8.46444
msg                 1627863.38     13557215.89     8.32823
sigpending           551174.68      4575836.91     8.30197
locka               1447750.95     11727762.91     8.10068
lockofd             1460020.77     11562178.66     7.91919
sigsegv              718492.57      5673228.57     7.89602
getrandom            129004.90      1006544.31     7.80237
sigq                 892062.12      6828556.43     7.6548
chdir                    13.39          100.66     7.51755
timerfd             2074142.37     15395307.29     7.42249
mq                   916620.00      6208148.59     6.77287
mutex               1124306.59      7285459.79     6.47996
urandom              104868.58       678510.46     6.4701
pipe                2243935.71     14391093.39     6.41333
loadavg              463874.30      2936816.17     6.33106
fifo                 423415.43      2632734.32     6.21785
vm                    16726.91        99928.62     5.97412
handle               199246.08      1131172.45     5.67726
fstat                  2383.12        13479.35     5.65618
sigrt                405007.13      2143758.11     5.29314
access                 8449.17        44145.10     5.22479
sigfd               1506073.95      7408089.06     4.91881
sysinfo               11711.47        54868.08     4.68499
sigio               1672452.59      7564833.33     4.5232
rlimit                26771.83       119476.12     4.46276
xattr                   772.25         3412.81     4.41931
udp                  595733.08      2495239.72     4.18852
sockfd               260825.22      1061910.05     4.07135
get                   13169.56        52788.06     4.00834
getdent              141465.81       564471.43     3.99016
rename                61771.74       246277.28     3.98689
chown                 54946.74       212353.58     3.86472
dev                    3555.80        13596.14     3.82365
mincore                6617.92        25215.66     3.81021
file-ioctl           105919.35       398122.29     3.75873
link                     15.45           56.02     3.62589
splice               239841.25       865390.06     3.60818
io-uring              45798.90       157006.17     3.42816
filename               7795.98        26238.75     3.36568
sock                   1746.96         5850.73     3.34909
vm-splice            953550.50      3188724.62     3.34405
schedpolicy          231915.33       773655.76     3.33594
clock                 21878.02        72400.21     3.30927
fcntl                 76122.11       245817.92     3.22926
dentry                79533.95       247610.80     3.11327
fpunch                11895.30        36608.97     3.0776
revio                866066.56      2596187.53     2.99768
null                2351038.37      6984334.92     2.97074
mknod                 71145.05       203284.26     2.85732
symlink                  12.40           35.41     2.85565
fiemap                45437.02       128983.69     2.83874
sleep                100093.89       282540.81     2.82276
dir                   99154.72       272727.21     2.75052
timer                126419.44       344857.10     2.72788
set                   70640.29       192423.96     2.724
udp-flood            662581.75      1782759.62     2.69063
ioprio                 7030.55        18807.67     2.67513
epoll                147525.39       387861.58     2.62912
vm-rw                  1437.12         3774.13     2.62618
kill                 234075.90       613281.66     2.62001
hdd                   99017.45       257841.08     2.604
rtc                   57639.55       149363.61     2.59134
dirmany              127249.90       323667.85     2.54356
sem-sysv            1096787.78      2753588.88     2.51059
close                194579.21       482854.54     2.48153
dnotify               15125.16        37097.94     2.45273
dccp                   7554.97        18429.65     2.43941
lease                285588.09       692990.31     2.42654
eventfd              282256.72       681576.60     2.41474
sockdiag           14803911.93     34934756.45     2.35983
memfd                  3632.45         8513.45     2.34372
tee                  124239.86       290298.68     2.3366
alarm                 78757.48       181210.40     2.30087
poll                 128638.34       292293.31     2.27221
open                 189323.41       418865.86     2.21244
sigpipe              222534.69       486854.87     2.18777
pty                      18.95           39.13     2.06491
futex               1333749.78      2742935.07     2.05656
lockf                648732.25      1321326.88     2.03678
kcmp                 734152.03      1452613.12     1.97863
procfs                 7378.58        14503.74     1.96565
sockmany              94910.81       180132.46     1.89791
dirdeep               10330.82        19390.08     1.87692
touch                 97843.94       182585.97     1.86609
chattr                 2952.98         5426.15     1.83752
mmaphuge                430.84          738.17     1.71333
sem                  649644.88      1107290.70     1.70446
ptrace              1010862.41      1677555.44     1.65953
vfork                244944.97       403514.39     1.64737
nanosleep             23147.04        38097.83     1.64591
mprotect            1068863.24      1729245.09     1.61784
pipeherd             720787.08      1157261.92     1.60555
pthread               48395.68        76169.49     1.57389
enosys                 8271.11        12705.37     1.53611
sockabuse              2825.44         4251.52     1.50473
af-alg               620270.87       916118.93     1.47697
fork                  10583.97        15363.15     1.45155
copy-file              6675.07         9389.54     1.40666
resched             1730236.55      2421449.49     1.39949
msync                 93196.18       122263.64     1.3119
vforkmany            239372.56       304313.41     1.2713
vm-segv               11918.23        14981.24     1.257
readahead            261489.55       321372.13     1.22901
sendfile             147043.77       174971.03     1.18992
dynlib                 8526.99        10078.23     1.18192
fault                 86430.63       100320.47     1.16071
dup                    9829.71        11264.11     1.14592
full                 473749.38       541801.33     1.14365
mmapaddr             315772.34       351766.42     1.11399
spawn                  3937.57         4384.92     1.11361
io                   371206.67       409205.80     1.10237
munmap                64162.14        70473.66     1.09837
exit-group             5990.95         6522.70     1.08876
pidfd                 37614.16        40687.85     1.08172
flock              14069057.61     15117799.43     1.07454
wait                 106334.40       113658.40     1.06888
mmapfork                  1.81            1.93     1.0663
daemon              1161091.36      1234795.43     1.06348
bigheap              185514.46       195279.13     1.05264
mmapfixed               319.65          333.70     1.04395
brk                 1410050.59      1456025.25     1.0326
sigabrt               12129.51        12520.45     1.03223
sysfs                   806.78          831.54     1.03069
dev-shm                  40.30           41.37     1.02655
bad-altstack           7310.53         7493.23     1.02499
shm                     823.73          842.50     1.02279
shm-sysv               1132.54         1151.86     1.01706
mmapmany             400323.77       406078.50     1.01438
session               12096.44        12228.64     1.01093
madvise                 116.81          117.96     1.00985
clone                 28152.35        28414.20     1.0093
msyncmany              2220.25         2238.88     1.00839
pageswap             205651.13       207367.84     1.00835
unshare                 637.92          642.98     1.00793
remap                   373.18          375.69     1.00673
personality         1698012.68      1706642.92     1.00508
reboot               117234.02       117421.91     1.0016
itimer                24962.64        24971.19     1.00034
sync-file                 0.00            0.00     1
sigfpe                    0.00            0.00     1
seek                      0.00            0.00     1
inode-flags               0.00            0.00     1
env                       0.00            0.00     1
prctl                 11805.81        11772.73     0.997198
malloc               991487.43       987061.41     0.995536
mmap                     14.48           14.39     0.993785
zombie                33753.24        33539.75     0.993675
rmap                    625.84          620.94     0.992171
tlb-shootdown           358.25          355.33     0.991849
switch              1251701.93      1240818.57     0.991305
zero                 127112.38       125254.50     0.985384
resources               685.62          674.89     0.98435
yield               4184626.17      4117860.34     0.984045
mlock                494527.50       485733.90     0.982218
fallocate             32711.39        32067.69     0.980322
sigchld               46289.82        44914.65     0.970292
inotify                3013.11         2879.87     0.95578
opcode                11315.78        10538.58     0.931317
nice                 154327.30       136797.63     0.886412
mremap                  225.29          198.82     0.882507
exec                   4118.89         3282.85     0.797023
vm-addr                 214.25          166.69     0.778016
landlock                950.00          722.74     0.760779

Thanks,
Fei.
> 
> r~
> 
> 
> Fei Wu (2):
>   target/riscv: Separate priv from mmu_idx
>   target/riscv: Reduce overhead of MSTATUS_SUM change
> 
> LIU Zhiwei (4):
>   target/riscv: Extract virt enabled state from tb flags
>   target/riscv: Add a general status enum for extensions
>   target/riscv: Encode the FS and VS on a normal way for tb flags
>   target/riscv: Add a tb flags field for vstart
> 
> Richard Henderson (19):
>   target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>   accel/tcg: Add cpu_ld*_code_mmu
>   target/riscv: Use cpu_ld*_code_mmu for HLVX
>   target/riscv: Handle HLV, HSV via helpers
>   target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>   target/riscv: Introduce mmuidx_sum
>   target/riscv: Introduce mmuidx_priv
>   target/riscv: Introduce mmuidx_2stage
>   target/riscv: Move hstatus.spvp check to check_access_hlsv
>   target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>   target/riscv: Check SUM in the correct register
>   target/riscv: Hoist second stage mode change to callers
>   target/riscv: Hoist pbmte and hade out of the level loop
>   target/riscv: Move leaf pte processing out of level loop
>   target/riscv: Suppress pte update with is_debug
>   target/riscv: Don't modify SUM with is_debug
>   target/riscv: Merge checks for reserved pte flags
>   target/riscv: Reorg access check in get_physical_address
>   target/riscv: Reorg sum check in get_physical_address
> 
>  include/exec/cpu_ldst.h                       |   9 +
>  target/riscv/cpu.h                            |  47 ++-
>  target/riscv/cpu_bits.h                       |  12 +-
>  target/riscv/helper.h                         |  12 +-
>  target/riscv/internals.h                      |  35 ++
>  accel/tcg/cputlb.c                            |  48 +++
>  accel/tcg/user-exec.c                         |  58 +++
>  target/riscv/cpu.c                            |   2 +-
>  target/riscv/cpu_helper.c                     | 393 +++++++++---------
>  target/riscv/csr.c                            |  21 +-
>  target/riscv/op_helper.c                      | 113 ++++-
>  target/riscv/translate.c                      |  72 ++--
>  .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>  target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>  target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>  target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>  target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>  17 files changed, 595 insertions(+), 395 deletions(-)
> 



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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-04-04  6:42 ` Wu, Fei
@ 2023-04-04  7:11   ` LIU Zhiwei
  2023-04-04  7:23     ` Wu, Fei
  0 siblings, 1 reply; 70+ messages in thread
From: LIU Zhiwei @ 2023-04-04  7:11 UTC (permalink / raw)
  To: Wu, Fei, Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer


On 2023/4/4 14:42, Wu, Fei wrote:
> On 3/25/2023 6:54 PM, Richard Henderson wrote:
>> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
>>
>>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
>>
>>    * Using cpu_mmu_index(env, true) is insufficient to implement
>>      HLVX properly.  While that chooses the correct mmu_idx, it
>>      does not perform the read with execute permission.
>>      I add a new tcg interface to perform a read-for-execute with
>>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>>      it's closer.
>>
>>    * Handle mstatus.MPV in cpu_mmu_index.
>>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>>    * Cleanups for get_physical_address.
>>
>> While this passes check-avocado, I'm sure that's insufficient.
>> Please have a close look.
>>
> I tested stress-ng to get the feeling of performance gain, although
> stress-ng is not designed to be a performance workload. btw, I had to
> revert commit 0ee342256af9 which is unrelated to this series, or qemu
> exited during the test.
>      ./stress-ng --timeout 5 --metrics-brief --class os --sequential 1
>
> Here is the result, in general most of the tests benefit from these
> series, but please note that not all the results are necessary to be
> consistent across multiple runs, and some regressions are not real but I
> haven't checked it one by one.
>
>               master(60ca584b)   master + this      speedup
>
> stressor           bogo ops/s      bogo ops/s
>                 (usr+sys time)  (usr+sys time)
> sigsuspend            19430.09      1492746.34     76.8265
> utime                  8779.64       271023.89     30.8696
> chmod                  1728.26        27050.50     15.6519
> vdso               23527136.74    246955742.76     10.4966
> signal               584521.13      5470775.44     9.35941
> sigtrap              822935.76      7190973.63     8.7382
> signest              802706.93      6969509.05     8.68251
> sockpair             501188.08      4242275.08     8.46444
> msg                 1627863.38     13557215.89     8.32823
> sigpending           551174.68      4575836.91     8.30197
> locka               1447750.95     11727762.91     8.10068
> lockofd             1460020.77     11562178.66     7.91919
> sigsegv              718492.57      5673228.57     7.89602
> getrandom            129004.90      1006544.31     7.80237
> sigq                 892062.12      6828556.43     7.6548
> chdir                    13.39          100.66     7.51755
> timerfd             2074142.37     15395307.29     7.42249
> mq                   916620.00      6208148.59     6.77287
> mutex               1124306.59      7285459.79     6.47996
> urandom              104868.58       678510.46     6.4701
> pipe                2243935.71     14391093.39     6.41333
> loadavg              463874.30      2936816.17     6.33106
> fifo                 423415.43      2632734.32     6.21785
> vm                    16726.91        99928.62     5.97412
> handle               199246.08      1131172.45     5.67726
> fstat                  2383.12        13479.35     5.65618
> sigrt                405007.13      2143758.11     5.29314
> access                 8449.17        44145.10     5.22479
> sigfd               1506073.95      7408089.06     4.91881
> sysinfo               11711.47        54868.08     4.68499
> sigio               1672452.59      7564833.33     4.5232
> rlimit                26771.83       119476.12     4.46276
> xattr                   772.25         3412.81     4.41931
> udp                  595733.08      2495239.72     4.18852
> sockfd               260825.22      1061910.05     4.07135
> get                   13169.56        52788.06     4.00834
> getdent              141465.81       564471.43     3.99016
> rename                61771.74       246277.28     3.98689
> chown                 54946.74       212353.58     3.86472
> dev                    3555.80        13596.14     3.82365
> mincore                6617.92        25215.66     3.81021
> file-ioctl           105919.35       398122.29     3.75873
> link                     15.45           56.02     3.62589
> splice               239841.25       865390.06     3.60818
> io-uring              45798.90       157006.17     3.42816
> filename               7795.98        26238.75     3.36568
> sock                   1746.96         5850.73     3.34909
> vm-splice            953550.50      3188724.62     3.34405
> schedpolicy          231915.33       773655.76     3.33594
> clock                 21878.02        72400.21     3.30927
> fcntl                 76122.11       245817.92     3.22926
> dentry                79533.95       247610.80     3.11327
> fpunch                11895.30        36608.97     3.0776
> revio                866066.56      2596187.53     2.99768
> null                2351038.37      6984334.92     2.97074
> mknod                 71145.05       203284.26     2.85732
> symlink                  12.40           35.41     2.85565
> fiemap                45437.02       128983.69     2.83874
> sleep                100093.89       282540.81     2.82276
> dir                   99154.72       272727.21     2.75052
> timer                126419.44       344857.10     2.72788
> set                   70640.29       192423.96     2.724
> udp-flood            662581.75      1782759.62     2.69063
> ioprio                 7030.55        18807.67     2.67513
> epoll                147525.39       387861.58     2.62912
> vm-rw                  1437.12         3774.13     2.62618
> kill                 234075.90       613281.66     2.62001
> hdd                   99017.45       257841.08     2.604
> rtc                   57639.55       149363.61     2.59134
> dirmany              127249.90       323667.85     2.54356
> sem-sysv            1096787.78      2753588.88     2.51059
> close                194579.21       482854.54     2.48153
> dnotify               15125.16        37097.94     2.45273
> dccp                   7554.97        18429.65     2.43941
> lease                285588.09       692990.31     2.42654
> eventfd              282256.72       681576.60     2.41474
> sockdiag           14803911.93     34934756.45     2.35983
> memfd                  3632.45         8513.45     2.34372
> tee                  124239.86       290298.68     2.3366
> alarm                 78757.48       181210.40     2.30087
> poll                 128638.34       292293.31     2.27221
> open                 189323.41       418865.86     2.21244
> sigpipe              222534.69       486854.87     2.18777
> pty                      18.95           39.13     2.06491
> futex               1333749.78      2742935.07     2.05656
> lockf                648732.25      1321326.88     2.03678
> kcmp                 734152.03      1452613.12     1.97863
> procfs                 7378.58        14503.74     1.96565
> sockmany              94910.81       180132.46     1.89791
> dirdeep               10330.82        19390.08     1.87692
> touch                 97843.94       182585.97     1.86609
> chattr                 2952.98         5426.15     1.83752
> mmaphuge                430.84          738.17     1.71333
> sem                  649644.88      1107290.70     1.70446
> ptrace              1010862.41      1677555.44     1.65953
> vfork                244944.97       403514.39     1.64737
> nanosleep             23147.04        38097.83     1.64591
> mprotect            1068863.24      1729245.09     1.61784
> pipeherd             720787.08      1157261.92     1.60555
> pthread               48395.68        76169.49     1.57389
> enosys                 8271.11        12705.37     1.53611
> sockabuse              2825.44         4251.52     1.50473
> af-alg               620270.87       916118.93     1.47697
> fork                  10583.97        15363.15     1.45155
> copy-file              6675.07         9389.54     1.40666
> resched             1730236.55      2421449.49     1.39949
> msync                 93196.18       122263.64     1.3119
> vforkmany            239372.56       304313.41     1.2713
> vm-segv               11918.23        14981.24     1.257
> readahead            261489.55       321372.13     1.22901
> sendfile             147043.77       174971.03     1.18992
> dynlib                 8526.99        10078.23     1.18192
> fault                 86430.63       100320.47     1.16071
> dup                    9829.71        11264.11     1.14592
> full                 473749.38       541801.33     1.14365
> mmapaddr             315772.34       351766.42     1.11399
> spawn                  3937.57         4384.92     1.11361
> io                   371206.67       409205.80     1.10237
> munmap                64162.14        70473.66     1.09837
> exit-group             5990.95         6522.70     1.08876
> pidfd                 37614.16        40687.85     1.08172
> flock              14069057.61     15117799.43     1.07454
> wait                 106334.40       113658.40     1.06888
> mmapfork                  1.81            1.93     1.0663
> daemon              1161091.36      1234795.43     1.06348
> bigheap              185514.46       195279.13     1.05264
> mmapfixed               319.65          333.70     1.04395
> brk                 1410050.59      1456025.25     1.0326
> sigabrt               12129.51        12520.45     1.03223
> sysfs                   806.78          831.54     1.03069
> dev-shm                  40.30           41.37     1.02655
> bad-altstack           7310.53         7493.23     1.02499
> shm                     823.73          842.50     1.02279
> shm-sysv               1132.54         1151.86     1.01706
> mmapmany             400323.77       406078.50     1.01438
> session               12096.44        12228.64     1.01093
> madvise                 116.81          117.96     1.00985
> clone                 28152.35        28414.20     1.0093
> msyncmany              2220.25         2238.88     1.00839
> pageswap             205651.13       207367.84     1.00835
> unshare                 637.92          642.98     1.00793
> remap                   373.18          375.69     1.00673
> personality         1698012.68      1706642.92     1.00508
> reboot               117234.02       117421.91     1.0016
> itimer                24962.64        24971.19     1.00034
> sync-file                 0.00            0.00     1
> sigfpe                    0.00            0.00     1
> seek                      0.00            0.00     1
> inode-flags               0.00            0.00     1
> env                       0.00            0.00     1
> prctl                 11805.81        11772.73     0.997198
> malloc               991487.43       987061.41     0.995536
> mmap                     14.48           14.39     0.993785
> zombie                33753.24        33539.75     0.993675
> rmap                    625.84          620.94     0.992171
> tlb-shootdown           358.25          355.33     0.991849
> switch              1251701.93      1240818.57     0.991305
> zero                 127112.38       125254.50     0.985384
> resources               685.62          674.89     0.98435
> yield               4184626.17      4117860.34     0.984045
> mlock                494527.50       485733.90     0.982218
> fallocate             32711.39        32067.69     0.980322
> sigchld               46289.82        44914.65     0.970292
> inotify                3013.11         2879.87     0.95578
> opcode                11315.78        10538.58     0.931317
> nice                 154327.30       136797.63     0.886412
> mremap                  225.29          198.82     0.882507
> exec                   4118.89         3282.85     0.797023
> vm-addr                 214.25          166.69     0.778016
> landlock                950.00          722.74     0.760779

Thanks for testing. Have you analyzed the cases with worse performance? 
As we are doing a optimization.

Thanks,
Zhiwei

> Thanks,
> Fei.
>> r~
>>
>>
>> Fei Wu (2):
>>    target/riscv: Separate priv from mmu_idx
>>    target/riscv: Reduce overhead of MSTATUS_SUM change
>>
>> LIU Zhiwei (4):
>>    target/riscv: Extract virt enabled state from tb flags
>>    target/riscv: Add a general status enum for extensions
>>    target/riscv: Encode the FS and VS on a normal way for tb flags
>>    target/riscv: Add a tb flags field for vstart
>>
>> Richard Henderson (19):
>>    target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>>    accel/tcg: Add cpu_ld*_code_mmu
>>    target/riscv: Use cpu_ld*_code_mmu for HLVX
>>    target/riscv: Handle HLV, HSV via helpers
>>    target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>>    target/riscv: Introduce mmuidx_sum
>>    target/riscv: Introduce mmuidx_priv
>>    target/riscv: Introduce mmuidx_2stage
>>    target/riscv: Move hstatus.spvp check to check_access_hlsv
>>    target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>>    target/riscv: Check SUM in the correct register
>>    target/riscv: Hoist second stage mode change to callers
>>    target/riscv: Hoist pbmte and hade out of the level loop
>>    target/riscv: Move leaf pte processing out of level loop
>>    target/riscv: Suppress pte update with is_debug
>>    target/riscv: Don't modify SUM with is_debug
>>    target/riscv: Merge checks for reserved pte flags
>>    target/riscv: Reorg access check in get_physical_address
>>    target/riscv: Reorg sum check in get_physical_address
>>
>>   include/exec/cpu_ldst.h                       |   9 +
>>   target/riscv/cpu.h                            |  47 ++-
>>   target/riscv/cpu_bits.h                       |  12 +-
>>   target/riscv/helper.h                         |  12 +-
>>   target/riscv/internals.h                      |  35 ++
>>   accel/tcg/cputlb.c                            |  48 +++
>>   accel/tcg/user-exec.c                         |  58 +++
>>   target/riscv/cpu.c                            |   2 +-
>>   target/riscv/cpu_helper.c                     | 393 +++++++++---------
>>   target/riscv/csr.c                            |  21 +-
>>   target/riscv/op_helper.c                      | 113 ++++-
>>   target/riscv/translate.c                      |  72 ++--
>>   .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>>   target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>>   target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>>   target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>>   target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>>   17 files changed, 595 insertions(+), 395 deletions(-)
>>


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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-04-04  7:11   ` LIU Zhiwei
@ 2023-04-04  7:23     ` Wu, Fei
  0 siblings, 0 replies; 70+ messages in thread
From: Wu, Fei @ 2023-04-04  7:23 UTC (permalink / raw)
  To: LIU Zhiwei, Richard Henderson, qemu-devel
  Cc: qemu-riscv, alistair.francis, palmer

On 4/4/2023 3:11 PM, LIU Zhiwei wrote:
> 
> On 2023/4/4 14:42, Wu, Fei wrote:
>> On 3/25/2023 6:54 PM, Richard Henderson wrote:
>>> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
>>>
>>>    * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
>>>
>>>    * Using cpu_mmu_index(env, true) is insufficient to implement
>>>      HLVX properly.  While that chooses the correct mmu_idx, it
>>>      does not perform the read with execute permission.
>>>      I add a new tcg interface to perform a read-for-execute with
>>>      an arbitrary mmu_idx.  This is still not 100% compliant, but
>>>      it's closer.
>>>
>>>    * Handle mstatus.MPV in cpu_mmu_index.
>>>    * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>>>    * Cleanups for get_physical_address.
>>>
>>> While this passes check-avocado, I'm sure that's insufficient.
>>> Please have a close look.
>>>
>> I tested stress-ng to get the feeling of performance gain, although
>> stress-ng is not designed to be a performance workload. btw, I had to
>> revert commit 0ee342256af9 which is unrelated to this series, or qemu
>> exited during the test.
>>      ./stress-ng --timeout 5 --metrics-brief --class os --sequential 1
>>
>> Here is the result, in general most of the tests benefit from these
>> series, but please note that not all the results are necessary to be
>> consistent across multiple runs, and some regressions are not real but I
>> haven't checked it one by one.
>>
>>               master(60ca584b)   master + this      speedup
>>
>> stressor           bogo ops/s      bogo ops/s
>>                 (usr+sys time)  (usr+sys time)
>> sigsuspend            19430.09      1492746.34     76.8265
>> utime                  8779.64       271023.89     30.8696

>> opcode                11315.78        10538.58     0.931317
>> nice                 154327.30       136797.63     0.886412
>> mremap                  225.29          198.82     0.882507
>> exec                   4118.89         3282.85     0.797023
>> vm-addr                 214.25          166.69     0.778016
>> landlock                950.00          722.74     0.760779
> 
> Thanks for testing. Have you analyzed the cases with worse performance?
> As we are doing a optimization.
> 
During the 1st run, 'io' showed the worst regression, and it's proved
not a real regression or at least not consistent when I tried it again.

       master(60ca584b)   this run1  speedup1       this run2  speedup2

stressor   bogo ops/s      bogo ops/s
          (usr+sys time)  (usr+sys time)
fallocate     32711.39     33794.28    1.0331        32067.69  0.980322
sigchld       46289.82     42975.50    0.928401      44914.65  0.970292
inotify        3013.11      3511.21    1.16531        2879.87  0.95578
opcode        11315.78     10084.42    0.891182      10538.58  0.931317
nice         154327.30    186649.43    1.20944      136797.63  0.886412
mremap          225.29       237.39    1.05371         198.82  0.882507
exec           4118.89      4248.12    1.03137        3282.85  0.797023
vm-addr         214.25       268.60    1.25368         166.69  0.778016
landlock        950.00       791.12    0.832758        722.74  0.760779

io           371206.67    205232.61    0.55288      409205.80  1.10237

Thanks,
Fei.

> Thanks,
> Zhiwei
> 
>> Thanks,
>> Fei.
>>> r~
>>>
>>>
>>> Fei Wu (2):
>>>    target/riscv: Separate priv from mmu_idx
>>>    target/riscv: Reduce overhead of MSTATUS_SUM change
>>>
>>> LIU Zhiwei (4):
>>>    target/riscv: Extract virt enabled state from tb flags
>>>    target/riscv: Add a general status enum for extensions
>>>    target/riscv: Encode the FS and VS on a normal way for tb flags
>>>    target/riscv: Add a tb flags field for vstart
>>>
>>> Richard Henderson (19):
>>>    target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>>>    accel/tcg: Add cpu_ld*_code_mmu
>>>    target/riscv: Use cpu_ld*_code_mmu for HLVX
>>>    target/riscv: Handle HLV, HSV via helpers
>>>    target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>>>    target/riscv: Introduce mmuidx_sum
>>>    target/riscv: Introduce mmuidx_priv
>>>    target/riscv: Introduce mmuidx_2stage
>>>    target/riscv: Move hstatus.spvp check to check_access_hlsv
>>>    target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>>>    target/riscv: Check SUM in the correct register
>>>    target/riscv: Hoist second stage mode change to callers
>>>    target/riscv: Hoist pbmte and hade out of the level loop
>>>    target/riscv: Move leaf pte processing out of level loop
>>>    target/riscv: Suppress pte update with is_debug
>>>    target/riscv: Don't modify SUM with is_debug
>>>    target/riscv: Merge checks for reserved pte flags
>>>    target/riscv: Reorg access check in get_physical_address
>>>    target/riscv: Reorg sum check in get_physical_address
>>>
>>>   include/exec/cpu_ldst.h                       |   9 +
>>>   target/riscv/cpu.h                            |  47 ++-
>>>   target/riscv/cpu_bits.h                       |  12 +-
>>>   target/riscv/helper.h                         |  12 +-
>>>   target/riscv/internals.h                      |  35 ++
>>>   accel/tcg/cputlb.c                            |  48 +++
>>>   accel/tcg/user-exec.c                         |  58 +++
>>>   target/riscv/cpu.c                            |   2 +-
>>>   target/riscv/cpu_helper.c                     | 393 +++++++++---------
>>>   target/riscv/csr.c                            |  21 +-
>>>   target/riscv/op_helper.c                      | 113 ++++-
>>>   target/riscv/translate.c                      |  72 ++--
>>>   .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>>>   target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>>>   target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>>>   target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>>>   target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>>>   17 files changed, 595 insertions(+), 395 deletions(-)
>>>



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

* Re: [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags
  2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
@ 2023-04-06  2:35   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-06  2:35 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu,
	fei2.wu, Weiwei Li

On Sat, Mar 25, 2023 at 9:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> Virt enabled state is not a constant. So we should put it into tb flags.
> Thus we can use it like a constant condition at translation phase.
>
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
> Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Message-Id: <20230324143031.1093-2-zhiwei_liu@linux.alibaba.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h        |  2 ++
>  target/riscv/cpu_helper.c |  2 ++
>  target/riscv/translate.c  | 10 +---------
>  3 files changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 638e47c75a..12fe8d8546 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -650,6 +650,8 @@ FIELD(TB_FLAGS, VTA, 24, 1)
>  FIELD(TB_FLAGS, VMA, 25, 1)
>  /* Native debug itrigger */
>  FIELD(TB_FLAGS, ITRIGGER, 26, 1)
> +/* Virtual mode enabled */
> +FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
>
>  #ifdef TARGET_RISCV32
>  #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index f88c503cf4..9d50e7bbb6 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -104,6 +104,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>
>          flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
>                             get_field(env->mstatus_hs, MSTATUS_VS));
> +        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
> +                           get_field(env->virt, VIRT_ONOFF));
>      }
>      if (cpu->cfg.debug && !icount_enabled()) {
>          flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0ee8ee147d..880f6318aa 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -1156,15 +1156,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
>      ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
>      ctx->priv_ver = env->priv_ver;
> -#if !defined(CONFIG_USER_ONLY)
> -    if (riscv_has_ext(env, RVH)) {
> -        ctx->virt_enabled = riscv_cpu_virt_enabled(env);
> -    } else {
> -        ctx->virt_enabled = false;
> -    }
> -#else
> -    ctx->virt_enabled = false;
> -#endif
> +    ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
>      ctx->misa_ext = env->misa_ext;
>      ctx->frm = -1;  /* unknown rounding mode */
>      ctx->cfg_ptr = &(cpu->cfg);
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags
  2023-03-25 10:54 ` [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags Richard Henderson
@ 2023-04-11  1:59   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  1:59 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu,
	fei2.wu, Weiwei Li

On Sat, Mar 25, 2023 at 10:01 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> Reuse the MSTATUS_FS and MSTATUS_VS for the tb flags positions is not a
> normal way.
>
> It will make it hard to change the tb flags layout. And even worse, if we
> want to keep tb flags for a same extension togather without a hole.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
> Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Message-Id: <20230324143031.1093-4-zhiwei_liu@linux.alibaba.com>
> [rth: Adjust trans_rvf.c.inc as well; use the typedef]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h                      | 15 +++++------
>  target/riscv/cpu_helper.c               | 11 ++++----
>  target/riscv/translate.c                | 34 ++++++++++++-------------
>  target/riscv/insn_trans/trans_rvf.c.inc |  2 +-
>  target/riscv/insn_trans/trans_rvv.c.inc |  8 +++---
>  5 files changed, 34 insertions(+), 36 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 30d9828d59..f787145a21 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -633,18 +633,17 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>
>  #define TB_FLAGS_PRIV_MMU_MASK                3
>  #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
> -#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
> -#define TB_FLAGS_MSTATUS_VS MSTATUS_VS
>
>  #include "exec/cpu-all.h"
>
>  FIELD(TB_FLAGS, MEM_IDX, 0, 3)
> -FIELD(TB_FLAGS, LMUL, 3, 3)
> -FIELD(TB_FLAGS, SEW, 6, 3)
> -/* Skip MSTATUS_VS (0x600) bits */
> -FIELD(TB_FLAGS, VL_EQ_VLMAX, 11, 1)
> -FIELD(TB_FLAGS, VILL, 12, 1)
> -/* Skip MSTATUS_FS (0x6000) bits */
> +FIELD(TB_FLAGS, FS, 3, 2)
> +/* Vector flags */
> +FIELD(TB_FLAGS, VS, 5, 2)
> +FIELD(TB_FLAGS, LMUL, 7, 3)
> +FIELD(TB_FLAGS, SEW, 10, 3)
> +FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
> +FIELD(TB_FLAGS, VILL, 14, 1)
>  /* Is a Hypervisor instruction load/store allowed? */
>  FIELD(TB_FLAGS, HLSX, 15, 1)
>  FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 9d50e7bbb6..1e7ee9aa30 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -79,16 +79,17 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      }
>
>  #ifdef CONFIG_USER_ONLY
> -    flags |= TB_FLAGS_MSTATUS_FS;
> -    flags |= TB_FLAGS_MSTATUS_VS;
> +    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
>  #else
>      flags |= cpu_mmu_index(env, 0);
>      if (riscv_cpu_fp_enabled(env)) {
> -        flags |= env->mstatus & MSTATUS_FS;
> +        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
> +                            get_field(env->mstatus,  MSTATUS_FS));
>      }
> -
>      if (riscv_cpu_vector_enabled(env)) {
> -        flags |= env->mstatus & MSTATUS_VS;
> +        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
> +                            get_field(env->mstatus, MSTATUS_VS));
>      }
>
>      if (riscv_has_ext(env, RVH)) {
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 880f6318aa..b897bf6006 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -64,10 +64,10 @@ typedef struct DisasContext {
>      RISCVMXL xl;
>      uint32_t misa_ext;
>      uint32_t opcode;
> -    uint32_t mstatus_fs;
> -    uint32_t mstatus_vs;
> -    uint32_t mstatus_hs_fs;
> -    uint32_t mstatus_hs_vs;
> +    RISCVExtStatus mstatus_fs;
> +    RISCVExtStatus mstatus_vs;
> +    RISCVExtStatus mstatus_hs_fs;
> +    RISCVExtStatus mstatus_hs_vs;
>      uint32_t mem_idx;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
> @@ -598,8 +598,7 @@ static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
>  }
>
>  #ifndef CONFIG_USER_ONLY
> -/* The states of mstatus_fs are:
> - * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
> +/*
>   * We will have already diagnosed disabled state,
>   * and need to turn initial/clean into dirty.
>   */
> @@ -611,9 +610,9 @@ static void mark_fs_dirty(DisasContext *ctx)
>          return;
>      }
>
> -    if (ctx->mstatus_fs != MSTATUS_FS) {
> +    if (ctx->mstatus_fs != EXT_STATUS_DIRTY) {
>          /* Remember the state change for the rest of the TB. */
> -        ctx->mstatus_fs = MSTATUS_FS;
> +        ctx->mstatus_fs = EXT_STATUS_DIRTY;
>
>          tmp = tcg_temp_new();
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> @@ -621,9 +620,9 @@ static void mark_fs_dirty(DisasContext *ctx)
>          tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>      }
>
> -    if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
> +    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
>          /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_fs = MSTATUS_FS;
> +        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
>
>          tmp = tcg_temp_new();
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> @@ -636,8 +635,7 @@ static inline void mark_fs_dirty(DisasContext *ctx) { }
>  #endif
>
>  #ifndef CONFIG_USER_ONLY
> -/* The states of mstatus_vs are:
> - * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
> +/*
>   * We will have already diagnosed disabled state,
>   * and need to turn initial/clean into dirty.
>   */
> @@ -645,9 +643,9 @@ static void mark_vs_dirty(DisasContext *ctx)
>  {
>      TCGv tmp;
>
> -    if (ctx->mstatus_vs != MSTATUS_VS) {
> +    if (ctx->mstatus_vs != EXT_STATUS_DIRTY) {
>          /* Remember the state change for the rest of the TB.  */
> -        ctx->mstatus_vs = MSTATUS_VS;
> +        ctx->mstatus_vs = EXT_STATUS_DIRTY;
>
>          tmp = tcg_temp_new();
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> @@ -655,9 +653,9 @@ static void mark_vs_dirty(DisasContext *ctx)
>          tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>      }
>
> -    if (ctx->virt_enabled && ctx->mstatus_hs_vs != MSTATUS_VS) {
> +    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
>          /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_vs = MSTATUS_VS;
> +        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
>
>          tmp = tcg_temp_new();
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> @@ -1153,8 +1151,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>
>      ctx->pc_succ_insn = ctx->base.pc_first;
>      ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
> -    ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
> -    ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
> +    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
>      ctx->priv_ver = env->priv_ver;
>      ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
>      ctx->misa_ext = env->misa_ext;
> diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc
> index 052408f45c..31cd3d0e05 100644
> --- a/target/riscv/insn_trans/trans_rvf.c.inc
> +++ b/target/riscv/insn_trans/trans_rvf.c.inc
> @@ -19,7 +19,7 @@
>   */
>
>  #define REQUIRE_FPU do {\
> -    if (ctx->mstatus_fs == 0) \
> +    if (ctx->mstatus_fs == EXT_STATUS_DISABLED) \
>          if (!ctx->cfg_ptr->ext_zfinx) \
>              return false; \
>  } while (0)
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
> index f2e3d38515..6297c3b50d 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -29,12 +29,12 @@ static inline bool is_overlapped(const int8_t astart, int8_t asize,
>
>  static bool require_rvv(DisasContext *s)
>  {
> -    return s->mstatus_vs != 0;
> +    return s->mstatus_vs != EXT_STATUS_DISABLED;
>  }
>
>  static bool require_rvf(DisasContext *s)
>  {
> -    if (s->mstatus_fs == 0) {
> +    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
>          return false;
>      }
>
> @@ -52,7 +52,7 @@ static bool require_rvf(DisasContext *s)
>
>  static bool require_scale_rvf(DisasContext *s)
>  {
> -    if (s->mstatus_fs == 0) {
> +    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
>          return false;
>      }
>
> @@ -70,7 +70,7 @@ static bool require_scale_rvf(DisasContext *s)
>
>  static bool require_scale_rvfmin(DisasContext *s)
>  {
> -    if (s->mstatus_fs == 0) {
> +    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
>          return false;
>      }
>
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags
  2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
  2023-03-27  1:34   ` liweiwei
  2023-03-28  2:34   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs,vs} " LIU Zhiwei
@ 2023-04-11  2:02   ` Alistair Francis
  2 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  2:02 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:36 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Merge with mstatus_{fs,vs}.  We might perform a redundant
> assignment to one or the other field, but it's a trivial
> and saves 4 bits from TB_FLAGS.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h        | 16 +++++++---------
>  target/riscv/cpu_helper.c | 34 ++++++++++++++++------------------
>  target/riscv/translate.c  | 32 ++++++++++----------------------
>  3 files changed, 33 insertions(+), 49 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index f787145a21..d9e0eaaf9b 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -646,19 +646,17 @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
>  FIELD(TB_FLAGS, VILL, 14, 1)
>  /* Is a Hypervisor instruction load/store allowed? */
>  FIELD(TB_FLAGS, HLSX, 15, 1)
> -FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
> -FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2)
>  /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
> -FIELD(TB_FLAGS, XL, 20, 2)
> +FIELD(TB_FLAGS, XL, 16, 2)
>  /* If PointerMasking should be applied */
> -FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
> -FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
> -FIELD(TB_FLAGS, VTA, 24, 1)
> -FIELD(TB_FLAGS, VMA, 25, 1)
> +FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1)
> +FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1)
> +FIELD(TB_FLAGS, VTA, 20, 1)
> +FIELD(TB_FLAGS, VMA, 21, 1)
>  /* Native debug itrigger */
> -FIELD(TB_FLAGS, ITRIGGER, 26, 1)
> +FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>  /* Virtual mode enabled */
> -FIELD(TB_FLAGS, VIRT_ENABLED, 27, 1)
> +FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>
>  #ifdef TARGET_RISCV32
>  #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 1e7ee9aa30..4fdd6fe021 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -45,7 +45,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>  {
>      CPUState *cs = env_cpu(env);
>      RISCVCPU *cpu = RISCV_CPU(cs);
> -
> +    RISCVExtStatus fs, vs;
>      uint32_t flags = 0;
>
>      *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
> @@ -79,18 +79,12 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      }
>
>  #ifdef CONFIG_USER_ONLY
> -    flags = FIELD_DP32(flags, TB_FLAGS, FS, EXT_STATUS_DIRTY);
> -    flags = FIELD_DP32(flags, TB_FLAGS, VS, EXT_STATUS_DIRTY);
> +    fs = EXT_STATUS_DIRTY;
> +    vs = EXT_STATUS_DIRTY;
>  #else
>      flags |= cpu_mmu_index(env, 0);
> -    if (riscv_cpu_fp_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, FS,
> -                            get_field(env->mstatus,  MSTATUS_FS));
> -    }
> -    if (riscv_cpu_vector_enabled(env)) {
> -        flags =  FIELD_DP32(flags, TB_FLAGS, VS,
> -                            get_field(env->mstatus, MSTATUS_VS));
> -    }
> +    fs = get_field(env->mstatus, MSTATUS_FS);
> +    vs = get_field(env->mstatus, MSTATUS_VS);
>
>      if (riscv_has_ext(env, RVH)) {
>          if (env->priv == PRV_M ||
> @@ -100,19 +94,23 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>              flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
>          }
>
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
> -                           get_field(env->mstatus_hs, MSTATUS_FS));
> -
> -        flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
> -                           get_field(env->mstatus_hs, MSTATUS_VS));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED,
> -                           get_field(env->virt, VIRT_ONOFF));
> +        if (riscv_cpu_virt_enabled(env)) {
> +            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +            /*
> +             * Merge DISABLED and !DIRTY states using MIN.
> +             * We will set both fields when dirtying.
> +             */
> +            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> +            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> +        }
>      }
>      if (cpu->cfg.debug && !icount_enabled()) {
>          flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>      }
>  #endif
>
> +    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
>      flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
>      if (env->cur_pmmask < (env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX)) {
>          flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index b897bf6006..74d0b9889d 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -66,8 +66,6 @@ typedef struct DisasContext {
>      uint32_t opcode;
>      RISCVExtStatus mstatus_fs;
>      RISCVExtStatus mstatus_vs;
> -    RISCVExtStatus mstatus_hs_fs;
> -    RISCVExtStatus mstatus_hs_vs;
>      uint32_t mem_idx;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
> @@ -618,16 +616,12 @@ static void mark_fs_dirty(DisasContext *ctx)
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>          tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
>          tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>
> -    if (ctx->virt_enabled && ctx->mstatus_hs_fs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_fs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }
>      }
>  }
>  #else
> @@ -651,16 +645,12 @@ static void mark_vs_dirty(DisasContext *ctx)
>          tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>          tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
>          tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -    }
>
> -    if (ctx->virt_enabled && ctx->mstatus_hs_vs != EXT_STATUS_DIRTY) {
> -        /* Remember the stage change for the rest of the TB. */
> -        ctx->mstatus_hs_vs = EXT_STATUS_DIRTY;
> -
> -        tmp = tcg_temp_new();
> -        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> -        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        if (ctx->virt_enabled) {
> +            tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +            tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
> +            tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +        }
>      }
>  }
>  #else
> @@ -1158,8 +1148,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->misa_ext = env->misa_ext;
>      ctx->frm = -1;  /* unknown rounding mode */
>      ctx->cfg_ptr = &(cpu->cfg);
> -    ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
> -    ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
>      ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
>      ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
>      ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 02/25] target/riscv: Add a general status enum for extensions
  2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
  2023-03-26 12:54   ` liweiwei
@ 2023-04-11  2:05   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  2:05 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> The pointer masking is the only extension that directly use status.
> The vector or float extension uses the status in an indirect way.
>
> Replace the pointer masking extension special status fields with
> the general status.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
> Message-Id: <20230324143031.1093-3-zhiwei_liu@linux.alibaba.com>
> [rth: Add a typedef for the enum]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h      |  8 ++++++++
>  target/riscv/cpu_bits.h | 12 ++++--------
>  target/riscv/cpu.c      |  2 +-
>  target/riscv/csr.c      | 14 +++++++-------
>  4 files changed, 20 insertions(+), 16 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 12fe8d8546..30d9828d59 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -99,6 +99,14 @@ enum {
>      TRANSLATE_G_STAGE_FAIL
>  };
>
> +/* Extension context status */
> +typedef enum {
> +    EXT_STATUS_DISABLED = 0,
> +    EXT_STATUS_INITIAL,
> +    EXT_STATUS_CLEAN,
> +    EXT_STATUS_DIRTY,
> +} RISCVExtStatus;
> +
>  #define MMU_USER_IDX 3
>
>  #define MAX_RISCV_PMPS (16)
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index fca7ef0cef..b84f62f8d6 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -9,6 +9,9 @@
>                   (((uint64_t)(val) * ((mask) & ~((mask) << 1))) & \
>                   (uint64_t)(mask)))
>
> +/* Extension context status mask */
> +#define EXT_STATUS_MASK     0x3ULL
> +
>  /* Floating point round mode */
>  #define FSR_RD_SHIFT        5
>  #define FSR_RD              (0x7 << FSR_RD_SHIFT)
> @@ -734,13 +737,6 @@ typedef enum RISCVException {
>  #define PM_ENABLE       0x00000001ULL
>  #define PM_CURRENT      0x00000002ULL
>  #define PM_INSN         0x00000004ULL
> -#define PM_XS_MASK      0x00000003ULL
> -
> -/* PointerMasking XS bits values */
> -#define PM_EXT_DISABLE  0x00000000ULL
> -#define PM_EXT_INITIAL  0x00000001ULL
> -#define PM_EXT_CLEAN    0x00000002ULL
> -#define PM_EXT_DIRTY    0x00000003ULL
>
>  /* Execution enviornment configuration bits */
>  #define MENVCFG_FIOM                       BIT(0)
> @@ -780,7 +776,7 @@ typedef enum RISCVException {
>  #define S_OFFSET     5ULL
>  #define M_OFFSET     8ULL
>
> -#define PM_XS_BITS   (PM_XS_MASK << XS_OFFSET)
> +#define PM_XS_BITS   (EXT_STATUS_MASK << XS_OFFSET)
>  #define U_PM_ENABLE  (PM_ENABLE  << U_OFFSET)
>  #define U_PM_CURRENT (PM_CURRENT << U_OFFSET)
>  #define U_PM_INSN    (PM_INSN    << U_OFFSET)
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1e97473af2..1135106b3e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -764,7 +764,7 @@ static void riscv_cpu_reset_hold(Object *obj)
>          i++;
>      }
>      /* mmte is supposed to have pm.current hardwired to 1 */
> -    env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
> +    env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
>  #endif
>      env->xl = riscv_cpu_mxl(env);
>      riscv_cpu_update_mask(env);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index d522efc0b6..abea7b749e 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3513,7 +3513,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno,
>
>      /* hardwiring pm.instruction bit to 0, since it's not supported yet */
>      wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
> -    env->mmte = wpri_val | PM_EXT_DIRTY;
> +    env->mmte = wpri_val | EXT_STATUS_DIRTY;
>      riscv_cpu_update_mask(env);
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -3593,7 +3593,7 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
>          env->cur_pmmask = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> @@ -3621,7 +3621,7 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
>          env->cur_pmmask = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> @@ -3649,7 +3649,7 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
>          env->cur_pmmask = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> @@ -3673,7 +3673,7 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
>          env->cur_pmbase = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> @@ -3701,7 +3701,7 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
>          env->cur_pmbase = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> @@ -3729,7 +3729,7 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
>      if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
>          env->cur_pmbase = val;
>      }
> -    env->mmte |= PM_EXT_DIRTY;
> +    env->mmte |= EXT_STATUS_DIRTY;
>
>      /* Set XS and SD bits, since PM CSRs are dirty */
>      mstatus = env->mstatus | MSTATUS_XS;
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart
  2023-03-25 10:54 ` [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart Richard Henderson
@ 2023-04-11  2:07   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  2:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu,
	fei2.wu, Weiwei Li

On Sat, Mar 25, 2023 at 9:52 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
>
> Once we mistook the vstart directly from the env->vstart. As env->vstart is not
> a constant, we should record it in the tb flags if we want to use
> it in translation.
>
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
> Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Message-Id: <20230324143031.1093-5-zhiwei_liu@linux.alibaba.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h                      |  1 +
>  target/riscv/cpu_helper.c               |  1 +
>  target/riscv/translate.c                |  4 ++--
>  target/riscv/insn_trans/trans_rvv.c.inc | 14 +++++++-------
>  4 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index d9e0eaaf9b..86a82e25dc 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -657,6 +657,7 @@ FIELD(TB_FLAGS, VMA, 21, 1)
>  FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>  /* Virtual mode enabled */
>  FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
> +FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
>
>  #ifdef TARGET_RISCV32
>  #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 4fdd6fe021..4f0999d50b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -74,6 +74,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>                      FIELD_EX64(env->vtype, VTYPE, VTA));
>          flags = FIELD_DP32(flags, TB_FLAGS, VMA,
>                      FIELD_EX64(env->vtype, VTYPE, VMA));
> +        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
>      } else {
>          flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
>      }
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 74d0b9889d..f8c077525c 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -97,7 +97,7 @@ typedef struct DisasContext {
>      uint8_t vta;
>      uint8_t vma;
>      bool cfg_vta_all_1s;
> -    target_ulong vstart;
> +    bool vstart_eq_zero;
>      bool vl_eq_vlmax;
>      CPUState *cs;
>      TCGv zero;
> @@ -1155,7 +1155,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
>      ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s;
>      ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
> -    ctx->vstart = env->vstart;
> +    ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
>      ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
>      ctx->misa_mxl_max = env->misa_mxl_max;
>      ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
> index 6297c3b50d..32b3b9a8e5 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -547,7 +547,7 @@ static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
>   */
>  static bool vext_check_reduction(DisasContext *s, int vs2)
>  {
> -    return require_align(vs2, s->lmul) && (s->vstart == 0);
> +    return require_align(vs2, s->lmul) && s->vstart_eq_zero;
>  }
>
>  /*
> @@ -3083,7 +3083,7 @@ static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
>  {
>      if (require_rvv(s) &&
>          vext_check_isa_ill(s) &&
> -        s->vstart == 0) {
> +        s->vstart_eq_zero) {
>          TCGv_ptr src2, mask;
>          TCGv dst;
>          TCGv_i32 desc;
> @@ -3112,7 +3112,7 @@ static bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
>  {
>      if (require_rvv(s) &&
>          vext_check_isa_ill(s) &&
> -        s->vstart == 0) {
> +        s->vstart_eq_zero) {
>          TCGv_ptr src2, mask;
>          TCGv dst;
>          TCGv_i32 desc;
> @@ -3146,7 +3146,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
>          vext_check_isa_ill(s) &&                                   \
>          require_vm(a->vm, a->rd) &&                                \
>          (a->rd != a->rs2) &&                                       \
> -        (s->vstart == 0)) {                                        \
> +        s->vstart_eq_zero) {                                       \
>          uint32_t data = 0;                                         \
>          gen_helper_gvec_3_ptr *fn = gen_helper_##NAME;             \
>          TCGLabel *over = gen_new_label();                          \
> @@ -3187,7 +3187,7 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
>          !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
>          require_vm(a->vm, a->rd) &&
>          require_align(a->rd, s->lmul) &&
> -        (s->vstart == 0)) {
> +        s->vstart_eq_zero) {
>          uint32_t data = 0;
>          TCGLabel *over = gen_new_label();
>          tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
> @@ -3636,7 +3636,7 @@ static bool vcompress_vm_check(DisasContext *s, arg_r *a)
>             require_align(a->rs2, s->lmul) &&
>             (a->rd != a->rs2) &&
>             !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1) &&
> -           (s->vstart == 0);
> +           s->vstart_eq_zero;
>  }
>
>  static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
> @@ -3675,7 +3675,7 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a)               \
>          QEMU_IS_ALIGNED(a->rd, LEN) &&                                  \
>          QEMU_IS_ALIGNED(a->rs2, LEN)) {                                 \
>          uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN;                 \
> -        if (s->vstart == 0) {                                           \
> +        if (s->vstart_eq_zero) {                                        \
>              /* EEW = 8 */                                               \
>              tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd),                  \
>                               vreg_ofs(s, a->rs2), maxsz, maxsz);        \
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx
  2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
  2023-03-28  2:39   ` LIU Zhiwei
@ 2023-04-11  2:08   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  2:08 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:01 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: Fei Wu <fei2.wu@intel.com>
>
> Currently it's assumed the 2 low bits of mmu_idx map to privilege mode,
> this assumption won't last as we are about to add more mmu_idx. Here an
> individual priv field is added into TB_FLAGS.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Message-Id: <20230324054154.414846-2-fei2.wu@intel.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h                             | 2 +-
>  target/riscv/cpu_helper.c                      | 4 +++-
>  target/riscv/translate.c                       | 2 ++
>  target/riscv/insn_trans/trans_privileged.c.inc | 2 +-
>  target/riscv/insn_trans/trans_xthead.c.inc     | 7 +------
>  5 files changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 86a82e25dc..3e59dbb3fd 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -631,7 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
>  target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
>  void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>
> -#define TB_FLAGS_PRIV_MMU_MASK                3
>  #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
>
>  #include "exec/cpu-all.h"
> @@ -658,6 +657,7 @@ FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>  /* Virtual mode enabled */
>  FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>  FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
> +FIELD(TB_FLAGS, PRIV, 25, 2)
>
>  #ifdef TARGET_RISCV32
>  #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 4f0999d50b..5753126c7a 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -83,6 +83,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      fs = EXT_STATUS_DIRTY;
>      vs = EXT_STATUS_DIRTY;
>  #else
> +    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
> +
>      flags |= cpu_mmu_index(env, 0);
>      fs = get_field(env->mstatus, MSTATUS_FS);
>      vs = get_field(env->mstatus, MSTATUS_VS);
> @@ -764,7 +766,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>       * (riscv_cpu_do_interrupt) is correct */
>      MemTxResult res;
>      MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
> -    int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
> +    int mode = env->priv;
>      bool use_background = false;
>      hwaddr ppn;
>      RISCVCPU *cpu = env_archcpu(env);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index f8c077525c..abfc152553 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -67,6 +67,7 @@ typedef struct DisasContext {
>      RISCVExtStatus mstatus_fs;
>      RISCVExtStatus mstatus_vs;
>      uint32_t mem_idx;
> +    uint32_t priv;
>      /* Remember the rounding mode encoded in the previous fp instruction,
>         which we have already installed into env->fp_status.  Or -1 for
>         no previous fp instruction.  Note that we exit the TB when writing
> @@ -1140,6 +1141,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      uint32_t tb_flags = ctx->base.tb->flags;
>
>      ctx->pc_succ_insn = ctx->base.pc_first;
> +    ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
>      ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
>      ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
>      ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
> diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
> index 59501b2780..9305b18299 100644
> --- a/target/riscv/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> @@ -52,7 +52,7 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
>       * that no exception will be raised when fetching them.
>       */
>
> -    if (semihosting_enabled(ctx->mem_idx < PRV_S) &&
> +    if (semihosting_enabled(ctx->priv < PRV_S) &&
>          (pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
>          pre    = opcode_at(&ctx->base, pre_addr);
>          ebreak = opcode_at(&ctx->base, ebreak_addr);
> diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
> index df504c3f2c..adfb53cb4c 100644
> --- a/target/riscv/insn_trans/trans_xthead.c.inc
> +++ b/target/riscv/insn_trans/trans_xthead.c.inc
> @@ -265,12 +265,7 @@ static bool trans_th_tst(DisasContext *ctx, arg_th_tst *a)
>
>  static inline int priv_level(DisasContext *ctx)
>  {
> -#ifdef CONFIG_USER_ONLY
> -    return PRV_U;
> -#else
> -     /* Priv level is part of mem_idx. */
> -    return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
> -#endif
> +    return ctx->priv;
>  }
>
>  /* Test if priv level is M, S, or U (cannot fail). */
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change
  2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
  2023-03-28  2:41   ` LIU Zhiwei
@ 2023-04-11  2:11   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  2:11 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> From: Fei Wu <fei2.wu@intel.com>
>
> Kernel needs to access user mode memory e.g. during syscalls, the window
> is usually opened up for a very limited time through MSTATUS.SUM, the
> overhead is too much if tlb_flush() gets called for every SUM change.
>
> This patch creates a separate MMU index for S+SUM, so that it's not
> necessary to flush tlb anymore when SUM changes. This is similar to how
> ARM handles Privileged Access Never (PAN).
>
> Result of 'pipe 10' from unixbench boosts from 223656 to 1705006. Many
> other syscalls benefit a lot from this too.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Message-Id: <20230324054154.414846-3-fei2.wu@intel.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h                      |  2 --
>  target/riscv/internals.h                | 14 ++++++++++++++
>  target/riscv/cpu_helper.c               | 17 +++++++++++++++--
>  target/riscv/csr.c                      |  3 +--
>  target/riscv/op_helper.c                |  5 +++--
>  target/riscv/insn_trans/trans_rvh.c.inc |  4 ++--
>  6 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 3e59dbb3fd..5e589db106 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -631,8 +631,6 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
>  target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
>  void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
>
> -#define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
> -
>  #include "exec/cpu-all.h"
>
>  FIELD(TB_FLAGS, MEM_IDX, 0, 3)
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 5620fbffb6..b55152a7dc 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -21,6 +21,20 @@
>
>  #include "hw/registerfields.h"
>
> +/*
> + * The current MMU Modes are:
> + *  - U                 0b000
> + *  - S                 0b001
> + *  - S+SUM             0b010
> + *  - M                 0b011
> + *  - HLV/HLVX/HSV adds 0b100
> + */
> +#define MMUIdx_U            0
> +#define MMUIdx_S            1
> +#define MMUIdx_S_SUM        2
> +#define MMUIdx_M            3
> +#define MMU_HYP_ACCESS_BIT  (1 << 2)
> +
>  /* share data between vector helpers and decode code */
>  FIELD(VDATA, VM, 0, 1)
>  FIELD(VDATA, LMUL, 1, 3)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 5753126c7a..052fdd2d9d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -21,6 +21,7 @@
>  #include "qemu/log.h"
>  #include "qemu/main-loop.h"
>  #include "cpu.h"
> +#include "internals.h"
>  #include "pmu.h"
>  #include "exec/exec-all.h"
>  #include "instmap.h"
> @@ -36,7 +37,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  #ifdef CONFIG_USER_ONLY
>      return 0;
>  #else
> -    return env->priv;
> +    if (ifetch) {
> +        return env->priv;
> +    }
> +
> +    /* All priv -> mmu_idx mapping are here */
> +    int mode = env->priv;
> +    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> +        mode = get_field(env->mstatus, MSTATUS_MPP);
> +    }
> +    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
> +        return MMUIdx_S_SUM;
> +    }
> +    return mode;
>  #endif
>  }
>
> @@ -600,7 +613,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
>
>  bool riscv_cpu_two_stage_lookup(int mmu_idx)
>  {
> -    return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    return mmu_idx & MMU_HYP_ACCESS_BIT;
>  }
>
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index abea7b749e..b79758a606 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1246,8 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
>      RISCVMXL xl = riscv_cpu_mxl(env);
>
>      /* flush tlb on mstatus fields that affect VM */
> -    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
> -            MSTATUS_MPRV | MSTATUS_SUM)) {
> +    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) {
>          tlb_flush(env_cpu(env));
>      }
>      mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 84ee018f7d..962a061228 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -20,6 +20,7 @@
>
>  #include "qemu/osdep.h"
>  #include "cpu.h"
> +#include "internals.h"
>  #include "qemu/main-loop.h"
>  #include "exec/exec-all.h"
>  #include "exec/helper-proto.h"
> @@ -428,14 +429,14 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
>
>  target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
>  {
> -    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
>
>      return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
>  }
>
>  target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
>  {
> -    int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
>
>      return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
>  }
> diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
> index 9248b48c36..15842f4282 100644
> --- a/target/riscv/insn_trans/trans_rvh.c.inc
> +++ b/target/riscv/insn_trans/trans_rvh.c.inc
> @@ -40,7 +40,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
>      if (check_access(ctx)) {
>          TCGv dest = dest_gpr(ctx, a->rd);
>          TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
>          tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
>          gen_set_gpr(ctx, a->rd, dest);
>      }
> @@ -87,7 +87,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
>      if (check_access(ctx)) {
>          TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
>          TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
> +        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
>          tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
>      }
>      return true;
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu
  2023-03-25 10:54 ` [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu Richard Henderson
@ 2023-04-11  3:10   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:10 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:52 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> At least RISC-V has the need to be able to perform a read
> using execute permissions, outside of translation.
> Add helpers to facilitate this.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/exec/cpu_ldst.h |  9 +++++++
>  accel/tcg/cputlb.c      | 48 ++++++++++++++++++++++++++++++++++
>  accel/tcg/user-exec.c   | 58 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 115 insertions(+)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index 09b55cc0ee..c141f0394f 100644
> --- a/include/exec/cpu_ldst.h
> +++ b/include/exec/cpu_ldst.h
> @@ -445,6 +445,15 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
>  # define cpu_stq_mmu          cpu_stq_le_mmu
>  #endif
>
> +uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
> +                         MemOpIdx oi, uintptr_t ra);
> +uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra);
> +uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra);
> +uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra);
> +
>  uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr);
>  uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr);
>  uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr);
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index e984a98dc4..e62c8f3c3f 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -2768,3 +2768,51 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
>      MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
>      return full_ldq_code(env, addr, oi, 0);
>  }
> +
> +uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
> +                         MemOpIdx oi, uintptr_t retaddr)
> +{
> +    return full_ldub_code(env, addr, oi, retaddr);
> +}
> +
> +uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t retaddr)
> +{
> +    MemOp mop = get_memop(oi);
> +    int idx = get_mmuidx(oi);
> +    uint16_t ret;
> +
> +    ret = full_lduw_code(env, addr, make_memop_idx(MO_TEUW, idx), retaddr);
> +    if ((mop & MO_BSWAP) != MO_TE) {
> +        ret = bswap16(ret);
> +    }
> +    return ret;
> +}
> +
> +uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t retaddr)
> +{
> +    MemOp mop = get_memop(oi);
> +    int idx = get_mmuidx(oi);
> +    uint32_t ret;
> +
> +    ret = full_ldl_code(env, addr, make_memop_idx(MO_TEUL, idx), retaddr);
> +    if ((mop & MO_BSWAP) != MO_TE) {
> +        ret = bswap32(ret);
> +    }
> +    return ret;
> +}
> +
> +uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t retaddr)
> +{
> +    MemOp mop = get_memop(oi);
> +    int idx = get_mmuidx(oi);
> +    uint64_t ret;
> +
> +    ret = full_ldq_code(env, addr, make_memop_idx(MO_TEUQ, idx), retaddr);
> +    if ((mop & MO_BSWAP) != MO_TE) {
> +        ret = bswap64(ret);
> +    }
> +    return ret;
> +}
> diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
> index 7b37fd229e..44e0ea55ba 100644
> --- a/accel/tcg/user-exec.c
> +++ b/accel/tcg/user-exec.c
> @@ -1222,6 +1222,64 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
>      return ret;
>  }
>
> +uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
> +                         MemOpIdx oi, uintptr_t ra)
> +{
> +    void *haddr;
> +    uint8_t ret;
> +
> +    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
> +    ret = ldub_p(haddr);
> +    clear_helper_retaddr();
> +    return ret;
> +}
> +
> +uint16_t cpu_ldw_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra)
> +{
> +    void *haddr;
> +    uint16_t ret;
> +
> +    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
> +    ret = lduw_p(haddr);
> +    clear_helper_retaddr();
> +    if (get_memop(oi) & MO_BSWAP) {
> +        ret = bswap16(ret);
> +    }
> +    return ret;
> +}
> +
> +uint32_t cpu_ldl_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra)
> +{
> +    void *haddr;
> +    uint32_t ret;
> +
> +    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_INST_FETCH);
> +    ret = ldl_p(haddr);
> +    clear_helper_retaddr();
> +    if (get_memop(oi) & MO_BSWAP) {
> +        ret = bswap32(ret);
> +    }
> +    return ret;
> +}
> +
> +uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
> +                          MemOpIdx oi, uintptr_t ra)
> +{
> +    void *haddr;
> +    uint64_t ret;
> +
> +    validate_memop(oi, MO_BEUQ);
> +    haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
> +    ret = ldq_p(haddr);
> +    clear_helper_retaddr();
> +    if (get_memop(oi) & MO_BSWAP) {
> +        ret = bswap64(ret);
> +    }
> +    return ret;
> +}
> +
>  #include "ldst_common.c.inc"
>
>  /*
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX
  2023-03-25 10:54 ` [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX Richard Henderson
@ 2023-04-11  3:12   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:12 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:53 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Use the new functions to properly check execute permission
> for the read rather than read permission.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/op_helper.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 962a061228..b2169a99ff 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -427,18 +427,27 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
>      helper_hyp_tlb_flush(env);
>  }
>
> +/*
> + * TODO: These implementations are not quite correct.  They perform the
> + * access using execute permission just fine, but the final PMP check
> + * is supposed to have read permission as well.  Without replicating
> + * a fair fraction of cputlb.c, fixing this requires adding new mmu_idx
> + * which would imply that exact check in tlb_fill.
> + */
>  target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
>  {
>      int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
> +    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
>
> -    return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
> +    return cpu_ldw_code_mmu(env, address, oi, GETPC());
>  }
>
>  target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
>  {
>      int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
> +    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
>
> -    return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
> +    return cpu_ldl_code_mmu(env, address, oi, GETPC());
>  }
>
>  #endif /* !CONFIG_USER_ONLY */
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers
  2023-03-25 10:54 ` [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers Richard Henderson
@ 2023-04-11  3:34   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:34 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:53 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Implement these instructions via helpers, in expectation
> of determining the mmu_idx to use at runtime.  This allows
> the permission check to also be moved out of line, which
> allows HLSX to be removed from TB_FLAGS.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h                      |   6 +-
>  target/riscv/helper.h                   |  12 ++-
>  target/riscv/cpu_helper.c               |  26 ++---
>  target/riscv/op_helper.c                |  99 +++++++++++++++--
>  target/riscv/translate.c                |   2 -
>  target/riscv/insn_trans/trans_rvh.c.inc | 135 ++++++++++--------------
>  6 files changed, 169 insertions(+), 111 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5e589db106..f03ff1f10c 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -641,8 +641,7 @@ FIELD(TB_FLAGS, LMUL, 7, 3)
>  FIELD(TB_FLAGS, SEW, 10, 3)
>  FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1)
>  FIELD(TB_FLAGS, VILL, 14, 1)
> -/* Is a Hypervisor instruction load/store allowed? */
> -FIELD(TB_FLAGS, HLSX, 15, 1)
> +FIELD(TB_FLAGS, VSTART_EQ_ZERO, 15, 1)
>  /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
>  FIELD(TB_FLAGS, XL, 16, 2)
>  /* If PointerMasking should be applied */
> @@ -654,8 +653,7 @@ FIELD(TB_FLAGS, VMA, 21, 1)
>  FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>  /* Virtual mode enabled */
>  FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
> -FIELD(TB_FLAGS, VSTART_EQ_ZERO, 24, 1)
> -FIELD(TB_FLAGS, PRIV, 25, 2)
> +FIELD(TB_FLAGS, PRIV, 24, 2)
>
>  #ifdef TARGET_RISCV32
>  #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 37b54e0991..be60bd1525 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -123,8 +123,16 @@ DEF_HELPER_1(itrigger_match, void, env)
>  #ifndef CONFIG_USER_ONLY
>  DEF_HELPER_1(hyp_tlb_flush, void, env)
>  DEF_HELPER_1(hyp_gvma_tlb_flush, void, env)
> -DEF_HELPER_2(hyp_hlvx_hu, tl, env, tl)
> -DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlv_bu, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlv_hu, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlv_wu, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlv_d, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlvx_hu, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_2(hyp_hlvx_wu, TCG_CALL_NO_WG, tl, env, tl)
> +DEF_HELPER_FLAGS_3(hyp_hsv_b, TCG_CALL_NO_WG, void, env, tl, tl)
> +DEF_HELPER_FLAGS_3(hyp_hsv_h, TCG_CALL_NO_WG, void, env, tl, tl)
> +DEF_HELPER_FLAGS_3(hyp_hsv_w, TCG_CALL_NO_WG, void, env, tl, tl)
> +DEF_HELPER_FLAGS_3(hyp_hsv_d, TCG_CALL_NO_WG, void, env, tl, tl)
>  #endif
>
>  /* Vector functions */
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 052fdd2d9d..9bb84be4e1 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -102,24 +102,16 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>      fs = get_field(env->mstatus, MSTATUS_FS);
>      vs = get_field(env->mstatus, MSTATUS_VS);
>
> -    if (riscv_has_ext(env, RVH)) {
> -        if (env->priv == PRV_M ||
> -            (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
> -            (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
> -                get_field(env->hstatus, HSTATUS_HU))) {
> -            flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
> -        }
> -
> -        if (riscv_cpu_virt_enabled(env)) {
> -            flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> -            /*
> -             * Merge DISABLED and !DIRTY states using MIN.
> -             * We will set both fields when dirtying.
> -             */
> -            fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> -            vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
> -        }
> +    if (riscv_cpu_virt_enabled(env)) {
> +        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +        /*
> +         * Merge DISABLED and !DIRTY states using MIN.
> +         * We will set both fields when dirtying.
> +         */
> +        fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
> +        vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
>      }
> +
>      if (cpu->cfg.debug && !icount_enabled()) {
>          flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>      }
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index b2169a99ff..0f81645adf 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -427,6 +427,91 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
>      helper_hyp_tlb_flush(env);
>  }
>
> +static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
> +{
> +    if (env->priv == PRV_M) {
> +        /* always allowed */
> +    } else if (riscv_cpu_virt_enabled(env)) {
> +        riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, ra);
> +    } else if (env->priv == PRV_U && !get_field(env->hstatus, HSTATUS_HU)) {
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
> +    }
> +
> +    return cpu_mmu_index(env, x) | MMU_HYP_ACCESS_BIT;
> +}
> +
> +target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
> +
> +    return cpu_ldb_mmu(env, addr, oi, ra);
> +}
> +
> +target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
> +
> +    return cpu_ldw_mmu(env, addr, oi, ra);
> +}
> +
> +target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
> +
> +    return cpu_ldl_mmu(env, addr, oi, ra);
> +}
> +
> +target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
> +
> +    return cpu_ldq_mmu(env, addr, oi, ra);
> +}
> +
> +void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
> +
> +    cpu_stb_mmu(env, addr, val, oi, ra);
> +}
> +
> +void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
> +
> +    cpu_stw_mmu(env, addr, val, oi, ra);
> +}
> +
> +void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
> +
> +    cpu_stl_mmu(env, addr, val, oi, ra);
> +}
> +
> +void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
> +{
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, false, ra);
> +    MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
> +
> +    cpu_stq_mmu(env, addr, val, oi, ra);
> +}
> +
>  /*
>   * TODO: These implementations are not quite correct.  They perform the
>   * access using execute permission just fine, but the final PMP check
> @@ -434,20 +519,22 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
>   * a fair fraction of cputlb.c, fixing this requires adding new mmu_idx
>   * which would imply that exact check in tlb_fill.
>   */
> -target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
> +target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong addr)
>  {
> -    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, true, ra);
>      MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
>
> -    return cpu_ldw_code_mmu(env, address, oi, GETPC());
> +    return cpu_ldw_code_mmu(env, addr, oi, GETPC());
>  }
>
> -target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
> +target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr)
>  {
> -    int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
> +    uintptr_t ra = GETPC();
> +    int mmu_idx = check_access_hlsv(env, true, ra);
>      MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
>
> -    return cpu_ldl_code_mmu(env, address, oi, GETPC());
> +    return cpu_ldl_code_mmu(env, addr, oi, ra);
>  }
>
>  #endif /* !CONFIG_USER_ONLY */
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index abfc152553..5282588247 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -78,7 +78,6 @@ typedef struct DisasContext {
>      bool virt_inst_excp;
>      bool virt_enabled;
>      const RISCVCPUConfig *cfg_ptr;
> -    bool hlsx;
>      /* vector extension */
>      bool vill;
>      /*
> @@ -1150,7 +1149,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->misa_ext = env->misa_ext;
>      ctx->frm = -1;  /* unknown rounding mode */
>      ctx->cfg_ptr = &(cpu->cfg);
> -    ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
>      ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
>      ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
>      ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
> diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
> index 15842f4282..3e9322130f 100644
> --- a/target/riscv/insn_trans/trans_rvh.c.inc
> +++ b/target/riscv/insn_trans/trans_rvh.c.inc
> @@ -16,156 +16,131 @@
>   * this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>
> -#ifndef CONFIG_USER_ONLY
> -static bool check_access(DisasContext *ctx)
> -{
> -    if (!ctx->hlsx) {
> -        if (ctx->virt_enabled) {
> -            generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
> -        } else {
> -            generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
> -        }
> -        return false;
> -    }
> -    return true;
> -}
> -#endif
> -
> -static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
> -{
>  #ifdef CONFIG_USER_ONLY
> -    return false;
> +#define do_hlv(ctx, a, func)  false
> +#define do_hsv(ctx, a, func)  false
>  #else
> -    decode_save_opc(ctx);
> -    if (check_access(ctx)) {
> -        TCGv dest = dest_gpr(ctx, a->rd);
> -        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
> -        tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
> -        gen_set_gpr(ctx, a->rd, dest);
> -    }
> -    return true;
> -#endif
> +static void gen_helper_hyp_hlv_b(TCGv r, TCGv_env e, TCGv a)
> +{
> +    gen_helper_hyp_hlv_bu(r, e, a);
> +    tcg_gen_ext8s_tl(r, r);
>  }
>
> +static void gen_helper_hyp_hlv_h(TCGv r, TCGv_env e, TCGv a)
> +{
> +    gen_helper_hyp_hlv_hu(r, e, a);
> +    tcg_gen_ext16s_tl(r, r);
> +}
> +
> +static void gen_helper_hyp_hlv_w(TCGv r, TCGv_env e, TCGv a)
> +{
> +    gen_helper_hyp_hlv_wu(r, e, a);
> +    tcg_gen_ext32s_tl(r, r);
> +}
> +
> +static bool do_hlv(DisasContext *ctx, arg_r2 *a,
> +                   void (*func)(TCGv, TCGv_env, TCGv))
> +{
> +    TCGv dest = dest_gpr(ctx, a->rd);
> +    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> +
> +    decode_save_opc(ctx);
> +    func(dest, cpu_env, addr);
> +    gen_set_gpr(ctx, a->rd, dest);
> +    return true;
> +}
> +
> +static bool do_hsv(DisasContext *ctx, arg_r2_s *a,
> +                   void (*func)(TCGv_env, TCGv, TCGv))
> +{
> +    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> +    TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
> +
> +    decode_save_opc(ctx);
> +    func(cpu_env, addr, data);
> +    return true;
> +}
> +#endif /* CONFIG_USER_ONLY */
> +
>  static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_SB);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_b);
>  }
>
>  static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_TESW);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_h);
>  }
>
>  static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_TESL);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_w);
>  }
>
>  static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_UB);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_bu);
>  }
>
>  static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_TEUW);
> -}
> -
> -static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
> -{
> -#ifdef CONFIG_USER_ONLY
> -    return false;
> -#else
> -    decode_save_opc(ctx);
> -    if (check_access(ctx)) {
> -        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> -        TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
> -        int mem_idx = ctx->mem_idx | MMU_HYP_ACCESS_BIT;
> -        tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
> -    }
> -    return true;
> -#endif
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_hu);
>  }
>
>  static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hsv(ctx, a, MO_SB);
> +    return do_hsv(ctx, a, gen_helper_hyp_hsv_b);
>  }
>
>  static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hsv(ctx, a, MO_TESW);
> +    return do_hsv(ctx, a, gen_helper_hyp_hsv_h);
>  }
>
>  static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hsv(ctx, a, MO_TESL);
> +    return do_hsv(ctx, a, gen_helper_hyp_hsv_w);
>  }
>
>  static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
>  {
>      REQUIRE_64BIT(ctx);
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_TEUL);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_wu);
>  }
>
>  static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
>  {
>      REQUIRE_64BIT(ctx);
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hlv(ctx, a, MO_TEUQ);
> +    return do_hlv(ctx, a, gen_helper_hyp_hlv_d);
>  }
>
>  static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
>  {
>      REQUIRE_64BIT(ctx);
>      REQUIRE_EXT(ctx, RVH);
> -    return do_hsv(ctx, a, MO_TEUQ);
> +    return do_hsv(ctx, a, gen_helper_hyp_hsv_d);
>  }
>
> -#ifndef CONFIG_USER_ONLY
> -static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
> -                    void (*func)(TCGv, TCGv_env, TCGv))
> -{
> -    decode_save_opc(ctx);
> -    if (check_access(ctx)) {
> -        TCGv dest = dest_gpr(ctx, a->rd);
> -        TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
> -        func(dest, cpu_env, addr);
> -        gen_set_gpr(ctx, a->rd, dest);
> -    }
> -    return true;
> -}
> -#endif
> -
>  static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -#ifndef CONFIG_USER_ONLY
> -    return do_hlvx(ctx, a, gen_helper_hyp_hlvx_hu);
> -#else
> -    return false;
> -#endif
> +    return do_hlv(ctx, a, gen_helper_hyp_hlvx_hu);
>  }
>
>  static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
>  {
>      REQUIRE_EXT(ctx, RVH);
> -#ifndef CONFIG_USER_ONLY
> -    return do_hlvx(ctx, a, gen_helper_hyp_hlvx_wu);
> -#else
> -    return false;
> -#endif
> +    return do_hlv(ctx, a, gen_helper_hyp_hlvx_wu);
>  }
>
>  static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
  2023-03-25 10:54 ` [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT Richard Henderson
@ 2023-04-11  3:36   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:36 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We will enable more uses of this bit in the future.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/internals.h  | 6 ++++--
>  target/riscv/cpu_helper.c | 2 +-
>  target/riscv/op_helper.c  | 2 +-
>  3 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index b55152a7dc..7b63c0f1b6 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -27,13 +27,15 @@
>   *  - S                 0b001
>   *  - S+SUM             0b010
>   *  - M                 0b011
> - *  - HLV/HLVX/HSV adds 0b100
> + *  - U+2STAGE          0b100
> + *  - S+2STAGE          0b101
> + *  - S+SUM+2STAGE      0b110
>   */
>  #define MMUIdx_U            0
>  #define MMUIdx_S            1
>  #define MMUIdx_S_SUM        2
>  #define MMUIdx_M            3
> -#define MMU_HYP_ACCESS_BIT  (1 << 2)
> +#define MMU_2STAGE_BIT      (1 << 2)
>
>  /* share data between vector helpers and decode code */
>  FIELD(VDATA, VM, 0, 1)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 9bb84be4e1..888f7ae0ef 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -605,7 +605,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
>
>  bool riscv_cpu_two_stage_lookup(int mmu_idx)
>  {
> -    return mmu_idx & MMU_HYP_ACCESS_BIT;
> +    return mmu_idx & MMU_2STAGE_BIT;
>  }
>
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 0f81645adf..81362537b6 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -437,7 +437,7 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
>      }
>
> -    return cpu_mmu_index(env, x) | MMU_HYP_ACCESS_BIT;
> +    return cpu_mmu_index(env, x) | MMU_2STAGE_BIT;
>  }
>
>  target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum
  2023-03-25 10:54 ` [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum Richard Henderson
@ 2023-04-11  3:39   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:39 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:55 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> In get_physical_address, we should use the setting passed
> via mmu_idx rather than checking env->mstatus directly.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/internals.h  | 5 +++++
>  target/riscv/cpu_helper.c | 2 +-
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 7b63c0f1b6..0b61f337dd 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -37,6 +37,11 @@
>  #define MMUIdx_M            3
>  #define MMU_2STAGE_BIT      (1 << 2)
>
> +static inline bool mmuidx_sum(int mmu_idx)
> +{
> +    return (mmu_idx & 3) == MMUIdx_S_SUM;
> +}
> +
>  /* share data between vector helpers and decode code */
>  FIELD(VDATA, VM, 0, 1)
>  FIELD(VDATA, LMUL, 1, 3)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 888f7ae0ef..7e6cd8e0fd 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -852,7 +852,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          widened = 2;
>      }
>      /* status.SUM will be ignored if execute on background */
> -    sum = get_field(env->mstatus, MSTATUS_SUM) || use_background || is_debug;
> +    sum = mmuidx_sum(mmu_idx) || use_background || is_debug;
>      switch (vm) {
>      case VM_1_10_SV32:
>        levels = 2; ptidxbits = 10; ptesize = 4; break;
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv
  2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
  2023-03-27  2:07   ` LIU Zhiwei
@ 2023-04-11  3:53   ` Alistair Francis
  1 sibling, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:53 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:53 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Use the priv level encoded into the mmu_idx, rather than
> starting from env->priv.  We have already checked MPRV+MPP
> in riscv_cpu_mmu_index -- no need to repeat that.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/internals.h  | 9 +++++++++
>  target/riscv/cpu_helper.c | 6 +-----
>  2 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 0b61f337dd..4aa1cb409f 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -37,6 +37,15 @@
>  #define MMUIdx_M            3
>  #define MMU_2STAGE_BIT      (1 << 2)
>
> +static inline int mmuidx_priv(int mmu_idx)
> +{
> +    int ret = mmu_idx & 3;
> +    if (ret == MMUIdx_S_SUM) {
> +        ret = PRV_S;
> +    }
> +    return ret;
> +}
> +
>  static inline bool mmuidx_sum(int mmu_idx)
>  {
>      return (mmu_idx & 3) == MMUIdx_S_SUM;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 7e6cd8e0fd..cb260b88ea 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -771,7 +771,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>       * (riscv_cpu_do_interrupt) is correct */
>      MemTxResult res;
>      MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
> -    int mode = env->priv;
> +    int mode = mmuidx_priv(mmu_idx);
>      bool use_background = false;
>      hwaddr ppn;
>      RISCVCPU *cpu = env_archcpu(env);
> @@ -793,10 +793,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>         instructions, HLV, HLVX, and HSV. */
>      if (riscv_cpu_two_stage_lookup(mmu_idx)) {
>          mode = get_field(env->hstatus, HSTATUS_SPVP);
> -    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
> -        if (get_field(env->mstatus, MSTATUS_MPRV)) {
> -            mode = get_field(env->mstatus, MSTATUS_MPP);
> -        }
>      }
>
>      if (first_stage == false) {
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage
  2023-03-25 10:54 ` [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage Richard Henderson
@ 2023-04-11  3:55   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:55 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:53 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Move and rename riscv_cpu_two_stage_lookup, to match
> the other mmuidx_* functions.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h        |  1 -
>  target/riscv/internals.h  |  5 +++++
>  target/riscv/cpu_helper.c | 17 ++++++-----------
>  3 files changed, 11 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index f03ff1f10c..b6bcfb3834 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -586,7 +586,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
>  bool riscv_cpu_vector_enabled(CPURISCVState *env);
>  bool riscv_cpu_virt_enabled(CPURISCVState *env);
>  void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
> -bool riscv_cpu_two_stage_lookup(int mmu_idx);
>  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
>  G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>                                                 MMUAccessType access_type, int mmu_idx,
> diff --git a/target/riscv/internals.h b/target/riscv/internals.h
> index 4aa1cb409f..b5f823c7ec 100644
> --- a/target/riscv/internals.h
> +++ b/target/riscv/internals.h
> @@ -51,6 +51,11 @@ static inline bool mmuidx_sum(int mmu_idx)
>      return (mmu_idx & 3) == MMUIdx_S_SUM;
>  }
>
> +static inline bool mmuidx_2stage(int mmu_idx)
> +{
> +    return mmu_idx & MMU_2STAGE_BIT;
> +}
> +
>  /* share data between vector helpers and decode code */
>  FIELD(VDATA, VM, 0, 1)
>  FIELD(VDATA, LMUL, 1, 3)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index cb260b88ea..8a124888cd 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -603,11 +603,6 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
>      }
>  }
>
> -bool riscv_cpu_two_stage_lookup(int mmu_idx)
> -{
> -    return mmu_idx & MMU_2STAGE_BIT;
> -}
> -
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
>  {
>      CPURISCVState *env = &cpu->env;
> @@ -791,7 +786,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>
>      /* MPRV does not affect the virtual-machine load/store
>         instructions, HLV, HLVX, and HSV. */
> -    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
> +    if (mmuidx_2stage(mmu_idx)) {
>          mode = get_field(env->hstatus, HSTATUS_SPVP);
>      }
>
> @@ -1177,7 +1172,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
>
>      env->badaddr = addr;
>      env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> -                            riscv_cpu_two_stage_lookup(mmu_idx);
> +                            mmuidx_2stage(mmu_idx);
>      env->two_stage_indirect_lookup = false;
>      cpu_loop_exit_restore(cs, retaddr);
>  }
> @@ -1203,7 +1198,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>      }
>      env->badaddr = addr;
>      env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> -                            riscv_cpu_two_stage_lookup(mmu_idx);
> +                            mmuidx_2stage(mmu_idx);
>      env->two_stage_indirect_lookup = false;
>      cpu_loop_exit_restore(cs, retaddr);
>  }
> @@ -1255,7 +1250,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>
>      /* MPRV does not affect the virtual-machine load/store
>         instructions, HLV, HLVX, and HSV. */
> -    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
> +    if (mmuidx_2stage(mmu_idx)) {
>          mode = get_field(env->hstatus, HSTATUS_SPVP);
>      } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
>                 get_field(env->mstatus, MSTATUS_MPRV)) {
> @@ -1267,7 +1262,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>
>      pmu_tlb_fill_incr_ctr(cpu, access_type);
>      if (riscv_cpu_virt_enabled(env) ||
> -        ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
> +        ((mmuidx_2stage(mmu_idx) || two_stage_lookup) &&
>           access_type != MMU_INST_FETCH)) {
>          /* Two stage lookup */
>          ret = get_physical_address(env, &pa, &prot, address,
> @@ -1365,7 +1360,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>          raise_mmu_exception(env, address, access_type, pmp_violation,
>                              first_stage_error,
>                              riscv_cpu_virt_enabled(env) ||
> -                                riscv_cpu_two_stage_lookup(mmu_idx),
> +                                mmuidx_2stage(mmu_idx),
>                              two_stage_indirect_error);
>          cpu_loop_exit_restore(cs, retaddr);
>      }
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv
  2023-03-25 10:54 ` [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv Richard Henderson
@ 2023-04-11  3:56   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  3:56 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The current cpu_mmu_index value is really irrelevant to
> the HLV/HSV lookup.  Provide the correct priv level directly.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 8 +-------
>  target/riscv/op_helper.c  | 2 +-
>  2 files changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 8a124888cd..0adfd4a12b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -784,12 +784,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          use_background = true;
>      }
>
> -    /* MPRV does not affect the virtual-machine load/store
> -       instructions, HLV, HLVX, and HSV. */
> -    if (mmuidx_2stage(mmu_idx)) {
> -        mode = get_field(env->hstatus, HSTATUS_SPVP);
> -    }
> -
>      if (first_stage == false) {
>          /* We are in stage 2 translation, this is similar to stage 1. */
>          /* Stage 2 is always taken as U-mode */
> @@ -1251,7 +1245,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      /* MPRV does not affect the virtual-machine load/store
>         instructions, HLV, HLVX, and HSV. */
>      if (mmuidx_2stage(mmu_idx)) {
> -        mode = get_field(env->hstatus, HSTATUS_SPVP);
> +        ;
>      } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
>                 get_field(env->mstatus, MSTATUS_MPRV)) {
>          mode = get_field(env->mstatus, MSTATUS_MPP);
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index 81362537b6..db7252e09d 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -437,7 +437,7 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
>      }
>
> -    return cpu_mmu_index(env, x) | MMU_2STAGE_BIT;
> +    return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT;
>  }
>
>  target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
  2023-03-25 10:54 ` [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index Richard Henderson
@ 2023-04-11  4:02   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:02 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Incorporate the virt_enabled and MPV checks into the cpu_mmu_index
> function, so we don't have to keep doing it within tlb_fill and
> subroutines.  This also elides a flush on changes to MPV.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 50 +++++++++++++--------------------------
>  target/riscv/csr.c        |  6 +----
>  2 files changed, 18 insertions(+), 38 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 0adfd4a12b..6c42f9c6fd 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -37,19 +37,21 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  #ifdef CONFIG_USER_ONLY
>      return 0;
>  #else
> -    if (ifetch) {
> -        return env->priv;
> -    }
> +    bool virt = riscv_cpu_virt_enabled(env);
> +    int mode = env->priv;
>
>      /* All priv -> mmu_idx mapping are here */
> -    int mode = env->priv;
> -    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> -        mode = get_field(env->mstatus, MSTATUS_MPP);
> +    if (!ifetch) {
> +        if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> +            mode = get_field(env->mstatus, MSTATUS_MPP);
> +            virt = get_field(env->mstatus, MSTATUS_MPV);
> +        }
> +        if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
> +            mode = MMUIdx_S_SUM;
> +        }
>      }
> -    if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
> -        return MMUIdx_S_SUM;
> -    }
> -    return mode;
> +
> +    return mode | (virt ? MMU_2STAGE_BIT : 0);
>  #endif
>  }
>
> @@ -1165,8 +1167,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
>      }
>
>      env->badaddr = addr;
> -    env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> -                            mmuidx_2stage(mmu_idx);
> +    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
>      env->two_stage_indirect_lookup = false;
>      cpu_loop_exit_restore(cs, retaddr);
>  }
> @@ -1191,8 +1192,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>          g_assert_not_reached();
>      }
>      env->badaddr = addr;
> -    env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> -                            mmuidx_2stage(mmu_idx);
> +    env->two_stage_lookup = mmuidx_2stage(mmu_idx);
>      env->two_stage_indirect_lookup = false;
>      cpu_loop_exit_restore(cs, retaddr);
>  }
> @@ -1230,7 +1230,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      int prot, prot2, prot_pmp;
>      bool pmp_violation = false;
>      bool first_stage_error = true;
> -    bool two_stage_lookup = false;
> +    bool two_stage_lookup = mmuidx_2stage(mmu_idx);
>      bool two_stage_indirect_error = false;
>      int ret = TRANSLATE_FAIL;
>      int mode = mmu_idx;
> @@ -1242,22 +1242,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>      qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
>                    __func__, address, access_type, mmu_idx);
>
> -    /* MPRV does not affect the virtual-machine load/store
> -       instructions, HLV, HLVX, and HSV. */
> -    if (mmuidx_2stage(mmu_idx)) {
> -        ;
> -    } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
> -               get_field(env->mstatus, MSTATUS_MPRV)) {
> -        mode = get_field(env->mstatus, MSTATUS_MPP);
> -        if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) {
> -            two_stage_lookup = true;
> -        }
> -    }
> -
>      pmu_tlb_fill_incr_ctr(cpu, access_type);
> -    if (riscv_cpu_virt_enabled(env) ||
> -        ((mmuidx_2stage(mmu_idx) || two_stage_lookup) &&
> -         access_type != MMU_INST_FETCH)) {
> +    if (two_stage_lookup) {
>          /* Two stage lookup */
>          ret = get_physical_address(env, &pa, &prot, address,
>                                     &env->guest_phys_fault_addr, access_type,
> @@ -1352,9 +1338,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>          return false;
>      } else {
>          raise_mmu_exception(env, address, access_type, pmp_violation,
> -                            first_stage_error,
> -                            riscv_cpu_virt_enabled(env) ||
> -                                mmuidx_2stage(mmu_idx),
> +                            first_stage_error, two_stage_lookup,
>                              two_stage_indirect_error);
>          cpu_loop_exit_restore(cs, retaddr);
>      }
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index b79758a606..1b635373c6 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1246,7 +1246,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
>      RISCVMXL xl = riscv_cpu_mxl(env);
>
>      /* flush tlb on mstatus fields that affect VM */
> -    if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPV)) {
> +    if ((val ^ mstatus) & MSTATUS_MXR) {
>          tlb_flush(env_cpu(env));
>      }
>      mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
> @@ -1294,10 +1294,6 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
>      uint64_t valh = (uint64_t)val << 32;
>      uint64_t mask = MSTATUS_MPV | MSTATUS_GVA;
>
> -    if ((valh ^ env->mstatus) & (MSTATUS_MPV)) {
> -        tlb_flush(env_cpu(env));
> -    }
> -
>      env->mstatus = (env->mstatus & ~mask) | (valh & mask);
>
>      return RISCV_EXCP_NONE;
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 17/25] target/riscv: Check SUM in the correct register
  2023-03-25 10:54 ` [PATCH v6 17/25] target/riscv: Check SUM in the correct register Richard Henderson
@ 2023-04-11  4:25   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:25 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:42 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Table 9.5 "Effect of MPRV..." specifies that MPV=1 uses VS-level
> vsstatus.SUM instead of HS-level sstatus.SUM.
>
> For HLV/HSV instructions, the HS-level register does not apply, but
> the VS-level register presumably does, though this is not mentioned
> explicitly in the manual.  However, it matches the behavior for MPV.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 12 ++++++++----
>  target/riscv/op_helper.c  |  6 +++++-
>  2 files changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6c42f9c6fd..0017ecbf37 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -42,11 +42,16 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>
>      /* All priv -> mmu_idx mapping are here */
>      if (!ifetch) {
> -        if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> +        uint64_t status = env->mstatus;
> +
> +        if (mode == PRV_M && get_field(status, MSTATUS_MPRV)) {
>              mode = get_field(env->mstatus, MSTATUS_MPP);
>              virt = get_field(env->mstatus, MSTATUS_MPV);
> +            if (virt) {
> +                status = env->vsstatus;
> +            }
>          }
> -        if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
> +        if (mode == PRV_S && get_field(status, MSTATUS_SUM)) {
>              mode = MMUIdx_S_SUM;
>          }
>      }
> @@ -838,8 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          }
>          widened = 2;
>      }
> -    /* status.SUM will be ignored if execute on background */
> -    sum = mmuidx_sum(mmu_idx) || use_background || is_debug;
> +    sum = mmuidx_sum(mmu_idx) || is_debug;
>      switch (vm) {
>      case VM_1_10_SV32:
>        levels = 2; ptidxbits = 10; ptesize = 4; break;
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index db7252e09d..93d4ae8b3e 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -437,7 +437,11 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
>          riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
>      }
>
> -    return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT;
> +    int mode = get_field(env->hstatus, HSTATUS_SPVP);
> +    if (!x && mode == PRV_S && get_field(env->vsstatus, MSTATUS_SUM)) {
> +        mode = MMUIdx_S_SUM;
> +    }
> +    return mode | MMU_2STAGE_BIT;
>  }
>
>  target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers
  2023-03-25 10:54 ` [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers Richard Henderson
@ 2023-04-11  4:25   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:25 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:29 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Move the check from the top of get_physical_address to
> the two callers, where passing mmu_idx makes no sense.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 0017ecbf37..833ea6d3fa 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -791,12 +791,6 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          use_background = true;
>      }
>
> -    if (first_stage == false) {
> -        /* We are in stage 2 translation, this is similar to stage 1. */
> -        /* Stage 2 is always taken as U-mode */
> -        mode = PRV_U;
> -    }
> -
>      if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
>          *physical = addr;
>          *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> @@ -902,7 +896,7 @@ restart:
>              /* Do the second stage translation on the base PTE address. */
>              int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
>                                                   base, NULL, MMU_DATA_LOAD,
> -                                                 mmu_idx, false, true,
> +                                                 MMUIdx_U, false, true,
>                                                   is_debug);
>
>              if (vbase_ret != TRANSLATE_SUCCESS) {
> @@ -1274,7 +1268,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>              im_address = pa;
>
>              ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
> -                                       access_type, mmu_idx, false, true,
> +                                       access_type, MMUIdx_U, false, true,
>                                         false);
>
>              qemu_log_mask(CPU_LOG_MMU,
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop
  2023-03-25 10:54 ` [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop Richard Henderson
@ 2023-04-11  4:26   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:26 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:56 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> These values are constant for every level of pte lookup.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 833ea6d3fa..00f70a3dd5 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -870,6 +870,14 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          return TRANSLATE_FAIL;
>      }
>
> +    bool pbmte = env->menvcfg & MENVCFG_PBMTE;
> +    bool hade = env->menvcfg & MENVCFG_HADE;
> +
> +    if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
> +        pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
> +        hade = hade && (env->henvcfg & HENVCFG_HADE);
> +    }
> +
>      int ptshift = (levels - 1) * ptidxbits;
>      int i;
>
> @@ -930,14 +938,6 @@ restart:
>              return TRANSLATE_FAIL;
>          }
>
> -        bool pbmte = env->menvcfg & MENVCFG_PBMTE;
> -        bool hade = env->menvcfg & MENVCFG_HADE;
> -
> -        if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
> -            pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
> -            hade = hade && (env->henvcfg & HENVCFG_HADE);
> -        }
> -
>          if (riscv_cpu_sxl(env) == MXL_RV32) {
>              ppn = pte >> PTE_PPN_SHIFT;
>          } else if (pbmte || cpu->cfg.ext_svnapot) {
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 20/25] target/riscv: Move leaf pte processing out of level loop
  2023-03-25 10:54 ` [PATCH v6 20/25] target/riscv: Move leaf pte processing out of " Richard Henderson
@ 2023-04-11  4:30   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:30 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sun, Mar 26, 2023 at 2:03 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Move the code that never loops outside of the loop.
> Unchain the if-return-else statements.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 234 +++++++++++++++++++++-----------------
>  1 file changed, 127 insertions(+), 107 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 00f70a3dd5..ce12dcec1d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -879,6 +879,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      }
>
>      int ptshift = (levels - 1) * ptidxbits;
> +    target_ulong pte;
> +    hwaddr pte_addr;
>      int i;
>
>  #if !TCG_OVERSIZED_GUEST
> @@ -895,7 +897,6 @@ restart:
>          }
>
>          /* check that physical address of PTE is legal */
> -        hwaddr pte_addr;
>
>          if (two_stage && first_stage) {
>              int vbase_prot;
> @@ -927,7 +928,6 @@ restart:
>              return TRANSLATE_PMP_FAIL;
>          }
>
> -        target_ulong pte;
>          if (riscv_cpu_mxl(env) == MXL_RV32) {
>              pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
>          } else {
> @@ -952,120 +952,140 @@ restart:
>          if (!(pte & PTE_V)) {
>              /* Invalid PTE */
>              return TRANSLATE_FAIL;
> -        } else if (!pbmte && (pte & PTE_PBMT)) {
> +        }
> +        if (pte & (PTE_R | PTE_W | PTE_X)) {
> +            goto leaf;
> +        }
> +
> +        /* Inner PTE, continue walking */
> +        if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
>              return TRANSLATE_FAIL;
> -        } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
> -            /* Inner PTE, continue walking */
> -            if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
> -                return TRANSLATE_FAIL;
> -            }
> -            base = ppn << PGSHIFT;
> -        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
> -            /* Reserved leaf PTE flags: PTE_W */
> -            return TRANSLATE_FAIL;
> -        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
> -            /* Reserved leaf PTE flags: PTE_W + PTE_X */
> -            return TRANSLATE_FAIL;
> -        } else if ((pte & PTE_U) && ((mode != PRV_U) &&
> -                   (!sum || access_type == MMU_INST_FETCH))) {
> -            /* User PTE flags when not U mode and mstatus.SUM is not set,
> -               or the access type is an instruction fetch */
> -            return TRANSLATE_FAIL;
> -        } else if (!(pte & PTE_U) && (mode != PRV_S)) {
> -            /* Supervisor PTE flags when not S mode */
> -            return TRANSLATE_FAIL;
> -        } else if (ppn & ((1ULL << ptshift) - 1)) {
> -            /* Misaligned PPN */
> -            return TRANSLATE_FAIL;
> -        } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
> -                   ((pte & PTE_X) && mxr))) {
> -            /* Read access check failed */
> -            return TRANSLATE_FAIL;
> -        } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
> -            /* Write access check failed */
> -            return TRANSLATE_FAIL;
> -        } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
> -            /* Fetch access check failed */
> -            return TRANSLATE_FAIL;
> -        } else {
> -            /* if necessary, set accessed and dirty bits. */
> -            target_ulong updated_pte = pte | PTE_A |
> +        }
> +        base = ppn << PGSHIFT;
> +    }
> +
> +    /* No leaf pte at any translation level. */
> +    return TRANSLATE_FAIL;
> +
> + leaf:
> +    if (ppn & ((1ULL << ptshift) - 1)) {
> +        /* Misaligned PPN */
> +        return TRANSLATE_FAIL;
> +    }
> +    if (!pbmte && (pte & PTE_PBMT)) {
> +        /* Reserved without Svpbmt. */
> +        return TRANSLATE_FAIL;
> +    }
> +    if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
> +        /* Reserved leaf PTE flags: PTE_W */
> +        return TRANSLATE_FAIL;
> +    }
> +    if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
> +        /* Reserved leaf PTE flags: PTE_W + PTE_X */
> +        return TRANSLATE_FAIL;
> +    }
> +    if ((pte & PTE_U) &&
> +        ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
> +        /*
> +         * User PTE flags when not U mode and mstatus.SUM is not set,
> +         * or the access type is an instruction fetch.
> +         */
> +        return TRANSLATE_FAIL;
> +    }
> +    if (!(pte & PTE_U) && (mode != PRV_S)) {
> +        /* Supervisor PTE flags when not S mode */
> +        return TRANSLATE_FAIL;
> +    }
> +    if (access_type == MMU_DATA_LOAD &&
> +        !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
> +        /* Read access check failed */
> +        return TRANSLATE_FAIL;
> +    }
> +    if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
> +        /* Write access check failed */
> +        return TRANSLATE_FAIL;
> +    }
> +    if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
> +        /* Fetch access check failed */
> +        return TRANSLATE_FAIL;
> +    }
> +
> +    /* If necessary, set accessed and dirty bits. */
> +    target_ulong updated_pte = pte | PTE_A |
>                  (access_type == MMU_DATA_STORE ? PTE_D : 0);
>
> -            /* Page table updates need to be atomic with MTTCG enabled */
> -            if (updated_pte != pte) {
> -                if (!hade) {
> -                    return TRANSLATE_FAIL;
> -                }
> +    /* Page table updates need to be atomic with MTTCG enabled */
> +    if (updated_pte != pte) {
> +        if (!hade) {
> +            return TRANSLATE_FAIL;
> +        }
>
> -                /*
> -                 * - if accessed or dirty bits need updating, and the PTE is
> -                 *   in RAM, then we do so atomically with a compare and swap.
> -                 * - if the PTE is in IO space or ROM, then it can't be updated
> -                 *   and we return TRANSLATE_FAIL.
> -                 * - if the PTE changed by the time we went to update it, then
> -                 *   it is no longer valid and we must re-walk the page table.
> -                 */
> -                MemoryRegion *mr;
> -                hwaddr l = sizeof(target_ulong), addr1;
> -                mr = address_space_translate(cs->as, pte_addr,
> -                    &addr1, &l, false, MEMTXATTRS_UNSPECIFIED);
> -                if (memory_region_is_ram(mr)) {
> -                    target_ulong *pte_pa =
> -                        qemu_map_ram_ptr(mr->ram_block, addr1);
> +        /*
> +         * - if accessed or dirty bits need updating, and the PTE is
> +         *   in RAM, then we do so atomically with a compare and swap.
> +         * - if the PTE is in IO space or ROM, then it can't be updated
> +         *   and we return TRANSLATE_FAIL.
> +         * - if the PTE changed by the time we went to update it, then
> +         *   it is no longer valid and we must re-walk the page table.
> +         */
> +        MemoryRegion *mr;
> +        hwaddr l = sizeof(target_ulong), addr1;
> +        mr = address_space_translate(cs->as, pte_addr, &addr1, &l, false,
> +                                     MEMTXATTRS_UNSPECIFIED);
> +        if (memory_region_is_ram(mr)) {
> +            target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
>  #if TCG_OVERSIZED_GUEST
> -                    /* MTTCG is not enabled on oversized TCG guests so
> -                     * page table updates do not need to be atomic */
> -                    *pte_pa = pte = updated_pte;
> +            /*
> +             * MTTCG is not enabled on oversized TCG guests so
> +             * page table updates do not need to be atomic.
> +             */
> +            *pte_pa = pte = updated_pte;
>  #else
> -                    target_ulong old_pte =
> -                        qatomic_cmpxchg(pte_pa, pte, updated_pte);
> -                    if (old_pte != pte) {
> -                        goto restart;
> -                    } else {
> -                        pte = updated_pte;
> -                    }
> +            target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
> +            if (old_pte != pte) {
> +                goto restart;
> +            }
> +            pte = updated_pte;
>  #endif
> -                } else {
> -                    /* misconfigured PTE in ROM (AD bits are not preset) or
> -                     * PTE is in IO space and can't be updated atomically */
> -                    return TRANSLATE_FAIL;
> -                }
> -            }
> -
> -            /* for superpage mappings, make a fake leaf PTE for the TLB's
> -               benefit. */
> -            target_ulong vpn = addr >> PGSHIFT;
> -
> -            if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
> -                napot_bits = ctzl(ppn) + 1;
> -                if ((i != (levels - 1)) || (napot_bits != 4)) {
> -                    return TRANSLATE_FAIL;
> -                }
> -            }
> -
> -            napot_mask = (1 << napot_bits) - 1;
> -            *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
> -                          (vpn & (((target_ulong)1 << ptshift) - 1))
> -                         ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
> -
> -            /* set permissions on the TLB entry */
> -            if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
> -                *prot |= PAGE_READ;
> -            }
> -            if ((pte & PTE_X)) {
> -                *prot |= PAGE_EXEC;
> -            }
> -            /* add write permission on stores or if the page is already dirty,
> -               so that we TLB miss on later writes to update the dirty bit */
> -            if ((pte & PTE_W) &&
> -                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> -                *prot |= PAGE_WRITE;
> -            }
> -            return TRANSLATE_SUCCESS;
> +        } else {
> +            /*
> +             * Misconfigured PTE in ROM (AD bits are not preset) or
> +             * PTE is in IO space and can't be updated atomically.
> +             */
> +            return TRANSLATE_FAIL;
>          }
>      }
> -    return TRANSLATE_FAIL;
> +
> +    /* For superpage mappings, make a fake leaf PTE for the TLB's benefit. */
> +    target_ulong vpn = addr >> PGSHIFT;
> +
> +    if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
> +        napot_bits = ctzl(ppn) + 1;
> +        if ((i != (levels - 1)) || (napot_bits != 4)) {
> +            return TRANSLATE_FAIL;
> +        }
> +    }
> +
> +    napot_mask = (1 << napot_bits) - 1;
> +    *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
> +                  (vpn & (((target_ulong)1 << ptshift) - 1))
> +                 ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
> +
> +    /* set permissions on the TLB entry */
> +    if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
> +        *prot |= PAGE_READ;
> +    }
> +    if (pte & PTE_X) {
> +        *prot |= PAGE_EXEC;
> +    }
> +    /*
> +     * Add write permission on stores or if the page is already dirty,
> +     * so that we TLB miss on later writes to update the dirty bit.
> +     */
> +    if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> +        *prot |= PAGE_WRITE;
> +    }
> +    return TRANSLATE_SUCCESS;
>  }
>
>  static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug
  2023-03-25 10:54 ` [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug Richard Henderson
@ 2023-04-11  4:30   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:30 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:56 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The debugger should not modify PTE_A or PTE_D.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index ce12dcec1d..b26840e46c 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1015,7 +1015,7 @@ restart:
>                  (access_type == MMU_DATA_STORE ? PTE_D : 0);
>
>      /* Page table updates need to be atomic with MTTCG enabled */
> -    if (updated_pte != pte) {
> +    if (updated_pte != pte && !is_debug) {
>          if (!hade) {
>              return TRANSLATE_FAIL;
>          }
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 22/25] target/riscv: Don't modify SUM with is_debug
  2023-03-25 10:54 ` [PATCH v6 22/25] target/riscv: Don't modify SUM " Richard Henderson
@ 2023-04-11  4:31   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:31 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:55 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> If we want to give the debugger a greater view of memory than
> the cpu, we should simply disable the access check entirely,
> not simply for this one corner case.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index b26840e46c..850817edfd 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -837,7 +837,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          }
>          widened = 2;
>      }
> -    sum = mmuidx_sum(mmu_idx) || is_debug;
> +    sum = mmuidx_sum(mmu_idx);
>      switch (vm) {
>      case VM_1_10_SV32:
>        levels = 2; ptidxbits = 10; ptesize = 4; break;
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags
  2023-03-25 10:54 ` [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags Richard Henderson
@ 2023-04-11  4:32   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:32 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:35 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 850817edfd..82a7c5f9dd 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -976,14 +976,14 @@ restart:
>          /* Reserved without Svpbmt. */
>          return TRANSLATE_FAIL;
>      }
> -    if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
> -        /* Reserved leaf PTE flags: PTE_W */
> -        return TRANSLATE_FAIL;
> -    }
> -    if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
> -        /* Reserved leaf PTE flags: PTE_W + PTE_X */
> +
> +    /* Check for reserved combinations of RWX flags. */
> +    switch (pte & (PTE_R | PTE_W | PTE_X)) {
> +    case PTE_W:
> +    case PTE_W | PTE_X:
>          return TRANSLATE_FAIL;
>      }
> +
>      if ((pte & PTE_U) &&
>          ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
>          /*
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address
  2023-03-25 10:54 ` [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address Richard Henderson
@ 2023-04-11  4:55   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  4:55 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:51 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We were effectively computing the protection bits twice,
> once while performing access checks and once while returning
> the valid bits to the caller.  Reorg so we do this once.
>
> Move the computation of mxr close to its single use.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 69 ++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 33 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 82a7c5f9dd..725ca45106 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -762,7 +762,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
>   * @is_debug: Is this access from a debugger or the monitor?
>   */
>  static int get_physical_address(CPURISCVState *env, hwaddr *physical,
> -                                int *prot, target_ulong addr,
> +                                int *ret_prot, target_ulong addr,
>                                  target_ulong *fault_pte_addr,
>                                  int access_type, int mmu_idx,
>                                  bool first_stage, bool two_stage,
> @@ -793,20 +793,14 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>
>      if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
>          *physical = addr;
> -        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
>          return TRANSLATE_SUCCESS;
>      }
>
> -    *prot = 0;
> +    *ret_prot = 0;
>
>      hwaddr base;
> -    int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
> -
> -    if (first_stage == true) {
> -        mxr = get_field(env->mstatus, MSTATUS_MXR);
> -    } else {
> -        mxr = get_field(env->vsstatus, MSTATUS_MXR);
> -    }
> +    int levels, ptidxbits, ptesize, vm, sum, widened;
>
>      if (first_stage == true) {
>          if (use_background) {
> @@ -849,7 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>        levels = 5; ptidxbits = 9; ptesize = 8; break;
>      case VM_1_10_MBARE:
>          *physical = addr;
> -        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +        *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
>          return TRANSLATE_SUCCESS;
>      default:
>        g_assert_not_reached();
> @@ -984,6 +978,27 @@ restart:
>          return TRANSLATE_FAIL;
>      }
>
> +    int prot = 0;
> +    if (pte & PTE_R) {
> +        prot |= PAGE_READ;
> +    }
> +    if (pte & PTE_W) {
> +        prot |= PAGE_WRITE;
> +    }
> +    if (pte & PTE_X) {
> +        bool mxr;
> +
> +        if (first_stage == true) {
> +            mxr = get_field(env->mstatus, MSTATUS_MXR);
> +        } else {
> +            mxr = get_field(env->vsstatus, MSTATUS_MXR);
> +        }
> +        if (mxr) {
> +            prot |= PAGE_READ;
> +        }
> +        prot |= PAGE_EXEC;
> +    }
> +
>      if ((pte & PTE_U) &&
>          ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
>          /*
> @@ -996,17 +1011,9 @@ restart:
>          /* Supervisor PTE flags when not S mode */
>          return TRANSLATE_FAIL;
>      }
> -    if (access_type == MMU_DATA_LOAD &&
> -        !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
> -        /* Read access check failed */
> -        return TRANSLATE_FAIL;
> -    }
> -    if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
> -        /* Write access check failed */
> -        return TRANSLATE_FAIL;
> -    }
> -    if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
> -        /* Fetch access check failed */
> +
> +    if (!((prot >> access_type) & 1)) {
> +        /* Access check failed */
>          return TRANSLATE_FAIL;
>      }
>
> @@ -1071,20 +1078,16 @@ restart:
>                    (vpn & (((target_ulong)1 << ptshift) - 1))
>                   ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
>
> -    /* set permissions on the TLB entry */
> -    if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
> -        *prot |= PAGE_READ;
> -    }
> -    if (pte & PTE_X) {
> -        *prot |= PAGE_EXEC;
> -    }
>      /*
> -     * Add write permission on stores or if the page is already dirty,
> -     * so that we TLB miss on later writes to update the dirty bit.
> +     * Remove write permission unless this is a store, or the page is
> +     * already dirty, so that we TLB miss on later writes to update
> +     * the dirty bit.
>       */
> -    if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> -        *prot |= PAGE_WRITE;
> +    if (access_type != MMU_DATA_STORE && !(pte & PTE_D)) {
> +        prot &= ~PAGE_WRITE;
>      }
> +    *ret_prot = prot;
> +
>      return TRANSLATE_SUCCESS;
>  }
>
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 25/25] target/riscv: Reorg sum check in get_physical_address
  2023-03-25 10:54 ` [PATCH v6 25/25] target/riscv: Reorg sum " Richard Henderson
@ 2023-04-11  5:36   ` Alistair Francis
  0 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  5:36 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 10:56 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Implement this by adjusting prot, which reduces the set of
> checks required.  This prevents exec to be set for U pages
> in MMUIdx_S_SUM.  While it had been technically incorrect,
> it did not manifest as a bug, because we will never attempt
> to execute from MMUIdx_S_SUM.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_helper.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 725ca45106..7336d1273b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -800,7 +800,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>      *ret_prot = 0;
>
>      hwaddr base;
> -    int levels, ptidxbits, ptesize, vm, sum, widened;
> +    int levels, ptidxbits, ptesize, vm, widened;
>
>      if (first_stage == true) {
>          if (use_background) {
> @@ -831,7 +831,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>          }
>          widened = 2;
>      }
> -    sum = mmuidx_sum(mmu_idx);
> +
>      switch (vm) {
>      case VM_1_10_SV32:
>        levels = 2; ptidxbits = 10; ptesize = 4; break;
> @@ -999,15 +999,15 @@ restart:
>          prot |= PAGE_EXEC;
>      }
>
> -    if ((pte & PTE_U) &&
> -        ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
> -        /*
> -         * User PTE flags when not U mode and mstatus.SUM is not set,
> -         * or the access type is an instruction fetch.
> -         */
> -        return TRANSLATE_FAIL;
> -    }
> -    if (!(pte & PTE_U) && (mode != PRV_S)) {
> +    if (pte & PTE_U) {
> +        if (mode != PRV_U) {
> +            if (!mmuidx_sum(mmu_idx)) {
> +                return TRANSLATE_FAIL;
> +            }
> +            /* SUM allows only read+write, not execute. */
> +            prot &= PAGE_READ | PAGE_WRITE;
> +        }
> +    } else if (mode != PRV_S) {
>          /* Supervisor PTE flags when not S mode */
>          return TRANSLATE_FAIL;
>      }
> --
> 2.34.1
>
>


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

* Re: [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups
  2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
                   ` (28 preceding siblings ...)
  2023-04-04  6:42 ` Wu, Fei
@ 2023-04-11  5:38 ` Alistair Francis
  29 siblings, 0 replies; 70+ messages in thread
From: Alistair Francis @ 2023-04-11  5:38 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-riscv, alistair.francis, palmer, zhiwei_liu, fei2.wu

On Sat, Mar 25, 2023 at 9:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This builds on Fei and Zhiwei's SUM and TB_FLAGS changes.
>
>   * Reclaim 5 TB_FLAGS bits, since we nearly ran out.
>
>   * Using cpu_mmu_index(env, true) is insufficient to implement
>     HLVX properly.  While that chooses the correct mmu_idx, it
>     does not perform the read with execute permission.
>     I add a new tcg interface to perform a read-for-execute with
>     an arbitrary mmu_idx.  This is still not 100% compliant, but
>     it's closer.
>
>   * Handle mstatus.MPV in cpu_mmu_index.
>   * Use vsstatus.SUM when required for MMUIdx_S_SUM.
>   * Cleanups for get_physical_address.
>
> While this passes check-avocado, I'm sure that's insufficient.
> Please have a close look.
>
>
> r~
>
>
> Fei Wu (2):
>   target/riscv: Separate priv from mmu_idx
>   target/riscv: Reduce overhead of MSTATUS_SUM change
>
> LIU Zhiwei (4):
>   target/riscv: Extract virt enabled state from tb flags
>   target/riscv: Add a general status enum for extensions
>   target/riscv: Encode the FS and VS on a normal way for tb flags
>   target/riscv: Add a tb flags field for vstart
>
> Richard Henderson (19):
>   target/riscv: Remove mstatus_hs_{fs,vs} from tb_flags
>   accel/tcg: Add cpu_ld*_code_mmu
>   target/riscv: Use cpu_ld*_code_mmu for HLVX
>   target/riscv: Handle HLV, HSV via helpers
>   target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT
>   target/riscv: Introduce mmuidx_sum
>   target/riscv: Introduce mmuidx_priv
>   target/riscv: Introduce mmuidx_2stage
>   target/riscv: Move hstatus.spvp check to check_access_hlsv
>   target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index
>   target/riscv: Check SUM in the correct register
>   target/riscv: Hoist second stage mode change to callers
>   target/riscv: Hoist pbmte and hade out of the level loop
>   target/riscv: Move leaf pte processing out of level loop
>   target/riscv: Suppress pte update with is_debug
>   target/riscv: Don't modify SUM with is_debug
>   target/riscv: Merge checks for reserved pte flags
>   target/riscv: Reorg access check in get_physical_address
>   target/riscv: Reorg sum check in get_physical_address

Thanks for the patches!

This has been reviewed and tested. Do you mind sending a v7 rebased on
https://github.com/alistair23/qemu/tree/riscv-to-apply.next?

Alistair

>
>  include/exec/cpu_ldst.h                       |   9 +
>  target/riscv/cpu.h                            |  47 ++-
>  target/riscv/cpu_bits.h                       |  12 +-
>  target/riscv/helper.h                         |  12 +-
>  target/riscv/internals.h                      |  35 ++
>  accel/tcg/cputlb.c                            |  48 +++
>  accel/tcg/user-exec.c                         |  58 +++
>  target/riscv/cpu.c                            |   2 +-
>  target/riscv/cpu_helper.c                     | 393 +++++++++---------
>  target/riscv/csr.c                            |  21 +-
>  target/riscv/op_helper.c                      | 113 ++++-
>  target/riscv/translate.c                      |  72 ++--
>  .../riscv/insn_trans/trans_privileged.c.inc   |   2 +-
>  target/riscv/insn_trans/trans_rvf.c.inc       |   2 +-
>  target/riscv/insn_trans/trans_rvh.c.inc       | 135 +++---
>  target/riscv/insn_trans/trans_rvv.c.inc       |  22 +-
>  target/riscv/insn_trans/trans_xthead.c.inc    |   7 +-
>  17 files changed, 595 insertions(+), 395 deletions(-)
>
> --
> 2.34.1
>
>


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

end of thread, other threads:[~2023-04-11  5:39 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
2023-04-06  2:35   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
2023-03-26 12:54   ` liweiwei
2023-04-11  2:05   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags Richard Henderson
2023-04-11  1:59   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
2023-03-27  1:34   ` liweiwei
2023-03-27 16:22     ` Richard Henderson
2023-03-28  2:34   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs,vs} " LIU Zhiwei
2023-04-11  2:02   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} " Alistair Francis
2023-03-25 10:54 ` [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart Richard Henderson
2023-04-11  2:07   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
2023-03-28  2:39   ` LIU Zhiwei
2023-04-11  2:08   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
2023-03-28  2:41   ` LIU Zhiwei
2023-04-11  2:11   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu Richard Henderson
2023-04-11  3:10   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX Richard Henderson
2023-04-11  3:12   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers Richard Henderson
2023-04-11  3:34   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT Richard Henderson
2023-04-11  3:36   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum Richard Henderson
2023-04-11  3:39   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
2023-03-27  2:07   ` LIU Zhiwei
2023-03-27 16:29     ` Richard Henderson
2023-03-28  1:33       ` LIU Zhiwei
2023-03-28  1:54         ` LIU Zhiwei
2023-03-28 14:27           ` Richard Henderson
2023-04-11  3:53   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage Richard Henderson
2023-04-11  3:55   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv Richard Henderson
2023-04-11  3:56   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index Richard Henderson
2023-04-11  4:02   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 17/25] target/riscv: Check SUM in the correct register Richard Henderson
2023-04-11  4:25   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers Richard Henderson
2023-04-11  4:25   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop Richard Henderson
2023-04-11  4:26   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 20/25] target/riscv: Move leaf pte processing out of " Richard Henderson
2023-04-11  4:30   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug Richard Henderson
2023-04-11  4:30   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 22/25] target/riscv: Don't modify SUM " Richard Henderson
2023-04-11  4:31   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags Richard Henderson
2023-04-11  4:32   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address Richard Henderson
2023-04-11  4:55   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 25/25] target/riscv: Reorg sum " Richard Henderson
2023-04-11  5:36   ` Alistair Francis
2023-03-26  5:17 ` [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
2023-03-26 14:18 ` liweiwei
2023-03-27 16:43 ` Daniel Henrique Barboza
2023-03-28  1:22   ` Wu, Fei
2023-04-04  6:42 ` Wu, Fei
2023-04-04  7:11   ` LIU Zhiwei
2023-04-04  7:23     ` Wu, Fei
2023-04-11  5:38 ` Alistair Francis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).