KVM: x86: Enable CMCI capability by default and handle injected UCNA errors

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>
This commit is contained in:
Jue Wang 2022-06-10 10:11:33 -07:00 коммит произвёл Paolo Bonzini
Родитель 281b52780b
Коммит aebc3ca190
2 изменённых файлов: 43 добавлений и 1 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -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