Commit 02dd33ec authored by Oliver Upton's avatar Oliver Upton
Browse files

KVM: arm64: Context switch SCTLR2_ELx when advertised to the guest



Restore SCTLR2_EL1 with the correct value for the given context when
FEAT_SCTLR2 is advertised to the guest.

Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250708172532.1699409-13-oliver.upton@linux.dev


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 81fbef16
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -120,6 +120,17 @@ static inline bool ctxt_has_ras(struct kvm_cpu_context *ctxt)
	return kvm_has_ras(kern_hyp_va(vcpu->kvm));
}

static inline bool ctxt_has_sctlr2(struct kvm_cpu_context *ctxt)
{
	struct kvm_vcpu *vcpu;

	if (!cpus_have_final_cap(ARM64_HAS_SCTLR2))
		return false;

	vcpu = ctxt_to_vcpu(ctxt);
	return kvm_has_sctlr2(kern_hyp_va(vcpu->kvm));
}

static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
{
	ctxt_sys_reg(ctxt, SCTLR_EL1)	= read_sysreg_el1(SYS_SCTLR);
@@ -158,6 +169,9 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
	ctxt_sys_reg(ctxt, SP_EL1)	= read_sysreg(sp_el1);
	ctxt_sys_reg(ctxt, ELR_EL1)	= read_sysreg_el1(SYS_ELR);
	ctxt_sys_reg(ctxt, SPSR_EL1)	= read_sysreg_el1(SYS_SPSR);

	if (ctxt_has_sctlr2(ctxt))
		ctxt_sys_reg(ctxt, SCTLR2_EL1) = read_sysreg_el1(SYS_SCTLR2);
}

static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt)
@@ -268,6 +282,9 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt,
	write_sysreg(ctxt_sys_reg(ctxt, SP_EL1),	sp_el1);
	write_sysreg_el1(ctxt_sys_reg(ctxt, ELR_EL1),	SYS_ELR);
	write_sysreg_el1(ctxt_sys_reg(ctxt, SPSR_EL1),	SYS_SPSR);

	if (ctxt_has_sctlr2(ctxt))
		write_sysreg_el1(ctxt_sys_reg(ctxt, SCTLR2_EL1), SYS_SCTLR2);
}

/* Read the VCPU state's PSTATE, but translate (v)EL2 to EL1. */
+6 −0
Original line number Diff line number Diff line
@@ -77,6 +77,9 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu)
	__vcpu_assign_sys_reg(vcpu, SP_EL2,	 read_sysreg(sp_el1));
	__vcpu_assign_sys_reg(vcpu, ELR_EL2,	 read_sysreg_el1(SYS_ELR));
	__vcpu_assign_sys_reg(vcpu, SPSR_EL2,	 read_sysreg_el1(SYS_SPSR));

	if (ctxt_has_sctlr2(&vcpu->arch.ctxt))
		__vcpu_assign_sys_reg(vcpu, SCTLR2_EL2, read_sysreg_el1(SYS_SCTLR2));
}

static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
@@ -139,6 +142,9 @@ static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
	write_sysreg(__vcpu_sys_reg(vcpu, SP_EL2),		sp_el1);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, ELR_EL2),		SYS_ELR);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, SPSR_EL2),	SYS_SPSR);

	if (ctxt_has_sctlr2(&vcpu->arch.ctxt))
		write_sysreg_el1(__vcpu_sys_reg(vcpu, SCTLR2_EL2), SYS_SCTLR2);
}

/*