Note prior to this patch, the UCNA type of signaling can already be processed by kvm_vcpu_ioctl_x86_set_mce and does not result in correct CMCI signaling semantic. Signed-off-by: Jue Wang <juew@xxxxxxxxxx> --- arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b730d799c26e..63aa2b3d30ca 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8035,6 +8035,7 @@ static __init int hardware_setup(void) } kvm_mce_cap_supported |= MCG_LMCE_P; + kvm_mce_cap_supported |= MCG_CMCI_P; if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST) return -EINVAL; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 73c64d2b9e60..eb6058ca1e70 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4775,6 +4775,50 @@ static int kvm_vcpu_ioctl_x86_setup_mce(struct kvm_vcpu *vcpu, return r; } +static bool is_ucna(u64 mcg_status, u64 mci_status) +{ + return !mcg_status && + !(mci_status & (MCI_STATUS_PCC | MCI_STATUS_S | MCI_STATUS_AR)); +} + +static int kvm_vcpu_x86_set_ucna(struct kvm_vcpu *vcpu, + struct kvm_x86_mce *mce) +{ + u64 mcg_cap = vcpu->arch.mcg_cap; + unsigned int bank_num = mcg_cap & 0xff; + u64 *banks = vcpu->arch.mce_banks; + + /* Check for legal bank number in guest */ + if (mce->bank >= bank_num) + return -EINVAL; + + /* + * UCNA signals should not set bits that are only used for machine check + * exceptions. + */ + if (mce->mcg_status || + (mce->status & (MCI_STATUS_PCC | MCI_STATUS_S | MCI_STATUS_AR))) + return -EINVAL; + + /* UCNA must have VAL and UC bits set */ + if (!(mce->status & MCI_STATUS_VAL) || !(mce->status & MCI_STATUS_UC)) + return -EINVAL; + + banks += 4 * mce->bank; + 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) { @@ -4784,6 +4828,10 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu, if (mce->bank >= bank_num || !(mce->status & MCI_STATUS_VAL)) return -EINVAL; + + if (is_ucna(mce->mcg_status, mce->status)) + return kvm_vcpu_x86_set_ucna(vcpu, mce); + /* * if IA32_MCG_CTL is not all 1s, the uncorrected error * reporting is disabled -- 2.35.1.1178.g4f1659d476-goog