diff mbox series

[1/2] target/riscv: Add additional xlen for address when MPRV=1

Message ID 20230614032547.35895-2-liweiwei@iscas.ac.cn
State New
Headers show
Series target/riscv: Fix the xlen for data address when MPRV=1 | expand

Commit Message

Weiwei Li June 14, 2023, 3:25 a.m. UTC
As specified in privilege spec:"When MPRV=1, load and store memory
addresses are treated as though the current XLEN were set to MPP’s
XLEN". So the xlen for address may be different from current xlen.

Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
---
 target/riscv/cpu.h        | 49 +++++++++++++++++++++++++++++++++------
 target/riscv/cpu_helper.c |  1 +
 target/riscv/translate.c  | 13 ++++++++++-
 3 files changed, 55 insertions(+), 8 deletions(-)

Comments

Daniel Henrique Barboza June 14, 2023, 9:18 a.m. UTC | #1
On 6/14/23 00:25, Weiwei Li wrote:
> As specified in privilege spec:"When MPRV=1, load and store memory
> addresses are treated as though the current XLEN were set to MPP’s
> XLEN". So the xlen for address may be different from current xlen.
> 
> Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
> ---

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

>   target/riscv/cpu.h        | 49 +++++++++++++++++++++++++++++++++------
>   target/riscv/cpu_helper.c |  1 +
>   target/riscv/translate.c  | 13 ++++++++++-
>   3 files changed, 55 insertions(+), 8 deletions(-)
> 
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index e3e08d315f..cc20ee25a7 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -498,6 +498,7 @@ FIELD(TB_FLAGS, ITRIGGER, 22, 1)
>   /* Virtual mode enabled */
>   FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
>   FIELD(TB_FLAGS, PRIV, 24, 2)
> +FIELD(TB_FLAGS, AXL, 26, 2)
>   
>   #ifdef TARGET_RISCV32
>   #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
> @@ -514,13 +515,20 @@ static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
>       return &env_archcpu(env)->cfg;
>   }
>   
> -#if defined(TARGET_RISCV32)
> -#define cpu_recompute_xl(env)  ((void)(env), MXL_RV32)
> -#else
> -static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
> +#if !defined(CONFIG_USER_ONLY)
> +static inline int cpu_address_mode(CPURISCVState *env)
> +{
> +    int mode = env->priv;
> +
> +    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
> +        mode = get_field(env->mstatus, MSTATUS_MPP);
> +    }
> +    return mode;
> +}
> +
> +static inline RISCVMXL cpu_get_xl(CPURISCVState *env, target_ulong mode)
>   {
>       RISCVMXL xl = env->misa_mxl;
> -#if !defined(CONFIG_USER_ONLY)
>       /*
>        * When emulating a 32-bit-only cpu, use RV32.
>        * When emulating a 64-bit cpu, and MXL has been reduced to RV32,
> @@ -528,7 +536,7 @@ static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
>        * back to RV64 for lower privs.
>        */
>       if (xl != MXL_RV32) {
> -        switch (env->priv) {
> +        switch (mode) {
>           case PRV_M:
>               break;
>           case PRV_U:
> @@ -539,11 +547,38 @@ static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
>               break;
>           }
>       }
> -#endif
>       return xl;
>   }
>   #endif
>   
> +#if defined(TARGET_RISCV32)
> +#define cpu_recompute_xl(env)  ((void)(env), MXL_RV32)
> +#else
> +static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
> +{
> +#if !defined(CONFIG_USER_ONLY)
> +    return cpu_get_xl(env, env->priv);
> +#else
> +    return env->misa_mxl;
> +#endif
> +}
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define cpu_address_xl(env)  ((void)(env), MXL_RV32)
> +#else
> +static inline RISCVMXL cpu_address_xl(CPURISCVState *env)
> +{
> +#ifdef CONFIG_USER_ONLY
> +    return env->xl;
> +#else
> +    int mode = cpu_address_mode(env);
> +
> +    return cpu_get_xl(env, mode);
> +#endif
> +}
> +#endif
> +
>   static inline int riscv_cpu_xlen(CPURISCVState *env)
>   {
>       return 16 << env->xl;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 90cef9856d..f85113a3db 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -134,6 +134,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>       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);
> +    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
>       if (env->cur_pmmask != 0) {
>           flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
>       }
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 8a33da811e..4bf61766b6 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -64,6 +64,7 @@ typedef struct DisasContext {
>       target_ulong priv_ver;
>       RISCVMXL misa_mxl_max;
>       RISCVMXL xl;
> +    RISCVMXL address_xl;
>       uint32_t misa_ext;
>       uint32_t opcode;
>       RISCVExtStatus mstatus_fs;
> @@ -152,6 +153,14 @@ MATERIALISE_EXT_PREDICATE(XVentanaCondOps);
>   #define get_xl(ctx)    ((ctx)->xl)
>   #endif
>   
> +#ifdef TARGET_RISCV32
> +#define get_address_xl(ctx)    MXL_RV32
> +#elif defined(CONFIG_USER_ONLY)
> +#define get_address_xl(ctx)    MXL_RV64
> +#else
> +#define get_address_xl(ctx)    ((ctx)->address_xl)
> +#endif
> +
>   /* The word size for this machine mode. */
>   static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
>   {
> @@ -598,12 +607,13 @@ static TCGv get_address(DisasContext *ctx, int rs1, int imm)
>       tcg_gen_addi_tl(addr, src1, imm);
>       if (ctx->pm_mask_enabled) {
>           tcg_gen_andc_tl(addr, addr, pm_mask);
> -    } else if (get_xl(ctx) == MXL_RV32) {
> +    } else if (get_address_xl(ctx) == MXL_RV32) {
>           tcg_gen_ext32u_tl(addr, addr);
>       }
>       if (ctx->pm_base_enabled) {
>           tcg_gen_or_tl(addr, addr, pm_base);
>       }
> +
>       return addr;
>   }
>   
> @@ -1200,6 +1210,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       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);
> +    ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
>       ctx->cs = cs;
>       ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
>       ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
diff mbox series

Patch

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e3e08d315f..cc20ee25a7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -498,6 +498,7 @@  FIELD(TB_FLAGS, ITRIGGER, 22, 1)
 /* Virtual mode enabled */
 FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
 FIELD(TB_FLAGS, PRIV, 24, 2)
+FIELD(TB_FLAGS, AXL, 26, 2)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
@@ -514,13 +515,20 @@  static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
     return &env_archcpu(env)->cfg;
 }
 
-#if defined(TARGET_RISCV32)
-#define cpu_recompute_xl(env)  ((void)(env), MXL_RV32)
-#else
-static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
+#if !defined(CONFIG_USER_ONLY)
+static inline int cpu_address_mode(CPURISCVState *env)
+{
+    int mode = env->priv;
+
+    if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+        mode = get_field(env->mstatus, MSTATUS_MPP);
+    }
+    return mode;
+}
+
+static inline RISCVMXL cpu_get_xl(CPURISCVState *env, target_ulong mode)
 {
     RISCVMXL xl = env->misa_mxl;
-#if !defined(CONFIG_USER_ONLY)
     /*
      * When emulating a 32-bit-only cpu, use RV32.
      * When emulating a 64-bit cpu, and MXL has been reduced to RV32,
@@ -528,7 +536,7 @@  static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
      * back to RV64 for lower privs.
      */
     if (xl != MXL_RV32) {
-        switch (env->priv) {
+        switch (mode) {
         case PRV_M:
             break;
         case PRV_U:
@@ -539,11 +547,38 @@  static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
             break;
         }
     }
-#endif
     return xl;
 }
 #endif
 
+#if defined(TARGET_RISCV32)
+#define cpu_recompute_xl(env)  ((void)(env), MXL_RV32)
+#else
+static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    return cpu_get_xl(env, env->priv);
+#else
+    return env->misa_mxl;
+#endif
+}
+#endif
+
+#if defined(TARGET_RISCV32)
+#define cpu_address_xl(env)  ((void)(env), MXL_RV32)
+#else
+static inline RISCVMXL cpu_address_xl(CPURISCVState *env)
+{
+#ifdef CONFIG_USER_ONLY
+    return env->xl;
+#else
+    int mode = cpu_address_mode(env);
+
+    return cpu_get_xl(env, mode);
+#endif
+}
+#endif
+
 static inline int riscv_cpu_xlen(CPURISCVState *env)
 {
     return 16 << env->xl;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 90cef9856d..f85113a3db 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -134,6 +134,7 @@  void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
     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);
+    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
     if (env->cur_pmmask != 0) {
         flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1);
     }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a33da811e..4bf61766b6 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -64,6 +64,7 @@  typedef struct DisasContext {
     target_ulong priv_ver;
     RISCVMXL misa_mxl_max;
     RISCVMXL xl;
+    RISCVMXL address_xl;
     uint32_t misa_ext;
     uint32_t opcode;
     RISCVExtStatus mstatus_fs;
@@ -152,6 +153,14 @@  MATERIALISE_EXT_PREDICATE(XVentanaCondOps);
 #define get_xl(ctx)    ((ctx)->xl)
 #endif
 
+#ifdef TARGET_RISCV32
+#define get_address_xl(ctx)    MXL_RV32
+#elif defined(CONFIG_USER_ONLY)
+#define get_address_xl(ctx)    MXL_RV64
+#else
+#define get_address_xl(ctx)    ((ctx)->address_xl)
+#endif
+
 /* The word size for this machine mode. */
 static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
 {
@@ -598,12 +607,13 @@  static TCGv get_address(DisasContext *ctx, int rs1, int imm)
     tcg_gen_addi_tl(addr, src1, imm);
     if (ctx->pm_mask_enabled) {
         tcg_gen_andc_tl(addr, addr, pm_mask);
-    } else if (get_xl(ctx) == MXL_RV32) {
+    } else if (get_address_xl(ctx) == MXL_RV32) {
         tcg_gen_ext32u_tl(addr, addr);
     }
     if (ctx->pm_base_enabled) {
         tcg_gen_or_tl(addr, addr, pm_base);
     }
+
     return addr;
 }
 
@@ -1200,6 +1210,7 @@  static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     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);
+    ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
     ctx->cs = cs;
     ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
     ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);