mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
EDAC/intel-bff: Reset bitfix filter when it overflows
Get notifications for all errors logged in machine check banks. Skip any that do not indicate a bitfix filter overflow. Machine check banks are scoped to a hardware unit, so the reset has to be issued from a CPU within that unit. Use the CPU that reported the error. Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Link: https://patch.msgid.link/20260828153002.10290-6-tony.luck@intel.com
This commit is contained in:
parent
a2808f919d
commit
666192e18f
|
|
@ -17,11 +17,14 @@
|
|||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/device-id/x86_cpu.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
|
@ -32,6 +35,11 @@
|
|||
#include <asm/msr.h>
|
||||
#include <asm/msr-index.h>
|
||||
|
||||
/* Intel bitfix filter control register defines */
|
||||
#define MSR_MC0_BFF_CTL 0x000006c0
|
||||
#define MSR_MCx_BFF_CTL(x) (MSR_MC0_BFF_CTL + (x))
|
||||
#define MCI_BFF_RESET BIT_ULL(0)
|
||||
|
||||
/* Machine check bank hardware unit types */
|
||||
enum bff_bank_type {
|
||||
BFF_BANK_NONE = 0,
|
||||
|
|
@ -64,6 +72,38 @@ MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
|
|||
|
||||
static const enum bff_bank_type *bff_bank_types;
|
||||
|
||||
static void bff_reset_and_report(struct mce *mce)
|
||||
{
|
||||
/* Reset bitfix filter using the CPU that logged the yellow status */
|
||||
if (wrmsrq_on_cpu(mce->extcpu, MSR_MCx_BFF_CTL(mce->bank), MCI_BFF_RESET))
|
||||
pr_warn("Failed to reset bitfix filter for CPU %d Bank %d\n",
|
||||
mce->extcpu, mce->bank);
|
||||
}
|
||||
|
||||
static int bff_mce_notify(struct notifier_block *nb, unsigned long val, void *data)
|
||||
{
|
||||
struct mce *mce = data;
|
||||
|
||||
/* TES is undefined for uncorrected errors. */
|
||||
if (mce->status & MCI_STATUS_UC)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (MCI_STATUS_TES(mce->status) != MCI_STATUS_TES_YELLOW)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (mce->bank >= MAX_NR_BANKS || bff_bank_types[mce->bank] == BFF_BANK_NONE)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
bff_reset_and_report(mce);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block bff_notifier = {
|
||||
.notifier_call = bff_mce_notify,
|
||||
.priority = MCE_PRIO_EDAC,
|
||||
};
|
||||
|
||||
static int __init bff_init(void)
|
||||
{
|
||||
const struct x86_cpu_id *m;
|
||||
|
|
@ -89,10 +129,18 @@ static int __init bff_init(void)
|
|||
|
||||
bff_bank_types = (const enum bff_bank_type *)m->driver_data;
|
||||
|
||||
mce_register_decode_chain(&bff_notifier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit bff_exit(void)
|
||||
{
|
||||
mce_unregister_decode_chain(&bff_notifier);
|
||||
}
|
||||
|
||||
module_init(bff_init);
|
||||
module_exit(bff_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Tony Luck");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user