Skip to content

Commit 0246725

Browse files
committed
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
2 parents 89f5349 + 8a01ec9 commit 0246725

File tree

5 files changed

+62
-31
lines changed

5 files changed

+62
-31
lines changed

arch/x86/include/asm/mce.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@
8888
#define MCI_MISC_ADDR_MEM 3 /* memory address */
8989
#define MCI_MISC_ADDR_GENERIC 7 /* generic */
9090

91+
/* MCi_ADDR register defines */
92+
#define MCI_ADDR_PHYSADDR GENMASK_ULL(boot_cpu_data.x86_phys_bits - 1, 0)
93+
9194
/* CTL2 register defines */
9295
#define MCI_CTL2_CMCI_EN BIT_ULL(30)
9396
#define MCI_CTL2_CMCI_THRESHOLD_MASK 0x7fffULL

arch/x86/kernel/cpu/mce/amd.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
306306
if ((low & BIT(5)) && !((high >> 5) & 0x3))
307307
high |= BIT(5);
308308

309+
this_cpu_ptr(mce_banks_array)[bank].lsb_in_status = !!(low & BIT(8));
310+
309311
wrmsr(smca_config, low, high);
310312
}
311313

@@ -736,15 +738,7 @@ static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
736738
if (m.status & MCI_STATUS_ADDRV) {
737739
m.addr = addr;
738740

739-
/*
740-
* Extract [55:<lsb>] where lsb is the least significant
741-
* *valid* bit of the address bits.
742-
*/
743-
if (mce_flags.smca) {
744-
u8 lsb = (m.addr >> 56) & 0x3f;
745-
746-
m.addr &= GENMASK_ULL(55, lsb);
747-
}
741+
smca_extract_err_addr(&m);
748742
}
749743

750744
if (mce_flags.smca) {

arch/x86/kernel/cpu/mce/core.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,7 @@ DEFINE_PER_CPU(unsigned, mce_exception_count);
6767

6868
DEFINE_PER_CPU_READ_MOSTLY(unsigned int, mce_num_banks);
6969

70-
struct mce_bank {
71-
u64 ctl; /* subevents to enable */
72-
73-
__u64 init : 1, /* initialise bank? */
74-
__reserved_1 : 63;
75-
};
76-
static DEFINE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
70+
DEFINE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
7771

7872
#define ATTR_LEN 16
7973
/* 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,
579573
mce->severity != MCE_DEFERRED_SEVERITY)
580574
return NOTIFY_DONE;
581575

582-
pfn = mce->addr >> PAGE_SHIFT;
576+
pfn = (mce->addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
583577
if (!memory_failure(pfn, 0)) {
584578
set_mce_nospec(pfn);
585579
mce->kflags |= MCE_HANDLED_UC;
@@ -633,15 +627,7 @@ static noinstr void mce_read_aux(struct mce *m, int i)
633627
m->addr <<= shift;
634628
}
635629

636-
/*
637-
* Extract [55:<lsb>] where lsb is the least significant
638-
* *valid* bit of the address bits.
639-
*/
640-
if (mce_flags.smca) {
641-
u8 lsb = (m->addr >> 56) & 0x3f;
642-
643-
m->addr &= GENMASK_ULL(55, lsb);
644-
}
630+
smca_extract_err_addr(m);
645631
}
646632

647633
if (mce_flags.smca) {
@@ -1308,6 +1294,7 @@ static void kill_me_maybe(struct callback_head *cb)
13081294
{
13091295
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
13101296
int flags = MF_ACTION_REQUIRED;
1297+
unsigned long pfn;
13111298
int ret;
13121299

13131300
p->mce_count = 0;
@@ -1316,9 +1303,10 @@ static void kill_me_maybe(struct callback_head *cb)
13161303
if (!p->mce_ripv)
13171304
flags |= MF_MUST_KILL;
13181305

1319-
ret = memory_failure(p->mce_addr >> PAGE_SHIFT, flags);
1306+
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
1307+
ret = memory_failure(pfn, flags);
13201308
if (!ret) {
1321-
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
1309+
set_mce_nospec(pfn);
13221310
sync_core();
13231311
return;
13241312
}
@@ -1340,11 +1328,13 @@ static void kill_me_maybe(struct callback_head *cb)
13401328
static void kill_me_never(struct callback_head *cb)
13411329
{
13421330
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
1331+
unsigned long pfn;
13431332

13441333
p->mce_count = 0;
13451334
pr_err("Kernel accessed poison in user space at %llx\n", p->mce_addr);
1346-
if (!memory_failure(p->mce_addr >> PAGE_SHIFT, 0))
1347-
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
1335+
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
1336+
if (!memory_failure(pfn, 0))
1337+
set_mce_nospec(pfn);
13481338
}
13491339

13501340
static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *))

arch/x86/kernel/cpu/mce/internal.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,24 @@ struct mce_vendor_flags {
177177

178178
extern struct mce_vendor_flags mce_flags;
179179

180+
struct mce_bank {
181+
/* subevents to enable */
182+
u64 ctl;
183+
184+
/* initialise bank? */
185+
__u64 init : 1,
186+
187+
/*
188+
* (AMD) MCA_CONFIG[McaLsbInStatusSupported]: When set, this bit indicates
189+
* the LSB field is found in MCA_STATUS and not in MCA_ADDR.
190+
*/
191+
lsb_in_status : 1,
192+
193+
__reserved_1 : 62;
194+
};
195+
196+
DECLARE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
197+
180198
enum mca_msr {
181199
MCA_CTL,
182200
MCA_STATUS,
@@ -189,8 +207,34 @@ extern bool filter_mce(struct mce *m);
189207

190208
#ifdef CONFIG_X86_MCE_AMD
191209
extern bool amd_filter_mce(struct mce *m);
210+
211+
/*
212+
* If MCA_CONFIG[McaLsbInStatusSupported] is set, extract ErrAddr in bits
213+
* [56:0] of MCA_STATUS, else in bits [55:0] of MCA_ADDR.
214+
*/
215+
static __always_inline void smca_extract_err_addr(struct mce *m)
216+
{
217+
u8 lsb;
218+
219+
if (!mce_flags.smca)
220+
return;
221+
222+
if (this_cpu_ptr(mce_banks_array)[m->bank].lsb_in_status) {
223+
lsb = (m->status >> 24) & 0x3f;
224+
225+
m->addr &= GENMASK_ULL(56, lsb);
226+
227+
return;
228+
}
229+
230+
lsb = (m->addr >> 56) & 0x3f;
231+
232+
m->addr &= GENMASK_ULL(55, lsb);
233+
}
234+
192235
#else
193236
static inline bool amd_filter_mce(struct mce *m) { return false; }
237+
static inline void smca_extract_err_addr(struct mce *m) { }
194238
#endif
195239

196240
#ifdef CONFIG_X86_ANCIENT_MCE

drivers/edac/skx_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
657657

658658
memset(&res, 0, sizeof(res));
659659
res.mce = mce;
660-
res.addr = mce->addr;
660+
res.addr = mce->addr & MCI_ADDR_PHYSADDR;
661661

662662
/* Try driver decoder first */
663663
if (!(driver_decode && driver_decode(&res))) {

0 commit comments

Comments
 (0)