Commit ffea7c73 authored by Marc Zyngier's avatar Marc Zyngier Committed by Oliver Upton
Browse files

KVM: arm64: Properly save/restore HCRX_EL2



Rather than restoring HCRX_EL2 to a fixed value on vcpu exit,
perform a full save/restore of the register, ensuring that
we don't lose bits that would have been set at some point in
the host kernel lifetime, such as the GCSEn bit.

Fixes: ff5181d8 ("arm64/gcs: Provide basic EL2 setup to allow GCS usage at EL0 and EL1")
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250430105916.3815157-2-maz@kernel.org


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent b60e285b
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ static inline void __deactivate_traps_mpam(void)

static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
{
	struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);

	/* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */
	write_sysreg(1 << 15, hstr_el2);

@@ -245,11 +247,8 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
	 * EL1 instead of being trapped to EL2.
	 */
	if (system_supports_pmuv3()) {
		struct kvm_cpu_context *hctxt;

		write_sysreg(0, pmselr_el0);

		hctxt = host_data_ptr(host_ctxt);
		ctxt_sys_reg(hctxt, PMUSERENR_EL0) = read_sysreg(pmuserenr_el0);
		write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
		vcpu_set_flag(vcpu, PMUSERENR_ON_CPU);
@@ -269,6 +268,7 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
			hcrx &= ~clr;
		}

		ctxt_sys_reg(hctxt, HCRX_EL2) = read_sysreg_s(SYS_HCRX_EL2);
		write_sysreg_s(hcrx, SYS_HCRX_EL2);
	}

@@ -278,19 +278,18 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)

static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
{
	struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);

	write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);

	write_sysreg(0, hstr_el2);
	if (system_supports_pmuv3()) {
		struct kvm_cpu_context *hctxt;

		hctxt = host_data_ptr(host_ctxt);
		write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0);
		vcpu_clear_flag(vcpu, PMUSERENR_ON_CPU);
	}

	if (cpus_have_final_cap(ARM64_HAS_HCX))
		write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
		write_sysreg_s(ctxt_sys_reg(hctxt, HCRX_EL2), SYS_HCRX_EL2);

	__deactivate_traps_hfgxtr(vcpu);
	__deactivate_traps_mpam();