KVM: x86: Use explicit case-statements for MCx banks in {g,s}et_msr_mce()
Use an explicit case statement to grab the full range of MCx bank MSRs in {g,s}et_msr_mce(), and manually check only the "end" (the number of banks configured by userspace may be less than the max). The "default" trick works, but is a bit odd now, and will be quite odd if/when support for accessing MCx_CTL2 MSRs is added, which has near identical logic. Hoist "offset" to function scope so as to avoid curly braces for the case statement, and because MCx_CTL2 support will need the same variables. Opportunstically clean up the comment about allowing bit 10 to be cleared from bank 4. No functional change intended. Cc: Jue Wang <juew@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Reviewed-by: Jim Mattson <jmattson@google.com> Link: https://lore.kernel.org/r/20220512222716.4112548-3-seanjc@google.com
This commit is contained in:
parent
2368048bf5
commit
f5223a332f
@ -3209,6 +3209,7 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
unsigned bank_num = mcg_cap & 0xff;
|
||||
u32 msr = msr_info->index;
|
||||
u64 data = msr_info->data;
|
||||
u32 offset, last_msr;
|
||||
|
||||
switch (msr) {
|
||||
case MSR_IA32_MCG_STATUS:
|
||||
@ -3222,35 +3223,36 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
return 1;
|
||||
vcpu->arch.mcg_ctl = data;
|
||||
break;
|
||||
case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
|
||||
last_msr = MSR_IA32_MCx_CTL(bank_num) - 1;
|
||||
if (msr > last_msr)
|
||||
return 1;
|
||||
|
||||
offset = array_index_nospec(msr - MSR_IA32_MC0_CTL,
|
||||
last_msr + 1 - MSR_IA32_MC0_CTL);
|
||||
|
||||
/*
|
||||
* Only 0 or all 1s can be written to IA32_MCi_CTL, all other
|
||||
* values are architecturally undefined. But, some Linux
|
||||
* kernels clear bit 10 in bank 4 to workaround a BIOS/GART TLB
|
||||
* issue on AMD K8s, allow bit 10 to be clear when setting all
|
||||
* other bits in order to avoid an uncaught #GP in the guest.
|
||||
*
|
||||
* UNIXWARE clears bit 0 of MC1_CTL to ignore correctable,
|
||||
* single-bit ECC data errors.
|
||||
*/
|
||||
if ((offset & 0x3) == 0 &&
|
||||
data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
|
||||
return 1;
|
||||
|
||||
/* MCi_STATUS */
|
||||
if (!msr_info->host_initiated && (offset & 0x3) == 1 &&
|
||||
data != 0 && !can_set_mci_status(vcpu))
|
||||
return 1;
|
||||
|
||||
vcpu->arch.mce_banks[offset] = data;
|
||||
break;
|
||||
default:
|
||||
if (msr >= MSR_IA32_MC0_CTL &&
|
||||
msr < MSR_IA32_MCx_CTL(bank_num)) {
|
||||
u32 offset = array_index_nospec(
|
||||
msr - MSR_IA32_MC0_CTL,
|
||||
MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
|
||||
|
||||
/* only 0 or all 1s can be written to IA32_MCi_CTL
|
||||
* some Linux kernels though clear bit 10 in bank 4 to
|
||||
* workaround a BIOS/GART TBL issue on AMD K8s, ignore
|
||||
* this to avoid an uncatched #GP in the guest.
|
||||
*
|
||||
* UNIXWARE clears bit 0 of MC1_CTL to ignore
|
||||
* correctable, single-bit ECC data errors.
|
||||
*/
|
||||
if ((offset & 0x3) == 0 &&
|
||||
data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
|
||||
return 1;
|
||||
|
||||
/* MCi_STATUS */
|
||||
if (!msr_info->host_initiated &&
|
||||
(offset & 0x3) == 1 && data != 0) {
|
||||
if (!can_set_mci_status(vcpu))
|
||||
return 1;
|
||||
}
|
||||
|
||||
vcpu->arch.mce_banks[offset] = data;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -3819,6 +3821,7 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host)
|
||||
u64 data;
|
||||
u64 mcg_cap = vcpu->arch.mcg_cap;
|
||||
unsigned bank_num = mcg_cap & 0xff;
|
||||
u32 offset, last_msr;
|
||||
|
||||
switch (msr) {
|
||||
case MSR_IA32_P5_MC_ADDR:
|
||||
@ -3836,16 +3839,16 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host)
|
||||
case MSR_IA32_MCG_STATUS:
|
||||
data = vcpu->arch.mcg_status;
|
||||
break;
|
||||
default:
|
||||
if (msr >= MSR_IA32_MC0_CTL &&
|
||||
msr < MSR_IA32_MCx_CTL(bank_num)) {
|
||||
u32 offset = array_index_nospec(
|
||||
msr - MSR_IA32_MC0_CTL,
|
||||
MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
|
||||
case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
|
||||
last_msr = MSR_IA32_MCx_CTL(bank_num) - 1;
|
||||
if (msr > last_msr)
|
||||
return 1;
|
||||
|
||||
data = vcpu->arch.mce_banks[offset];
|
||||
break;
|
||||
}
|
||||
offset = array_index_nospec(msr - MSR_IA32_MC0_CTL,
|
||||
last_msr + 1 - MSR_IA32_MC0_CTL);
|
||||
data = vcpu->arch.mce_banks[offset];
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
*pdata = data;
|
||||
|
Loading…
x
Reference in New Issue
Block a user