@samitouri / QOSamiQemu / commits / 03fe8e941d

target/riscv: Fix size of priv

The priv field of CPUArchState only stores values in the range [0,3], fix to 8 bits in size and update relevant function arguments. Introduce a new privilege_mode_t typedef for passing around the privilege mode. Signed-off-by: Anton Johansson <anjo@rev.ng> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260520125406.28693-13-anjo@rev.ng> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Anton Johansson committed May 20, 2026 at 14:53 UTC 03fe8e941d8ab66f4a2be83df1ffccd8ea9fcded
10 files changed +69 -53
target/riscv/cpu.h
+17 -10
@@ -110,6 +110,12 @@ typedef struct riscv_cpu_profile {
110
111 extern RISCVCPUProfile *riscv_profiles[];
112
113 +/*
114 + * Type large enough to hold all PRV_* fields, update CPUArchState::priv
115 + * migration field if changing this type.
116 + */
117 +typedef uint8_t privilege_mode_t;
118 +
119 /* Privileged specification version */
120 #define PRIV_VER_1_10_0_STR "v1.10.0"
121 #define PRIV_VER_1_11_0_STR "v1.11.0"
@@ -266,7 +272,7 @@ struct CPUArchState {
272 uint32_t elf_flags;
273 #endif
274
269 - target_ulong priv;
275 + privilege_mode_t priv;
276 /* CSRs for execution environment configuration */
277 uint64_t menvcfg;
278 uint64_t senvcfg;
@@ -642,7 +648,7 @@ void riscv_cpu_interrupt(CPURISCVState *env);
648 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
649 void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
650 void *arg);
645 -void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
651 +void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, privilege_mode_t priv,
652 int (*rmw_fn)(void *arg,
653 target_ulong reg,
654 target_ulong *val,
@@ -653,10 +659,11 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
659 RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
660 #endif /* !CONFIG_USER_ONLY */
661
656 -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en);
662 +void riscv_cpu_set_mode(CPURISCVState *env, privilege_mode_t newpriv,
663 + bool virt_en);
664
665 void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst,
659 - enum CTRType type, target_ulong prev_priv, bool prev_virt);
666 + enum CTRType type, privilege_mode_t prev_priv, bool prev_virt);
667 void riscv_ctr_clear(CPURISCVState *env);
668
669 void riscv_translate_init(void);
@@ -724,9 +731,9 @@ static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
731 }
732
733 #if !defined(CONFIG_USER_ONLY)
727 -static inline int cpu_address_mode(CPURISCVState *env)
734 +static inline privilege_mode_t cpu_address_mode(CPURISCVState *env)
735 {
729 - int mode = env->priv;
736 + privilege_mode_t mode = env->priv;
737
738 if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
739 mode = get_field(env->mstatus, MSTATUS_MPP);
@@ -734,7 +741,7 @@ static inline int cpu_address_mode(CPURISCVState *env)
741 return mode;
742 }
743
737 -static inline RISCVMXL cpu_get_xl(CPURISCVState *env, target_ulong mode)
744 +static inline RISCVMXL cpu_get_xl(CPURISCVState *env, privilege_mode_t mode)
745 {
746 RISCVMXL xl = env->misa_mxl;
747 /*
@@ -780,7 +787,7 @@ static inline RISCVMXL cpu_address_xl(CPURISCVState *env)
787 #ifdef CONFIG_USER_ONLY
788 return env->xl;
789 #else
783 - int mode = cpu_address_mode(env);
790 + privilege_mode_t mode = cpu_address_mode(env);
791
792 return cpu_get_xl(env, mode);
793 #endif
@@ -818,9 +825,9 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
825 * Returns true if the effective privilege mode is modified.
826 */
827 static inline QEMU_ALWAYS_INLINE
821 -bool riscv_cpu_eff_priv(CPURISCVState *env, int *priv, bool *virt)
828 +bool riscv_cpu_eff_priv(CPURISCVState *env, privilege_mode_t *priv, bool *virt)
829 {
823 - int mode = env->priv;
830 + privilege_mode_t mode = env->priv;
831 bool virt_enabled = false;
832 bool mode_modified = false;
833
target/riscv/cpu_helper.c
+20 -17
@@ -44,7 +44,7 @@ int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
44 return 0;
45 #else
46 bool virt = env->virt_enabled;
47 - int mode = env->priv;
47 + privilege_mode_t mode = env->priv;
48 bool mode_modified = false;
49
50 /* All priv -> mmu_idx mapping are here */
@@ -165,7 +165,7 @@ bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt)
165 RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env)
166 {
167 #ifndef CONFIG_USER_ONLY
168 - int priv_mode;
168 + privilege_mode_t priv_mode;
169 bool virt;
170
171 riscv_cpu_eff_priv(env, &priv_mode, &virt);
@@ -217,7 +217,7 @@ RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env)
217 RISCVPmPmm riscv_pm_get_vm_ldst_pmm(CPURISCVState *env)
218 {
219 #ifndef CONFIG_USER_ONLY
220 - int priv_mode;
220 + privilege_mode_t priv_mode;
221
222 if (!riscv_cpu_cfg(env)->ext_ssnpm ||
223 get_field(env->mstatus, MSTATUS_MXR) ||
@@ -245,7 +245,7 @@ bool riscv_cpu_virt_mem_enabled(CPURISCVState *env, bool is_vm_ldst)
245 #ifndef CONFIG_USER_ONLY
246 int satp_mode = 0;
247 uint64_t satp;
248 - int priv_mode;
248 + privilege_mode_t priv_mode;
249 bool virt = false;
250
251 if (!is_vm_ldst) {
@@ -816,7 +816,7 @@ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
816 env->rdtime_fn_arg = arg;
817 }
818
819 -void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
819 +void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, privilege_mode_t priv,
820 int (*rmw_fn)(void *arg,
821 target_ulong reg,
822 target_ulong *val,
@@ -849,7 +849,7 @@ void riscv_ctr_clear(CPURISCVState *env)
849 memset(env->ctr_data, 0x0, sizeof(env->ctr_data));
850 }
851
852 -static uint64_t riscv_ctr_priv_to_mask(target_ulong priv, bool virt)
852 +static uint64_t riscv_ctr_priv_to_mask(privilege_mode_t priv, bool virt)
853 {
854 switch (priv) {
855 case PRV_M:
@@ -869,7 +869,8 @@ static uint64_t riscv_ctr_priv_to_mask(target_ulong priv, bool virt)
869 g_assert_not_reached();
870 }
871
872 -static uint64_t riscv_ctr_get_control(CPURISCVState *env, target_long priv,
872 +static uint64_t riscv_ctr_get_control(CPURISCVState *env,
873 + privilege_mode_t priv,
874 bool virt)
875 {
876 switch (priv) {
@@ -891,10 +892,11 @@ static uint64_t riscv_ctr_get_control(CPURISCVState *env, target_long priv,
892 * and src privilege is less than target privilege. This includes the virtual
893 * state as well.
894 */
894 -static bool riscv_ctr_check_xte(CPURISCVState *env, target_long src_prv,
895 +static bool riscv_ctr_check_xte(CPURISCVState *env,
896 + privilege_mode_t src_prv,
897 bool src_virt)
898 {
897 - target_long tgt_prv = env->priv;
899 + privilege_mode_t tgt_prv = env->priv;
900 bool res = true;
901
902 /*
@@ -980,7 +982,7 @@ static bool riscv_ctr_check_xte(CPURISCVState *env, target_long src_prv,
982 * idx = (sctrstatus.WRPTR - entry - 1) & (depth - 1);
983 */
984 void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst,
983 - enum CTRType type, target_ulong src_priv, bool src_virt)
985 + enum CTRType type, privilege_mode_t src_priv, bool src_virt)
986 {
987 bool tgt_virt = env->virt_enabled;
988 uint64_t src_mask = riscv_ctr_priv_to_mask(src_priv, src_virt);
@@ -1078,7 +1080,8 @@ void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst,
1080 env->sctrstatus = set_field(env->sctrstatus, SCTRSTATUS_WRPTR_MASK, head);
1081 }
1082
1081 -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
1083 +void riscv_cpu_set_mode(CPURISCVState *env, privilege_mode_t newpriv,
1084 + bool virt_en)
1085 {
1086 g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
1087
@@ -1141,7 +1144,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
1144 */
1145 static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
1146 int size, MMUAccessType access_type,
1144 - int mode)
1147 + privilege_mode_t mode)
1148 {
1149 pmp_priv_t pmp_priv;
1150 bool pmp_has_privs;
@@ -1165,7 +1168,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
1168
1169 /* Returns 'true' if a svukte address check is needed */
1170 static bool do_svukte_check(CPURISCVState *env, bool first_stage,
1168 - int mode, bool virt)
1171 + privilege_mode_t mode, bool virt)
1172 {
1173 /* Svukte extension depends on Sv39. */
1174 if (!(env_archcpu(env)->cfg.ext_svukte ||
@@ -1248,7 +1251,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
1251 */
1252 MemTxResult res;
1253 MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
1251 - int mode = mmuidx_priv(mmu_idx);
1254 + privilege_mode_t mode = mmuidx_priv(mmu_idx);
1255 bool virt = mmuidx_2stage(mmu_idx);
1256 bool use_background = false;
1257 hwaddr ppn;
@@ -1861,7 +1864,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
1864 bool two_stage_lookup = mmuidx_2stage(mmu_idx);
1865 bool two_stage_indirect_error = false;
1866 int ret = TRANSLATE_FAIL;
1864 - int mode = mmuidx_priv(mmu_idx);
1867 + privilege_mode_t mode = mmuidx_priv(mmu_idx);
1868 /* default TLB page size */
1869 hwaddr tlb_size = TARGET_PAGE_SIZE;
1870
@@ -2250,7 +2253,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
2253 bool always_storeamo = (env->excp_uw2 & RISCV_UW2_ALWAYS_STORE_AMO);
2254 bool vsmode_exc;
2255 uint64_t s;
2253 - int mode;
2256 + privilege_mode_t mode;
2257
2258 /*
2259 * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@@ -2266,7 +2269,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
2269 bool smode_double_trap = false;
2270 uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
2271 const bool prev_virt = env->virt_enabled;
2269 - const target_ulong prev_priv = env->priv;
2272 + const privilege_mode_t prev_priv = env->priv;
2273 uint64_t last_pc = env->pc;
2274 target_ulong tval = 0;
2275 target_ulong tinst = 0;
target/riscv/csr.c
+6 -4
@@ -374,7 +374,7 @@ static RISCVException aia_smode(CPURISCVState *env, int csrno)
374 static RISCVException aia_smode32(CPURISCVState *env, int csrno)
375 {
376 int ret;
377 - int csr_priv = get_field(csrno, 0x300);
377 + privilege_mode_t csr_priv = get_field(csrno, 0x300);
378
379 if (csr_priv == PRV_M && !riscv_cpu_cfg(env)->ext_smaia) {
380 return RISCV_EXCP_ILLEGAL_INST;
@@ -2671,7 +2671,8 @@ static RISCVException rmw_xireg_aia(CPURISCVState *env, int csrno,
2671 bool virt = false, isel_reserved = false;
2672 int ret = -EINVAL;
2673 uint8_t *iprio;
2674 - target_ulong priv, vgein;
2674 + privilege_mode_t priv;
2675 + uint32_t vgein;
2676
2677 /* VS-mode CSR number passed in has already been translated */
2678 switch (csrno) {
@@ -2956,7 +2957,8 @@ static RISCVException rmw_xtopei(CPURISCVState *env, int csrno,
2957 {
2958 bool virt;
2959 int ret = -EINVAL;
2959 - target_ulong priv, vgein;
2960 + privilege_mode_t priv;
2961 + uint32_t vgein;
2962
2963 /* Translate CSR number for VS-mode */
2964 csrno = aia_xlate_vs_csrno(env, csrno);
@@ -5647,7 +5649,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
5649 }
5650
5651 #if !defined(CONFIG_USER_ONLY)
5650 - int csr_priv, effective_priv = env->priv;
5652 + privilege_mode_t csr_priv, effective_priv = env->priv;
5653
5654 if (riscv_has_ext(env, RVH) && env->priv == PRV_S &&
5655 !env->virt_enabled) {
target/riscv/gdbstub.c
+1 -1
@@ -223,7 +223,7 @@ static int riscv_gdb_set_virtual(CPUState *cs, uint8_t *mem_buf, int n)
223 const unsigned regsz = riscv_cpu_is_32bit(cpu) ? 4 : 8;
224 #ifndef CONFIG_USER_ONLY
225 CPURISCVState *env = &cpu->env;
226 - uint64_t new_priv = ldn(env, mem_buf, regsz) & 0x3;
226 + privilege_mode_t new_priv = ldn(env, mem_buf, regsz) & 0x3;
227 bool new_virt = 0;
228
229 if (new_priv == PRV_RESERVED) {
target/riscv/internals.h
+2 -2
@@ -43,9 +43,9 @@
43 #define MMU_2STAGE_BIT (1 << 2)
44 #define MMU_IDX_SS_WRITE (1 << 3)
45
46 -static inline int mmuidx_priv(int mmu_idx)
46 +static inline privilege_mode_t mmuidx_priv(int mmu_idx)
47 {
48 - int ret = mmu_idx & 3;
48 + privilege_mode_t ret = mmu_idx & 3;
49 if (ret == MMUIdx_S_SUM) {
50 ret = PRV_S;
51 }
target/riscv/machine.c
+1 -1
@@ -465,7 +465,7 @@ const VMStateDescription vmstate_riscv_cpu = {
465 VMSTATE_UINT32(env.misa_ext, RISCVCPU),
466 VMSTATE_UNUSED(4),
467 VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
468 - VMSTATE_UINTTL(env.priv, RISCVCPU),
468 + VMSTATE_UINT8(env.priv, RISCVCPU),
469 VMSTATE_BOOL(env.virt_enabled, RISCVCPU),
470 VMSTATE_UINT64(env.resetvec, RISCVCPU),
471 VMSTATE_UINT64(env.mhartid, RISCVCPU),
target/riscv/op_helper.c
+14 -13
@@ -286,8 +286,9 @@ void helper_sc_probe_write(CPURISCVState *env, target_ulong addr,
286 target_ulong helper_sret(CPURISCVState *env)
287 {
288 uint64_t mstatus;
289 - target_ulong prev_priv, prev_virt = env->virt_enabled;
290 - const target_ulong src_priv = env->priv;
289 + privilege_mode_t prev_priv;
290 + bool prev_virt = env->virt_enabled;
291 + const privilege_mode_t src_priv = env->priv;
292 const bool src_virt = env->virt_enabled;
293
294 if (!(env->priv >= PRV_S)) {
@@ -339,7 +340,7 @@ target_ulong helper_sret(CPURISCVState *env)
340 /* We support Hypervisor extensions and virtulisation is disabled */
341 target_ulong hstatus = env->hstatus;
342
342 - prev_virt = get_field(hstatus, HSTATUS_SPV);
343 + prev_virt = !!(get_field(hstatus, HSTATUS_SPV));
344 hstatus = set_field(hstatus, HSTATUS_SPV, 0);
345
346 env->hstatus = hstatus;
@@ -369,7 +370,7 @@ target_ulong helper_sret(CPURISCVState *env)
370 }
371
372 static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc,
372 - target_ulong prev_priv,
373 + privilege_mode_t prev_priv,
374 uintptr_t ra)
375 {
376 if (!(env->priv >= PRV_M)) {
@@ -388,8 +389,8 @@ static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc,
389 }
390 }
391 static target_ulong ssdbltrp_mxret(CPURISCVState *env, target_ulong mstatus,
391 - target_ulong prev_priv,
392 - target_ulong prev_virt)
392 + privilege_mode_t prev_priv,
393 + bool prev_virt)
394 {
395 /* If returning to U, VS or VU, sstatus.sdt = 0 */
396 if (prev_priv == PRV_U || (prev_virt &&
@@ -408,13 +409,13 @@ target_ulong helper_mret(CPURISCVState *env)
409 {
410 target_ulong retpc = env->mepc & get_xepc_mask(env);
411 uint64_t mstatus = env->mstatus;
411 - target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
412 + privilege_mode_t prev_priv = get_field(mstatus, MSTATUS_MPP);
413 uintptr_t ra = GETPC();
414
415 check_ret_from_m_mode(env, retpc, prev_priv, ra);
416
416 - target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV) &&
417 - (prev_priv != PRV_M);
417 + bool prev_virt = !!(get_field(env->mstatus, MSTATUS_MPV) &&
418 + (prev_priv != PRV_M));
419 mstatus = set_field(mstatus, MSTATUS_MIE,
420 get_field(mstatus, MSTATUS_MPIE));
421 mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
@@ -457,14 +458,14 @@ target_ulong helper_mret(CPURISCVState *env)
458 target_ulong helper_mnret(CPURISCVState *env)
459 {
460 target_ulong retpc = env->mnepc;
460 - target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
461 - target_ulong prev_virt;
461 + privilege_mode_t prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
462 + bool prev_virt;
463 uintptr_t ra = GETPC();
464
465 check_ret_from_m_mode(env, retpc, prev_priv, ra);
466
466 - prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV) &&
467 - (prev_priv != PRV_M);
467 + prev_virt = !!(get_field(env->mnstatus, MNSTATUS_MNPV) &&
468 + (prev_priv != PRV_M));
469 env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, true);
470
471 /*
target/riscv/pmu.c
+6 -3
@@ -114,7 +114,8 @@ static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx)
114 * new priv and new virt values are passed in as arguments.
115 */
116 static void riscv_pmu_icount_update_priv(CPURISCVState *env,
117 - target_ulong newpriv, bool new_virt)
117 + privilege_mode_t newpriv,
118 + bool new_virt)
119 {
120 uint64_t *snapshot_prev, *snapshot_new;
121 uint64_t current_icount;
@@ -154,7 +155,8 @@ static void riscv_pmu_icount_update_priv(CPURISCVState *env,
155 }
156
157 static void riscv_pmu_cycle_update_priv(CPURISCVState *env,
157 - target_ulong newpriv, bool new_virt)
158 + privilege_mode_t newpriv,
159 + bool new_virt)
160 {
161 uint64_t *snapshot_prev, *snapshot_new;
162 uint64_t current_ticks;
@@ -189,7 +191,8 @@ static void riscv_pmu_cycle_update_priv(CPURISCVState *env,
191 counter_arr[env->priv] += delta;
192 }
193
192 -void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv,
194 +void riscv_pmu_update_fixed_ctrs(CPURISCVState *env,
195 + privilege_mode_t newpriv,
196 bool new_virt)
197 {
198 riscv_pmu_cycle_update_priv(env, newpriv, new_virt);
target/riscv/pmu.h
+1 -1
@@ -34,7 +34,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx);
34 void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
35 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value,
36 uint32_t ctr_idx);
37 -void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv,
37 +void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, privilege_mode_t newpriv,
38 bool new_virt);
39 RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
40 bool upper_half, uint32_t ctr_idx);
target/riscv/translate.c
+1 -1
@@ -68,7 +68,7 @@ typedef struct DisasContext {
68 RISCVExtStatus mstatus_fs;
69 RISCVExtStatus mstatus_vs;
70 uint32_t mem_idx;
71 - uint32_t priv;
71 + privilege_mode_t priv;
72 /*
73 * Remember the rounding mode encoded in the previous fp instruction,
74 * which we have already installed into env->fp_status. Or -1 for