mirror of https://github.com/xemu-project/xemu.git
target/riscv: Combine set_mode and set_virt functions.
Combining riscv_cpu_set_virt_enabled() and riscv_cpu_set_mode() functions. This is to make complete mode change information available through a single function. This allows to easily differentiate between HS->VS, VS->HS and VS->VS transitions when executing state update codes. For example: One use-case which inspired this change is to update mode-specific instruction and cycle counters which requires information of both prev mode and current mode. Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20240711-smcntrpmf_v7-v8-1-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
3cb9f20499
commit
68c05fb530
|
@ -567,7 +567,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
|
|||
RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
|
||||
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en);
|
||||
|
||||
void riscv_translate_init(void);
|
||||
G_NORETURN void riscv_raise_exception(CPURISCVState *env,
|
||||
|
|
|
@ -619,30 +619,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
|
|||
env->geilen = geilen;
|
||||
}
|
||||
|
||||
/* This function can only be called to set virt when RVH is enabled */
|
||||
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
|
||||
{
|
||||
/* Flush the TLB on all virt mode changes. */
|
||||
if (env->virt_enabled != enable) {
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
|
||||
env->virt_enabled = enable;
|
||||
|
||||
if (enable) {
|
||||
/*
|
||||
* The guest external interrupts from an interrupt controller are
|
||||
* delivered only when the Guest/VM is running (i.e. V=1). This means
|
||||
* any guest external interrupt which is triggered while the Guest/VM
|
||||
* is not running (i.e. V=0) will be missed on QEMU resulting in guest
|
||||
* with sluggish response to serial console input and other I/O events.
|
||||
*
|
||||
* To solve this, we check and inject interrupt after setting V=1.
|
||||
*/
|
||||
riscv_cpu_update_mip(env, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
|
@ -715,7 +691,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
|
|||
}
|
||||
}
|
||||
|
||||
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
|
||||
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
|
||||
{
|
||||
g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
|
||||
|
||||
|
@ -736,6 +712,28 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
|
|||
* preemptive context switch. As a result, do both.
|
||||
*/
|
||||
env->load_res = -1;
|
||||
|
||||
if (riscv_has_ext(env, RVH)) {
|
||||
/* Flush the TLB on all virt mode changes. */
|
||||
if (env->virt_enabled != virt_en) {
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
|
||||
env->virt_enabled = virt_en;
|
||||
if (virt_en) {
|
||||
/*
|
||||
* The guest external interrupts from an interrupt controller are
|
||||
* delivered only when the Guest/VM is running (i.e. V=1). This
|
||||
* means any guest external interrupt which is triggered while the
|
||||
* Guest/VM is not running (i.e. V=0) will be missed on QEMU
|
||||
* resulting in guest with sluggish response to serial console
|
||||
* input and other I/O events.
|
||||
*
|
||||
* To solve this, we check and inject interrupt after setting V=1.
|
||||
*/
|
||||
riscv_cpu_update_mip(env, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1648,6 +1646,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
{
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
CPURISCVState *env = &cpu->env;
|
||||
bool virt = env->virt_enabled;
|
||||
bool write_gva = false;
|
||||
uint64_t s;
|
||||
|
||||
|
@ -1778,7 +1777,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
|
||||
htval = env->guest_phys_fault_addr;
|
||||
|
||||
riscv_cpu_set_virt_enabled(env, 0);
|
||||
virt = false;
|
||||
} else {
|
||||
/* Trap into HS mode */
|
||||
env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
|
||||
|
@ -1799,7 +1798,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
env->htinst = tinst;
|
||||
env->pc = (env->stvec >> 2 << 2) +
|
||||
((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
|
||||
riscv_cpu_set_mode(env, PRV_S);
|
||||
riscv_cpu_set_mode(env, PRV_S, virt);
|
||||
} else {
|
||||
/* handle the trap in M-mode */
|
||||
if (riscv_has_ext(env, RVH)) {
|
||||
|
@ -1815,7 +1814,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
mtval2 = env->guest_phys_fault_addr;
|
||||
|
||||
/* Trapping to M mode, virt is disabled */
|
||||
riscv_cpu_set_virt_enabled(env, 0);
|
||||
virt = false;
|
||||
}
|
||||
|
||||
s = env->mstatus;
|
||||
|
@ -1830,7 +1829,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
env->mtinst = tinst;
|
||||
env->pc = (env->mtvec >> 2 << 2) +
|
||||
((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
|
||||
riscv_cpu_set_mode(env, PRV_M);
|
||||
riscv_cpu_set_mode(env, PRV_M, virt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -264,7 +264,7 @@ void helper_cbo_inval(CPURISCVState *env, target_ulong address)
|
|||
target_ulong helper_sret(CPURISCVState *env)
|
||||
{
|
||||
uint64_t mstatus;
|
||||
target_ulong prev_priv, prev_virt;
|
||||
target_ulong prev_priv, prev_virt = env->virt_enabled;
|
||||
|
||||
if (!(env->priv >= PRV_S)) {
|
||||
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||
|
@ -307,11 +307,9 @@ target_ulong helper_sret(CPURISCVState *env)
|
|||
if (prev_virt) {
|
||||
riscv_cpu_swap_hypervisor_regs(env);
|
||||
}
|
||||
|
||||
riscv_cpu_set_virt_enabled(env, prev_virt);
|
||||
}
|
||||
|
||||
riscv_cpu_set_mode(env, prev_priv);
|
||||
riscv_cpu_set_mode(env, prev_priv, prev_virt);
|
||||
|
||||
return retpc;
|
||||
}
|
||||
|
@ -347,16 +345,13 @@ target_ulong helper_mret(CPURISCVState *env)
|
|||
mstatus = set_field(mstatus, MSTATUS_MPRV, 0);
|
||||
}
|
||||
env->mstatus = mstatus;
|
||||
riscv_cpu_set_mode(env, prev_priv);
|
||||
|
||||
if (riscv_has_ext(env, RVH)) {
|
||||
if (prev_virt) {
|
||||
riscv_cpu_swap_hypervisor_regs(env);
|
||||
}
|
||||
|
||||
riscv_cpu_set_virt_enabled(env, prev_virt);
|
||||
if (riscv_has_ext(env, RVH) && prev_virt) {
|
||||
riscv_cpu_swap_hypervisor_regs(env);
|
||||
}
|
||||
|
||||
riscv_cpu_set_mode(env, prev_priv, prev_virt);
|
||||
|
||||
return retpc;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue