OSDN Git Service

KVM: x86: Enable CMCI capability by default and handle injected UCNA errors
authorJue Wang <juew@google.com>
Fri, 10 Jun 2022 17:11:33 +0000 (10:11 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 Jun 2022 08:52:03 +0000 (04:52 -0400)
This patch enables MCG_CMCI_P by default in kvm_mce_cap_supported. It
reuses ioctl KVM_X86_SET_MCE to implement injection of UnCorrectable
No Action required (UCNA) errors, signaled via Corrected Machine
Check Interrupt (CMCI).

Neither of the CMCI and UCNA emulations depends on hardware.

Signed-off-by: Jue Wang <juew@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20220610171134.772566-8-juew@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c

index 4002f6c..c30115b 100644 (file)
@@ -8299,6 +8299,7 @@ static __init int hardware_setup(void)
        }
 
        kvm_caps.supported_mce_cap |= MCG_LMCE_P;
+       kvm_caps.supported_mce_cap |= MCG_CMCI_P;
 
        if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST)
                return -EINVAL;
index f743e4e..031678e 100644 (file)
@@ -4901,6 +4901,42 @@ out:
        return r;
 }
 
+/*
+ * Validate this is an UCNA (uncorrectable no action) error by checking the
+ * MCG_STATUS and MCi_STATUS registers:
+ * - none of the bits for Machine Check Exceptions are set
+ * - both the VAL (valid) and UC (uncorrectable) bits are set
+ * MCI_STATUS_PCC - Processor Context Corrupted
+ * MCI_STATUS_S - Signaled as a Machine Check Exception
+ * MCI_STATUS_AR - Software recoverable Action Required
+ */
+static bool is_ucna(struct kvm_x86_mce *mce)
+{
+       return  !mce->mcg_status &&
+               !(mce->status & (MCI_STATUS_PCC | MCI_STATUS_S | MCI_STATUS_AR)) &&
+               (mce->status & MCI_STATUS_VAL) &&
+               (mce->status & MCI_STATUS_UC);
+}
+
+static int kvm_vcpu_x86_set_ucna(struct kvm_vcpu *vcpu, struct kvm_x86_mce *mce, u64* banks)
+{
+       u64 mcg_cap = vcpu->arch.mcg_cap;
+
+       banks[1] = mce->status;
+       banks[2] = mce->addr;
+       banks[3] = mce->misc;
+       vcpu->arch.mcg_status = mce->mcg_status;
+
+       if (!(mcg_cap & MCG_CMCI_P) ||
+           !(vcpu->arch.mci_ctl2_banks[mce->bank] & MCI_CTL2_CMCI_EN))
+               return 0;
+
+       if (lapic_in_kernel(vcpu))
+               kvm_apic_local_deliver(vcpu->arch.apic, APIC_LVTCMCI);
+
+       return 0;
+}
+
 static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
                                      struct kvm_x86_mce *mce)
 {
@@ -4910,6 +4946,12 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
 
        if (mce->bank >= bank_num || !(mce->status & MCI_STATUS_VAL))
                return -EINVAL;
+
+       banks += array_index_nospec(4 * mce->bank, 4 * bank_num);
+
+       if (is_ucna(mce))
+               return kvm_vcpu_x86_set_ucna(vcpu, mce, banks);
+
        /*
         * if IA32_MCG_CTL is not all 1s, the uncorrected error
         * reporting is disabled
@@ -4917,7 +4959,6 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
        if ((mce->status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
            vcpu->arch.mcg_ctl != ~(u64)0)
                return 0;
-       banks += 4 * mce->bank;
        /*
         * if IA32_MCi_CTL is not all 1s, the uncorrected error
         * reporting is disabled for the bank