mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
KVM: arm64: Factor out reusable vCPU reset helpers
Pull the reusable pieces out of kvm_reset_vcpu(): expose the reset PSTATE values in kvm_arm.h, and split the core register reset and the PSCI-driven reset into kvm_reset_vcpu_core() and kvm_reset_vcpu_psci(). A follow-up series reuses these to reset protected vCPUs at EL2. No functional change intended. Reviewed-by: Vincent Donnefort <vdonnefort@google.com> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev> Link: https://patch.msgid.link/20260729131823.2021516-4-fuad.tabba@linux.dev Signed-off-by: Oliver Upton <oupton@kernel.org>
This commit is contained in:
parent
f88099ad9f
commit
29b2e2ab7f
|
|
@ -348,4 +348,16 @@
|
|||
{ PSR_AA32_MODE_UND, "32-bit UND" }, \
|
||||
{ PSR_AA32_MODE_SYS, "32-bit SYS" }
|
||||
|
||||
/*
|
||||
* ARMv8 Reset Values
|
||||
*/
|
||||
#define VCPU_RESET_PSTATE_EL1 (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | \
|
||||
PSR_F_BIT | PSR_D_BIT)
|
||||
|
||||
#define VCPU_RESET_PSTATE_EL2 (PSR_MODE_EL2h | PSR_A_BIT | PSR_I_BIT | \
|
||||
PSR_F_BIT | PSR_D_BIT)
|
||||
|
||||
#define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
|
||||
PSR_AA32_I_BIT | PSR_AA32_F_BIT)
|
||||
|
||||
#endif /* __ARM64_KVM_ARM_H__ */
|
||||
|
|
|
|||
|
|
@ -694,4 +694,61 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)
|
|||
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnASR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset a vcpu's core registers. */
|
||||
static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u32 pstate;
|
||||
|
||||
if (vcpu_el1_is_32bit(vcpu))
|
||||
pstate = VCPU_RESET_PSTATE_SVC;
|
||||
else if (vcpu_has_nv(vcpu))
|
||||
pstate = VCPU_RESET_PSTATE_EL2;
|
||||
else
|
||||
pstate = VCPU_RESET_PSTATE_EL1;
|
||||
|
||||
/* Reset core registers */
|
||||
memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
|
||||
memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
|
||||
vcpu->arch.ctxt.spsr_abt = 0;
|
||||
vcpu->arch.ctxt.spsr_und = 0;
|
||||
vcpu->arch.ctxt.spsr_irq = 0;
|
||||
vcpu->arch.ctxt.spsr_fiq = 0;
|
||||
vcpu_gp_regs(vcpu)->pstate = pstate;
|
||||
}
|
||||
|
||||
/* PSCI reset handling for a vcpu. */
|
||||
static inline void kvm_reset_vcpu_psci(struct kvm_vcpu *vcpu,
|
||||
struct vcpu_reset_state *reset_state)
|
||||
{
|
||||
unsigned long target_pc = reset_state->pc;
|
||||
|
||||
/* Gracefully handle Thumb2 entry point */
|
||||
if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
|
||||
target_pc &= ~1UL;
|
||||
vcpu_set_thumb(vcpu);
|
||||
}
|
||||
|
||||
/* Propagate caller endianness */
|
||||
if (reset_state->be)
|
||||
kvm_vcpu_set_be(vcpu);
|
||||
|
||||
*vcpu_pc(vcpu) = target_pc;
|
||||
|
||||
/*
|
||||
* We may come from a state where either a PC update was
|
||||
* pending (SMC call resulting in PC being increpented to
|
||||
* skip the SMC) or a pending exception. Make sure we get
|
||||
* rid of all that, as this cannot be valid out of reset.
|
||||
*
|
||||
* Note that clearing the exception mask also clears PC
|
||||
* updates, but that's an implementation detail, and we
|
||||
* really want to make it explicit.
|
||||
*/
|
||||
vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
|
||||
vcpu_clear_flag(vcpu, EXCEPT_MASK);
|
||||
vcpu_clear_flag(vcpu, INCREMENT_PC);
|
||||
vcpu_set_reg(vcpu, 0, reset_state->r0);
|
||||
}
|
||||
|
||||
#endif /* __ARM64_KVM_EMULATE_H__ */
|
||||
|
|
|
|||
|
|
@ -34,18 +34,6 @@
|
|||
static u32 __ro_after_init kvm_ipa_limit;
|
||||
unsigned int __ro_after_init kvm_host_sve_max_vl;
|
||||
|
||||
/*
|
||||
* ARMv8 Reset Values
|
||||
*/
|
||||
#define VCPU_RESET_PSTATE_EL1 (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | \
|
||||
PSR_F_BIT | PSR_D_BIT)
|
||||
|
||||
#define VCPU_RESET_PSTATE_EL2 (PSR_MODE_EL2h | PSR_A_BIT | PSR_I_BIT | \
|
||||
PSR_F_BIT | PSR_D_BIT)
|
||||
|
||||
#define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
|
||||
PSR_AA32_I_BIT | PSR_AA32_F_BIT)
|
||||
|
||||
unsigned int __ro_after_init kvm_sve_max_vl;
|
||||
|
||||
int __init kvm_arm_init_sve(void)
|
||||
|
|
@ -191,7 +179,6 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct vcpu_reset_state reset_state;
|
||||
bool loaded;
|
||||
u32 pstate;
|
||||
|
||||
spin_lock(&vcpu->arch.mp_state_lock);
|
||||
reset_state = vcpu->arch.reset_state;
|
||||
|
|
@ -210,21 +197,8 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
|||
kvm_vcpu_reset_sve(vcpu);
|
||||
}
|
||||
|
||||
if (vcpu_el1_is_32bit(vcpu))
|
||||
pstate = VCPU_RESET_PSTATE_SVC;
|
||||
else if (vcpu_has_nv(vcpu))
|
||||
pstate = VCPU_RESET_PSTATE_EL2;
|
||||
else
|
||||
pstate = VCPU_RESET_PSTATE_EL1;
|
||||
|
||||
/* Reset core registers */
|
||||
memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
|
||||
memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
|
||||
vcpu->arch.ctxt.spsr_abt = 0;
|
||||
vcpu->arch.ctxt.spsr_und = 0;
|
||||
vcpu->arch.ctxt.spsr_irq = 0;
|
||||
vcpu->arch.ctxt.spsr_fiq = 0;
|
||||
vcpu_gp_regs(vcpu)->pstate = pstate;
|
||||
kvm_reset_vcpu_core(vcpu);
|
||||
|
||||
/* Reset system registers */
|
||||
kvm_reset_sys_regs(vcpu);
|
||||
|
|
@ -233,36 +207,8 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
|||
* Additional reset state handling that PSCI may have imposed on us.
|
||||
* Must be done after all the sys_reg reset.
|
||||
*/
|
||||
if (reset_state.reset) {
|
||||
unsigned long target_pc = reset_state.pc;
|
||||
|
||||
/* Gracefully handle Thumb2 entry point */
|
||||
if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
|
||||
target_pc &= ~1UL;
|
||||
vcpu_set_thumb(vcpu);
|
||||
}
|
||||
|
||||
/* Propagate caller endianness */
|
||||
if (reset_state.be)
|
||||
kvm_vcpu_set_be(vcpu);
|
||||
|
||||
*vcpu_pc(vcpu) = target_pc;
|
||||
|
||||
/*
|
||||
* We may come from a state where either a PC update was
|
||||
* pending (SMC call resulting in PC being increpented to
|
||||
* skip the SMC) or a pending exception. Make sure we get
|
||||
* rid of all that, as this cannot be valid out of reset.
|
||||
*
|
||||
* Note that clearing the exception mask also clears PC
|
||||
* updates, but that's an implementation detail, and we
|
||||
* really want to make it explicit.
|
||||
*/
|
||||
vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
|
||||
vcpu_clear_flag(vcpu, EXCEPT_MASK);
|
||||
vcpu_clear_flag(vcpu, INCREMENT_PC);
|
||||
vcpu_set_reg(vcpu, 0, reset_state.r0);
|
||||
}
|
||||
if (reset_state.reset)
|
||||
kvm_reset_vcpu_psci(vcpu, &reset_state);
|
||||
|
||||
/* Reset timer */
|
||||
kvm_timer_vcpu_reset(vcpu);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user