mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
- Add support for reporting more bits of the physical address on error,
on newer AMD CPUs - Mask out bits which don't belong to the address of the error being reported -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmPzUAEACgkQEsHwGGHe VUr22RAAh7fi3s8sDP4B2WBe1LPKZystZamxlLObBG2eLT7g0YmSKV12+bHCGf/B nGqz9iy+e/T1Khxv0gdEyuENwzuitXgiEOYgB4u70HimWy5422ZCzn1EiOMFtyST g0ehOR+tU84YwMVR40ui3spI1DHgeVPqVBLHBARZ1OAaA58N8eVREC6MqJAeAzIU +VYiBbn69quECTuU1P7yaT8NDnbm5G6pA1dhKLc7vLl9QWzoW1yWLLcp+oGFN6B8 rcGDKEDK1OYtdHScRCfhFrznkeYP6SVnSt4wlAgX+HVGPoMpvq8nJygxCWdE0yjd aQGhdcVJkQlSqm1iJUv0MK9nkolqXVVSVTurpHunAq7ctul6Qm/X+fsfwBgSIXXn Gdj3in374MLWCz/xGqeBS8IiiPxGxJA9s350jyk02LK6Np6sXeuc4PpR66+6FAKQ Ypen+uWJ6oBof04bW7DBK0R14atA8EpOOLUrrGIsSkNSEIjLaCipMZOpRCbOw76N bXcdnKKsaEDjKtHClvx/vZXklfzWk0OgF8qtY0nGF+khvDAi3pQaIIlCehf0Qemh 6j00TqIYBCXa0kuKktdPzVJSM7A7TZ5ftboa1IPhE+GYrFFee/VJ3yfgqz102FWI RJsY8JXt+EP3VMSOQYqQ5KzcLBJ2uDiRYtgUo4P1CITNpRfZEMc= =e9v9 -----END PGP SIGNATURE----- Merge tag 'ras_core_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull RAS updates from Borislav Petkov: - Add support for reporting more bits of the physical address on error, on newer AMD CPUs - Mask out bits which don't belong to the address of the error being reported * tag 'ras_core_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mce: Mask out non-address bits from machine check bank x86/mce: Add support for Extended Physical Address MCA changes x86/mce: Define a function to extract ErrorAddr from MCA_ADDR
This commit is contained in:
commit
0246725d73
5 changed files with 62 additions and 31 deletions
|
@ -88,6 +88,9 @@
|
|||
#define MCI_MISC_ADDR_MEM 3 /* memory address */
|
||||
#define MCI_MISC_ADDR_GENERIC 7 /* generic */
|
||||
|
||||
/* MCi_ADDR register defines */
|
||||
#define MCI_ADDR_PHYSADDR GENMASK_ULL(boot_cpu_data.x86_phys_bits - 1, 0)
|
||||
|
||||
/* CTL2 register defines */
|
||||
#define MCI_CTL2_CMCI_EN BIT_ULL(30)
|
||||
#define MCI_CTL2_CMCI_THRESHOLD_MASK 0x7fffULL
|
||||
|
|
|
@ -306,6 +306,8 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
|
|||
if ((low & BIT(5)) && !((high >> 5) & 0x3))
|
||||
high |= BIT(5);
|
||||
|
||||
this_cpu_ptr(mce_banks_array)[bank].lsb_in_status = !!(low & BIT(8));
|
||||
|
||||
wrmsr(smca_config, low, high);
|
||||
}
|
||||
|
||||
|
@ -736,15 +738,7 @@ static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
|
|||
if (m.status & MCI_STATUS_ADDRV) {
|
||||
m.addr = addr;
|
||||
|
||||
/*
|
||||
* Extract [55:<lsb>] where lsb is the least significant
|
||||
* *valid* bit of the address bits.
|
||||
*/
|
||||
if (mce_flags.smca) {
|
||||
u8 lsb = (m.addr >> 56) & 0x3f;
|
||||
|
||||
m.addr &= GENMASK_ULL(55, lsb);
|
||||
}
|
||||
smca_extract_err_addr(&m);
|
||||
}
|
||||
|
||||
if (mce_flags.smca) {
|
||||
|
|
|
@ -67,13 +67,7 @@ DEFINE_PER_CPU(unsigned, mce_exception_count);
|
|||
|
||||
DEFINE_PER_CPU_READ_MOSTLY(unsigned int, mce_num_banks);
|
||||
|
||||
struct mce_bank {
|
||||
u64 ctl; /* subevents to enable */
|
||||
|
||||
__u64 init : 1, /* initialise bank? */
|
||||
__reserved_1 : 63;
|
||||
};
|
||||
static DEFINE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
|
||||
DEFINE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
|
||||
|
||||
#define ATTR_LEN 16
|
||||
/* One object for each MCE bank, shared by all CPUs */
|
||||
|
@ -579,7 +573,7 @@ static int uc_decode_notifier(struct notifier_block *nb, unsigned long val,
|
|||
mce->severity != MCE_DEFERRED_SEVERITY)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
pfn = mce->addr >> PAGE_SHIFT;
|
||||
pfn = (mce->addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
|
||||
if (!memory_failure(pfn, 0)) {
|
||||
set_mce_nospec(pfn);
|
||||
mce->kflags |= MCE_HANDLED_UC;
|
||||
|
@ -633,15 +627,7 @@ static noinstr void mce_read_aux(struct mce *m, int i)
|
|||
m->addr <<= shift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract [55:<lsb>] where lsb is the least significant
|
||||
* *valid* bit of the address bits.
|
||||
*/
|
||||
if (mce_flags.smca) {
|
||||
u8 lsb = (m->addr >> 56) & 0x3f;
|
||||
|
||||
m->addr &= GENMASK_ULL(55, lsb);
|
||||
}
|
||||
smca_extract_err_addr(m);
|
||||
}
|
||||
|
||||
if (mce_flags.smca) {
|
||||
|
@ -1308,6 +1294,7 @@ static void kill_me_maybe(struct callback_head *cb)
|
|||
{
|
||||
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
|
||||
int flags = MF_ACTION_REQUIRED;
|
||||
unsigned long pfn;
|
||||
int ret;
|
||||
|
||||
p->mce_count = 0;
|
||||
|
@ -1316,9 +1303,10 @@ static void kill_me_maybe(struct callback_head *cb)
|
|||
if (!p->mce_ripv)
|
||||
flags |= MF_MUST_KILL;
|
||||
|
||||
ret = memory_failure(p->mce_addr >> PAGE_SHIFT, flags);
|
||||
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
|
||||
ret = memory_failure(pfn, flags);
|
||||
if (!ret) {
|
||||
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
|
||||
set_mce_nospec(pfn);
|
||||
sync_core();
|
||||
return;
|
||||
}
|
||||
|
@ -1340,11 +1328,13 @@ static void kill_me_maybe(struct callback_head *cb)
|
|||
static void kill_me_never(struct callback_head *cb)
|
||||
{
|
||||
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
|
||||
unsigned long pfn;
|
||||
|
||||
p->mce_count = 0;
|
||||
pr_err("Kernel accessed poison in user space at %llx\n", p->mce_addr);
|
||||
if (!memory_failure(p->mce_addr >> PAGE_SHIFT, 0))
|
||||
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
|
||||
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
|
||||
if (!memory_failure(pfn, 0))
|
||||
set_mce_nospec(pfn);
|
||||
}
|
||||
|
||||
static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *))
|
||||
|
|
|
@ -177,6 +177,24 @@ struct mce_vendor_flags {
|
|||
|
||||
extern struct mce_vendor_flags mce_flags;
|
||||
|
||||
struct mce_bank {
|
||||
/* subevents to enable */
|
||||
u64 ctl;
|
||||
|
||||
/* initialise bank? */
|
||||
__u64 init : 1,
|
||||
|
||||
/*
|
||||
* (AMD) MCA_CONFIG[McaLsbInStatusSupported]: When set, this bit indicates
|
||||
* the LSB field is found in MCA_STATUS and not in MCA_ADDR.
|
||||
*/
|
||||
lsb_in_status : 1,
|
||||
|
||||
__reserved_1 : 62;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
|
||||
|
||||
enum mca_msr {
|
||||
MCA_CTL,
|
||||
MCA_STATUS,
|
||||
|
@ -189,8 +207,34 @@ extern bool filter_mce(struct mce *m);
|
|||
|
||||
#ifdef CONFIG_X86_MCE_AMD
|
||||
extern bool amd_filter_mce(struct mce *m);
|
||||
|
||||
/*
|
||||
* If MCA_CONFIG[McaLsbInStatusSupported] is set, extract ErrAddr in bits
|
||||
* [56:0] of MCA_STATUS, else in bits [55:0] of MCA_ADDR.
|
||||
*/
|
||||
static __always_inline void smca_extract_err_addr(struct mce *m)
|
||||
{
|
||||
u8 lsb;
|
||||
|
||||
if (!mce_flags.smca)
|
||||
return;
|
||||
|
||||
if (this_cpu_ptr(mce_banks_array)[m->bank].lsb_in_status) {
|
||||
lsb = (m->status >> 24) & 0x3f;
|
||||
|
||||
m->addr &= GENMASK_ULL(56, lsb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lsb = (m->addr >> 56) & 0x3f;
|
||||
|
||||
m->addr &= GENMASK_ULL(55, lsb);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline bool amd_filter_mce(struct mce *m) { return false; }
|
||||
static inline void smca_extract_err_addr(struct mce *m) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_ANCIENT_MCE
|
||||
|
|
|
@ -657,7 +657,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
|
|||
|
||||
memset(&res, 0, sizeof(res));
|
||||
res.mce = mce;
|
||||
res.addr = mce->addr;
|
||||
res.addr = mce->addr & MCI_ADDR_PHYSADDR;
|
||||
|
||||
/* Try driver decoder first */
|
||||
if (!(driver_decode && driver_decode(&res))) {
|
||||
|
|
Loading…
Add table
Reference in a new issue