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:
                        return 1;
                vcpu->arch.mcg_ctl = 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;
+       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;
 
-                       /* MCi_STATUS */
-                       if (!msr_info->host_initiated &&
-                           (offset & 0x3) == 1 && data != 0) {
-                               if (!can_set_mci_status(vcpu))
-                                       return 1;
-                       }
+               offset = array_index_nospec(msr - MSR_IA32_MC0_CTL,
+                                           last_msr + 1 - MSR_IA32_MC0_CTL);
 
-                       vcpu->arch.mce_banks[offset] = data;
-                       break;
-               }
+               /*
+                * 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:
                return 1;
        }
        return 0;
        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:
        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;