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