KVM: arm64: Make FEAT_MOPS UNDEF if not advertised to the guest
authorMarc Zyngier <maz@kernel.org>
Wed, 14 Feb 2024 13:18:25 +0000 (13:18 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Mon, 19 Feb 2024 17:13:02 +0000 (17:13 +0000)
We unconditionally enable FEAT_MOPS, which is obviously wrong.

So let's only do that when it is advertised to the guest.
Which means we need to rely on a per-vcpu HCRX_EL2 shadow register.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Link: https://lore.kernel.org/r/20240214131827.2856277-25-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/sys_regs.c

index 3c6f8ba1e47927cea13fd4ff7f25c46c846052cf..a1769e415d728ad9354c99ed7686a2e912e962ad 100644 (file)
 #define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
-#define HCRX_GUEST_FLAGS \
-       (HCRX_EL2_SMPME | HCRX_EL2_TCR2En | \
-        (cpus_have_final_cap(ARM64_HAS_MOPS) ? (HCRX_EL2_MSCEn | HCRX_EL2_MCE2) : 0))
+#define HCRX_GUEST_FLAGS (HCRX_EL2_SMPME | HCRX_EL2_TCR2En)
 #define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En)
 
 /* TCR_EL2 Registers bits */
index 968a997b3f02804a255b0002bbbbe4e252df5cb6..3feabde9c926dac81ef16e88c0adb7e536beb4c0 100644 (file)
@@ -584,6 +584,7 @@ struct kvm_vcpu_arch {
 
        /* Values of trap registers for the guest. */
        u64 hcr_el2;
+       u64 hcrx_el2;
        u64 mdcr_el2;
        u64 cptr_el2;
 
index 2d5891518006d2aaae4331dcd90c0a929c7870a1..e3fcf8c4d5b4d4c847e0dd1522380463a6c92e44 100644 (file)
@@ -236,7 +236,7 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
        write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
 
        if (cpus_have_final_cap(ARM64_HAS_HCX)) {
-               u64 hcrx = HCRX_GUEST_FLAGS;
+               u64 hcrx = vcpu->arch.hcrx_el2;
                if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
                        u64 clr = 0, set = 0;
 
index 38ed47bd29db81ca8f7cbad72e47ad44e43df0d6..2cb69efac1dc4fafc9419fc0b1d4b9d9352cdfbc 100644 (file)
@@ -3956,6 +3956,13 @@ void kvm_init_sysreg(struct kvm_vcpu *vcpu)
        if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
                vcpu->arch.hcr_el2 |= HCR_TTLBOS;
 
+       if (cpus_have_final_cap(ARM64_HAS_HCX)) {
+               vcpu->arch.hcrx_el2 = HCRX_GUEST_FLAGS;
+
+               if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
+                       vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
+       }
+
        if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
                goto out;