static void mca_save_state(mca_state_t *mca_state) { mca_mci_bank_t *bank; unsigned int i; assert(!ml_get_interrupts_enabled() || get_preemption_level() > 0); if (mca_state == NULL) return; mca_state->mca_mcg_ctl = mca_control_MSR_present ? rdmsr64(IA32_MCG_CTL) : 0ULL; mca_state->mca_mcg_status.u64 = rdmsr64(IA32_MCG_STATUS); bank = (mca_mci_bank_t *) &mca_state->mca_error_bank[0]; for (i = 0; i < mca_error_bank_count; i++, bank++) { bank->mca_mci_ctl = rdmsr64(IA32_MCi_CTL(i)); bank->mca_mci_status.u64 = rdmsr64(IA32_MCi_STATUS(i)); if (!bank->mca_mci_status.bits.val) continue; bank->mca_mci_misc = (bank->mca_mci_status.bits.miscv)? rdmsr64(IA32_MCi_MISC(i)) : 0ULL; bank->mca_mci_addr = (bank->mca_mci_status.bits.addrv)? rdmsr64(IA32_MCi_ADDR(i)) : 0ULL; } /* * If we're the first thread with MCA state, point our package to it * and don't care about races */ if (x86_package()->mca_state == NULL) x86_package()->mca_state = mca_state; }
static void mca_dump_bank(mca_state_t *state, int i) { mca_mci_bank_t *bank; ia32_mci_status_t status; bank = &state->mca_error_bank[i]; status = bank->mca_mci_status; kdb_printf( " IA32_MC%d_STATUS(0x%x): 0x%016qx %svalid\n", i, IA32_MCi_STATUS(i), status.u64, IF(!status.bits.val, "in")); if (!status.bits.val) return; kdb_printf( " MCA error code: 0x%04x\n", status.bits.mca_error); kdb_printf( " Model specific error code: 0x%04x\n", status.bits.model_specific_error); if (!mca_threshold_status_present) { kdb_printf( " Other information: 0x%08x\n", status.bits.other_information); } else { int threshold = status.bits_tes_p.threshold; kdb_printf( " Other information: 0x%08x\n" " Threshold-based status: %s\n", status.bits_tes_p.other_information, (status.bits_tes_p.uc == 0) ? mca_threshold_status[threshold] : "Undefined"); } if (mca_threshold_status_present && mca_sw_error_recovery_present) { kdb_printf( " Software Error Recovery:\n%s%s", IF(status.bits_tes_p.ar, " Recovery action reqd\n"), IF(status.bits_tes_p.s, " Signaling UCR error\n")); } kdb_printf( " Status bits:\n%s%s%s%s%s%s", IF(status.bits.pcc, " Processor context corrupt\n"), IF(status.bits.addrv, " ADDR register valid\n"), IF(status.bits.miscv, " MISC register valid\n"), IF(status.bits.en, " Error enabled\n"), IF(status.bits.uc, " Uncorrected error\n"), IF(status.bits.over, " Error overflow\n")); if (status.bits.addrv) kdb_printf( " IA32_MC%d_ADDR(0x%x): 0x%016qx\n", i, IA32_MCi_ADDR(i), bank->mca_mci_addr); if (status.bits.miscv) kdb_printf( " IA32_MC%d_MISC(0x%x): 0x%016qx\n", i, IA32_MCi_MISC(i), bank->mca_mci_misc); }
static void mca_dump_bank(mca_state_t *state, int i) { mca_mci_bank_t *bank; ia32_mci_status_t status; bank = &state->mca_error_bank[i]; status = bank->mca_mci_status; if (!status.bits.val) return; kdb_printf(" IA32_MC%d_STATUS(0x%x): 0x%016qx\n", i, IA32_MCi_STATUS(i), status.u64); if (status.bits.addrv) kdb_printf(" IA32_MC%d_ADDR(0x%x): 0x%016qx\n", i, IA32_MCi_ADDR(i), bank->mca_mci_addr); if (status.bits.miscv) kdb_printf(" IA32_MC%d_MISC(0x%x): 0x%016qx\n", i, IA32_MCi_MISC(i), bank->mca_mci_misc); }
static void mca_dump_bank_mc8(mca_state_t *state, int i) { mca_mci_bank_t *bank; ia32_mci_status_t status; struct ia32_mc8_specific mc8; int mmm; bank = &state->mca_error_bank[i]; status = bank->mca_mci_status; mc8 = status.bits_mc8; mmm = MIN(mc8.memory_operation, MC8_MMM_RESERVED); kdb_printf( " IA32_MC%d_STATUS(0x%x): 0x%016qx %svalid\n", i, IA32_MCi_STATUS(i), status.u64, IF(!status.bits.val, "in")); if (!status.bits.val) return; kdb_printf( " Channel number: %d%s\n" " Memory Operation: %s\n" " Machine-specific error: %s%s%s%s%s%s%s%s%s\n" " COR_ERR_CNT: %d\n", mc8.channel_number, IF(mc8.channel_number == 15, " (unknown)"), mc8_memory_operation[mmm], IF(mc8.read_ecc, "Read ECC "), IF(mc8.ecc_on_a_scrub, "ECC on scrub "), IF(mc8.write_parity, "Write parity "), IF(mc8.redundant_memory, "Redundant memory "), IF(mc8.sparing, "Sparing/Resilvering "), IF(mc8.access_out_of_range, "Access out of Range "), IF(mc8.rtid_out_of_range, "RTID out of Range "), IF(mc8.address_parity, "Address Parity "), IF(mc8.byte_enable_parity, "Byte Enable Parity "), mc8.cor_err_cnt); kdb_printf( " Status bits:\n%s%s%s%s%s%s", IF(status.bits.pcc, " Processor context corrupt\n"), IF(status.bits.addrv, " ADDR register valid\n"), IF(status.bits.miscv, " MISC register valid\n"), IF(status.bits.en, " Error enabled\n"), IF(status.bits.uc, " Uncorrected error\n"), IF(status.bits.over, " Error overflow\n")); if (status.bits.addrv) kdb_printf( " IA32_MC%d_ADDR(0x%x): 0x%016qx\n", i, IA32_MCi_ADDR(i), bank->mca_mci_addr); if (status.bits.miscv) { ia32_mc8_misc_t mc8_misc; mc8_misc.u64 = bank->mca_mci_misc; kdb_printf( " IA32_MC%d_MISC(0x%x): 0x%016qx\n" " RTID: %d\n" " DIMM: %d\n" " Channel: %d\n" " Syndrome: 0x%x\n", i, IA32_MCi_MISC(i), mc8_misc.u64, mc8_misc.bits.rtid, mc8_misc.bits.dimm, mc8_misc.bits.channel, (int) mc8_misc.bits.syndrome); } }