]> www.infradead.org Git - users/hch/misc.git/commitdiff
KVM: arm64: nv: Use FGT write trap of MDSCR_EL1 when available
authorOliver Upton <oliver.upton@linux.dev>
Wed, 24 Sep 2025 23:51:50 +0000 (16:51 -0700)
committerMarc Zyngier <maz@kernel.org>
Mon, 13 Oct 2025 13:44:37 +0000 (14:44 +0100)
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: Marc Zyngier <maz@kernel.org>
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/config.c
arch/arm64/kvm/nested.c

index b1cf7660efe17f377e5239c791fc866f3a28daaf..24bb3f36e9d59d479cd1efa73487131e7a69a4b5 100644 (file)
@@ -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))
index 7a045cad6bdf0a80e2fe250b211f011ca43533a7..f04cda40545b101f3fcde7a9cf63b7fdfe27af0c 100644 (file)
@@ -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);
 }