@@ -228,7 +228,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc);
#ifndef CONFIG_USER_ONLY
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
- qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "bstatus ", env->vsstatus);
@@ -238,7 +238,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsip ",
(target_ulong)atomic_read(&env->vsip));
}
- qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", *env->mie);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsie ", env->vsie);
}
@@ -308,7 +308,7 @@ static bool riscv_cpu_has_work(CPUState *cs)
* Definition of the WFI instruction requires it to ignore the privilege
* mode and delegation registers, but respect individual enables
*/
- return (env->mip & env->mie) != 0;
+ return (env->mip & *env->mie) != 0;
#else
return true;
#endif
@@ -329,7 +329,7 @@ static void riscv_cpu_reset(CPUState *cs)
mcc->parent_reset(cs);
#ifndef CONFIG_USER_ONLY
env->priv = PRV_M;
- env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
+ *env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
env->mcause = 0;
env->pc = env->resetvec;
#endif
@@ -458,8 +458,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
static void riscv_cpu_init(Object *obj)
{
RISCVCPU *cpu = RISCV_CPU(obj);
+#ifndef CONFIG_USER_ONLY
+ CPURISCVState *env = &cpu->env;
+#endif
cpu_set_cpustate_pointers(cpu);
+
+#ifndef CONFIG_USER_ONLY
+ env->mie = &env->mie_novirt;
+ env->mstatus = &env->mstatus_novirt;
+#endif
}
static const VMStateDescription vmstate_riscv_cpu = {
@@ -122,12 +122,12 @@ struct CPURISCVState {
target_ulong resetvec;
target_ulong mhartid;
- target_ulong mstatus;
+ target_ulong *mstatus;
target_ulong mip;
uint32_t miclaim;
- target_ulong mie;
+ target_ulong *mie;
target_ulong mideleg;
target_ulong sptbr; /* until: priv-1.9.1 */
@@ -145,6 +145,14 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
+ /* The following registers are the "real" versions that the pointer
+ * versions point to. These should never be used unless you know what you
+ * are doing. To access these use the pointer versions instead. This is
+ * required to handle the Hypervisor register swapping.
+ */
+ target_ulong mie_novirt;
+ target_ulong mstatus_novirt;
+
/* Hypervisor CSRs */
target_ulong hstatus;
target_ulong hedeleg;
@@ -37,9 +37,9 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#ifndef CONFIG_USER_ONLY
static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
- target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
- target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
- target_ulong pending = env->mip & env->mie;
+ target_ulong mstatus_mie = get_field(*env->mstatus, MSTATUS_MIE);
+ target_ulong mstatus_sie = get_field(*env->mstatus, MSTATUS_SIE);
+ target_ulong pending = env->mip & *env->mie;
target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && mstatus_mie);
target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && mstatus_sie);
target_ulong irqs = (pending & ~env->mideleg & -mie) |
@@ -75,7 +75,7 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
/* Return true is floating point support is currently enabled */
bool riscv_cpu_fp_enabled(CPURISCVState *env)
{
- if (env->mstatus & MSTATUS_FS) {
+ if (*env->mstatus & MSTATUS_FS) {
return true;
}
@@ -198,8 +198,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
int mode = mmu_idx;
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
- if (get_field(env->mstatus, MSTATUS_MPRV)) {
- mode = get_field(env->mstatus, MSTATUS_MPP);
+ if (get_field(*env->mstatus, MSTATUS_MPRV)) {
+ mode = get_field(*env->mstatus, MSTATUS_MPP);
}
}
@@ -213,11 +213,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
hwaddr base;
int levels, ptidxbits, ptesize, vm, sum;
- int mxr = get_field(env->mstatus, MSTATUS_MXR);
+ int mxr = get_field(*env->mstatus, MSTATUS_MXR);
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
- sum = get_field(env->mstatus, MSTATUS_SUM);
+ sum = get_field(*env->mstatus, MSTATUS_SUM);
vm = get_field(env->satp, SATP_MODE);
switch (vm) {
case VM_1_10_SV32:
@@ -237,8 +237,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
}
} else {
base = (hwaddr)(env->sptbr) << PGSHIFT;
- sum = !get_field(env->mstatus, MSTATUS_PUM);
- vm = get_field(env->mstatus, MSTATUS_VM);
+ sum = !get_field(*env->mstatus, MSTATUS_PUM);
+ vm = get_field(*env->mstatus, MSTATUS_VM);
switch (vm) {
case VM_1_09_SV32:
levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -493,8 +493,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
- if (get_field(env->mstatus, MSTATUS_MPRV)) {
- mode = get_field(env->mstatus, MSTATUS_MPP);
+ if (get_field(*env->mstatus, MSTATUS_MPRV)) {
+ mode = get_field(*env->mstatus, MSTATUS_MPP);
}
}
@@ -607,12 +607,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
if (env->priv <= PRV_S &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
/* handle the trap in S-mode */
- target_ulong s = env->mstatus;
+ target_ulong s = *env->mstatus;
s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
s = set_field(s, MSTATUS_SPP, env->priv);
s = set_field(s, MSTATUS_SIE, 0);
- env->mstatus = s;
+ *env->mstatus = s;
env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
env->sepc = env->pc;
env->sbadaddr = tval;
@@ -621,12 +621,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
riscv_cpu_set_mode(env, PRV_S);
} else {
/* handle the trap in M-mode */
- target_ulong s = env->mstatus;
+ target_ulong s = *env->mstatus;
s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
s = set_field(s, MSTATUS_MPP, env->priv);
s = set_field(s, MSTATUS_MIE, 0);
- env->mstatus = s;
+ *env->mstatus = s;
env->mcause = cause | ~(((target_ulong)-1) >> async);
env->mepc = env->pc;
env->mbadaddr = tval;
@@ -136,7 +136,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
return -1;
}
- env->mstatus |= MSTATUS_FS;
+ *env->mstatus |= MSTATUS_FS;
#endif
riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
return 0;
@@ -159,7 +159,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
return -1;
}
- env->mstatus |= MSTATUS_FS;
+ *env->mstatus |= MSTATUS_FS;
#endif
env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
return 0;
@@ -183,7 +183,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
return -1;
}
- env->mstatus |= MSTATUS_FS;
+ *env->mstatus |= MSTATUS_FS;
#endif
env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
@@ -307,7 +307,7 @@ static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
/* Machine Trap Setup */
static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
{
- *val = env->mstatus;
+ *val = *env->mstatus;
return 0;
}
@@ -319,7 +319,7 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
{
- target_ulong mstatus = env->mstatus;
+ target_ulong mstatus = *env->mstatus;
target_ulong mask = 0;
int dirty;
@@ -359,7 +359,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
((mstatus & MSTATUS_XS) == MSTATUS_XS);
mstatus = set_field(mstatus, MSTATUS_SD, dirty);
- env->mstatus = mstatus;
+ *env->mstatus = mstatus;
return 0;
}
@@ -448,13 +448,13 @@ static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
static int read_mie(CPURISCVState *env, int csrno, target_ulong *val)
{
- *val = env->mie;
+ *val = *env->mie;
return 0;
}
static int write_mie(CPURISCVState *env, int csrno, target_ulong val)
{
- env->mie = (env->mie & ~all_ints) | (val & all_ints);
+ *env->mie = (*env->mie & ~all_ints) | (val & all_ints);
return 0;
}
@@ -608,7 +608,7 @@ static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
{
target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
sstatus_v1_10_mask : sstatus_v1_9_mask);
- *val = env->mstatus & mask;
+ *val = *env->mstatus & mask;
return 0;
}
@@ -616,19 +616,19 @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
{
target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
sstatus_v1_10_mask : sstatus_v1_9_mask);
- target_ulong newval = (env->mstatus & ~mask) | (val & mask);
+ target_ulong newval = (*env->mstatus & ~mask) | (val & mask);
return write_mstatus(env, CSR_MSTATUS, newval);
}
static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
{
- *val = env->mie & env->mideleg;
+ *val = *env->mie & env->mideleg;
return 0;
}
static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
{
- target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg);
+ target_ulong newval = (*env->mie & ~env->mideleg) | (val & env->mideleg);
return write_mie(env, CSR_MIE, newval);
}
@@ -731,7 +731,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
*val = 0;
} else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
- if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+ if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
return -1;
} else {
*val = env->satp;
@@ -756,7 +756,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
validate_vm(env, get_field(val, SATP_MODE)) &&
((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
{
- if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+ if (env->priv == PRV_S && get_field(*env->mstatus, MSTATUS_TVM)) {
return -1;
} else {
if((val ^ env->satp) & SATP_ASID) {
@@ -83,11 +83,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
}
if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
- get_field(env->mstatus, MSTATUS_TSR)) {
+ get_field(*env->mstatus, MSTATUS_TSR)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
- target_ulong mstatus = env->mstatus;
+ target_ulong mstatus = *env->mstatus;
target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
mstatus = set_field(mstatus,
env->priv_ver >= PRIV_VERSION_1_10_0 ?
@@ -96,7 +96,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
riscv_cpu_set_mode(env, prev_priv);
- env->mstatus = mstatus;
+ *env->mstatus = mstatus;
return retpc;
}
@@ -112,7 +112,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
}
- target_ulong mstatus = env->mstatus;
+ target_ulong mstatus = *env->mstatus;
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
mstatus = set_field(mstatus,
env->priv_ver >= PRIV_VERSION_1_10_0 ?
@@ -121,7 +121,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
riscv_cpu_set_mode(env, prev_priv);
- env->mstatus = mstatus;
+ *env->mstatus = mstatus;
return retpc;
}
@@ -132,7 +132,7 @@ void helper_wfi(CPURISCVState *env)
if (env->priv == PRV_S &&
env->priv_ver >= PRIV_VERSION_1_10_0 &&
- get_field(env->mstatus, MSTATUS_TW)) {
+ get_field(*env->mstatus, MSTATUS_TW)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
} else {
cs->halted = 1;
@@ -147,7 +147,7 @@ void helper_tlb_flush(CPURISCVState *env)
if (!(env->priv >= PRV_S) ||
(env->priv == PRV_S &&
env->priv_ver >= PRIV_VERSION_1_10_0 &&
- get_field(env->mstatus, MSTATUS_TVM))) {
+ get_field(*env->mstatus, MSTATUS_TVM))) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
} else {
tlb_flush(cs);