Commit 191c8137 authored by Borislav Petkov's avatar Borislav Petkov Committed by Paolo Bonzini

x86/kvm: Implement HWCR support

The hardware configuration register has some useful bits which can be
used by guests. Implement McStatusWrEn which can be used by guests when
injecting MCEs with the in-kernel mce-inject module.

For that, we need to set bit 18 - McStatusWrEn - first, before writing
the MCi_STATUS registers (otherwise we #GP).

Add the required machinery to do so.
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Jim Mattson <jmattson@google.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: KVM <kvm@vger.kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Sean Christopherson <sean.j.christopherson@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Yazen Ghannam <Yazen.Ghannam@amd.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 19e38336
...@@ -781,6 +781,9 @@ struct kvm_vcpu_arch { ...@@ -781,6 +781,9 @@ struct kvm_vcpu_arch {
/* Flush the L1 Data cache for L1TF mitigation on VMENTER */ /* Flush the L1 Data cache for L1TF mitigation on VMENTER */
bool l1tf_flush_l1d; bool l1tf_flush_l1d;
/* AMD MSRC001_0015 Hardware Configuration */
u64 msr_hwcr;
}; };
struct kvm_lpage_info { struct kvm_lpage_info {
......
...@@ -1171,6 +1171,8 @@ static u32 emulated_msrs[] = { ...@@ -1171,6 +1171,8 @@ static u32 emulated_msrs[] = {
MSR_MISC_FEATURES_ENABLES, MSR_MISC_FEATURES_ENABLES,
MSR_AMD64_VIRT_SPEC_CTRL, MSR_AMD64_VIRT_SPEC_CTRL,
MSR_IA32_POWER_CTL, MSR_IA32_POWER_CTL,
MSR_K7_HWCR,
}; };
static unsigned num_emulated_msrs; static unsigned num_emulated_msrs;
...@@ -2294,6 +2296,18 @@ static void kvmclock_sync_fn(struct work_struct *work) ...@@ -2294,6 +2296,18 @@ static void kvmclock_sync_fn(struct work_struct *work)
KVMCLOCK_SYNC_PERIOD); KVMCLOCK_SYNC_PERIOD);
} }
/*
* On AMD, HWCR[McStatusWrEn] controls whether setting MCi_STATUS results in #GP.
*/
static bool can_set_mci_status(struct kvm_vcpu *vcpu)
{
/* McStatusWrEn enabled? */
if (guest_cpuid_is_amd(vcpu))
return !!(vcpu->arch.msr_hwcr & BIT_ULL(18));
return false;
}
static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info) static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{ {
u64 mcg_cap = vcpu->arch.mcg_cap; u64 mcg_cap = vcpu->arch.mcg_cap;
...@@ -2325,9 +2339,14 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2325,9 +2339,14 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if ((offset & 0x3) == 0 && if ((offset & 0x3) == 0 &&
data != 0 && (data | (1 << 10)) != ~(u64)0) data != 0 && (data | (1 << 10)) != ~(u64)0)
return -1; return -1;
/* MCi_STATUS */
if (!msr_info->host_initiated && if (!msr_info->host_initiated &&
(offset & 0x3) == 1 && data != 0) (offset & 0x3) == 1 && data != 0) {
if (!can_set_mci_status(vcpu))
return -1; return -1;
}
vcpu->arch.mce_banks[offset] = data; vcpu->arch.mce_banks[offset] = data;
break; break;
} }
...@@ -2476,8 +2495,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2476,8 +2495,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
data &= ~(u64)0x40; /* ignore flush filter disable */ data &= ~(u64)0x40; /* ignore flush filter disable */
data &= ~(u64)0x100; /* ignore ignne emulation enable */ data &= ~(u64)0x100; /* ignore ignne emulation enable */
data &= ~(u64)0x8; /* ignore TLB cache disable */ data &= ~(u64)0x8; /* ignore TLB cache disable */
data &= ~(u64)0x40000; /* ignore Mc status write enable */
if (data != 0) { /* Handle McStatusWrEn */
if (data == BIT_ULL(18)) {
vcpu->arch.msr_hwcr = data;
} else if (data != 0) {
vcpu_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n", vcpu_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n",
data); data);
return 1; return 1;
...@@ -2751,7 +2773,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2751,7 +2773,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_K8_SYSCFG: case MSR_K8_SYSCFG:
case MSR_K8_TSEG_ADDR: case MSR_K8_TSEG_ADDR:
case MSR_K8_TSEG_MASK: case MSR_K8_TSEG_MASK:
case MSR_K7_HWCR:
case MSR_VM_HSAVE_PA: case MSR_VM_HSAVE_PA:
case MSR_K8_INT_PENDING_MSG: case MSR_K8_INT_PENDING_MSG:
case MSR_AMD64_NB_CFG: case MSR_AMD64_NB_CFG:
...@@ -2915,6 +2936,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2915,6 +2936,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_MISC_FEATURES_ENABLES: case MSR_MISC_FEATURES_ENABLES:
msr_info->data = vcpu->arch.msr_misc_features_enables; msr_info->data = vcpu->arch.msr_misc_features_enables;
break; break;
case MSR_K7_HWCR:
msr_info->data = vcpu->arch.msr_hwcr;
break;
default: default:
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info->index, &msr_info->data); return kvm_pmu_get_msr(vcpu, msr_info->index, &msr_info->data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment