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

KVM: arm64: nv: Use FGT write trap of MDSCR_EL1 when available



Marc reports that the performance of running an L3 guest has regressed
by 60% as a result of setting MDCR_EL2.TDA to hide bad architecture.
That's of course terrible for the single user of recursive NV ;-)

While there's nothing to be done on non-FGT systems, take advantage of
the precise write trap of MDSCR_EL1 and leave the rest of the debug
registers untrapped.

Reported-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
Reviewed-by: default avatarJoey Gouly <joey.gouly@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent fb10ddf3
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -1489,6 +1489,14 @@ static void __compute_hfgwtr(struct kvm_vcpu *vcpu)
		*vcpu_fgt(vcpu, HFGWTR_EL2) |= HFGWTR_EL2_TCR_EL1;
}

static void __compute_hdfgwtr(struct kvm_vcpu *vcpu)
{
	__compute_fgt(vcpu, HDFGWTR_EL2);

	if (is_hyp_ctxt(vcpu))
		*vcpu_fgt(vcpu, HDFGWTR_EL2) |= HDFGWTR_EL2_MDSCR_EL1;
}

void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
{
	if (!cpus_have_final_cap(ARM64_HAS_FGT))
@@ -1498,7 +1506,7 @@ void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
	__compute_hfgwtr(vcpu);
	__compute_fgt(vcpu, HFGITR_EL2);
	__compute_fgt(vcpu, HDFGRTR_EL2);
	__compute_fgt(vcpu, HDFGWTR_EL2);
	__compute_hdfgwtr(vcpu);
	__compute_fgt(vcpu, HAFGRTR_EL2);

	if (!cpus_have_final_cap(ARM64_HAS_FGT2))
+6 −3
Original line number Diff line number Diff line
@@ -1859,13 +1859,16 @@ void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu)
{
	u64 guest_mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);

	if (is_nested_ctxt(vcpu))
		vcpu->arch.mdcr_el2 |= (guest_mdcr & NV_MDCR_GUEST_INCLUDE);
	/*
	 * In yet another example where FEAT_NV2 is fscking broken, accesses
	 * to MDSCR_EL1 are redirected to the VNCR despite having an effect
	 * at EL2. Use a big hammer to apply sanity.
	 *
	 * Unless of course we have FEAT_FGT, in which case we can precisely
	 * trap MDSCR_EL1.
	 */
	if (is_hyp_ctxt(vcpu))
	else if (!cpus_have_final_cap(ARM64_HAS_FGT))
		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
	else
		vcpu->arch.mdcr_el2 |= (guest_mdcr & NV_MDCR_GUEST_INCLUDE);
}