/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include static const char *const mca_bank_name[] = { [0] = "Load-store unit", [1] = "Instruction fetch unit", [2] = "L2 cache unit", [3] = "Decode unit", [4] = "", [5] = "Execution unit", [6] = "Floating point unit", [7] = "L3 cache unit", [8] = "L3 cache unit", [9] = "L3 cache unit", [10] = "L3 cache unit", [11] = "L3 cache unit", [12] = "L3 cache unit", [13] = "L3 cache unit", [14] = "L3 cache unit", [15] = "UMC", [16] = "UMC", [17] = "SMU", [18] = "PSP", [19] = "PB", [20] = "CS", [21] = "CS", [22] = "PIE", }; static bool mca_is_valid_bank(unsigned int bank) { return (bank < ARRAY_SIZE(mca_bank_name) && mca_bank_name[bank] != NULL); } static const char *mca_get_bank_name(unsigned int bank) { if (mca_is_valid_bank(bank)) return mca_bank_name[bank]; else return ""; } static void mca_print_error(unsigned int bank) { msr_t msr; printk(BIOS_WARNING, "#MC Error: core %u, bank %u %s\n", initial_lapicid(), bank, mca_get_bank_name(bank)); msr = rdmsr(MCAX_STATUS_MSR(bank)); printk(BIOS_WARNING, " MC%u_STATUS = %08x_%08x\n", bank, msr.hi, msr.lo); msr = rdmsr(MCAX_ADDR_MSR(bank)); printk(BIOS_WARNING, " MC%u_ADDR = %08x_%08x\n", bank, msr.hi, msr.lo); msr = rdmsr(MCAX_MISC0_MSR(bank)); printk(BIOS_WARNING, " MC%u_MISC = %08x_%08x\n", bank, msr.hi, msr.lo); msr = rdmsr(MCAX_CTL_MSR(bank)); printk(BIOS_WARNING, " MC%u_CTL = %08x_%08x\n", bank, msr.hi, msr.lo); msr = rdmsr(MCA_CTL_MASK_MSR(bank)); printk(BIOS_WARNING, " MC%u_CTL_MASK = %08x_%08x\n", bank, msr.hi, msr.lo); } void mca_check_all_banks(void) { struct mca_bank_status mci; const unsigned int num_banks = mca_get_bank_count(); if (ARRAY_SIZE(mca_bank_name) != num_banks) printk(BIOS_WARNING, "CPU has an unexpected number of MCA banks!\n"); for (unsigned int i = 0 ; i < num_banks ; i++) { if (!mca_is_valid_bank(i)) continue; mci.bank = i; mci.sts = rdmsr(MCAX_STATUS_MSR(i)); if (mci.sts.hi || mci.sts.lo) { mca_print_error(i); if (CONFIG(ACPI_BERT) && mca_valid(mci.sts)) build_bert_mca_error(&mci); } } }