Skip to content

Commit cbe1de1

Browse files
committed
x86/mce: Get rid of machine_check_vector
Get rid of the indirect function pointer and use flags settings instead to steer execution. Now that it is not an indirect call any longer, drop the instrumentation annotation for objtool too. No functional changes. Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Tony Luck <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 631adc7 commit cbe1de1

File tree

5 files changed

+53
-55
lines changed

5 files changed

+53
-55
lines changed

arch/x86/include/asm/mce.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,6 @@ static inline int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
215215
u64 lapic_id) { return -EINVAL; }
216216
#endif
217217

218-
#ifdef CONFIG_X86_ANCIENT_MCE
219-
void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
220-
void winchip_mcheck_init(struct cpuinfo_x86 *c);
221-
static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
222-
#else
223-
static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
224-
static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
225-
static inline void enable_p5_mce(void) {}
226-
#endif
227-
228218
void mce_setup(struct mce *m);
229219
void mce_log(struct mce *m);
230220
DECLARE_PER_CPU(struct device *, mce_device);

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

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,15 @@ static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callba
13281328
task_work_add(current, &current->mce_kill_me, TWA_RESUME);
13291329
}
13301330

1331+
/* Handle unconfigured int18 (should never happen) */
1332+
static noinstr void unexpected_machine_check(struct pt_regs *regs)
1333+
{
1334+
instrumentation_begin();
1335+
pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
1336+
smp_processor_id());
1337+
instrumentation_end();
1338+
}
1339+
13311340
/*
13321341
* The actual machine check handler. This only handles real
13331342
* exceptions when something got corrupted coming in through int 18.
@@ -1348,36 +1357,43 @@ static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callba
13481357
*/
13491358
noinstr void do_machine_check(struct pt_regs *regs)
13501359
{
1360+
int worst = 0, order, no_way_out, kill_current_task, lmce;
13511361
DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
13521362
DECLARE_BITMAP(toclear, MAX_NR_BANKS);
13531363
struct mca_config *cfg = &mca_cfg;
13541364
struct mce m, *final;
13551365
char *msg = NULL;
1356-
int worst = 0;
1366+
1367+
if (unlikely(mce_flags.p5))
1368+
return pentium_machine_check(regs);
1369+
else if (unlikely(mce_flags.winchip))
1370+
return winchip_machine_check(regs);
1371+
else if (unlikely(!mca_cfg.initialized))
1372+
return unexpected_machine_check(regs);
13571373

13581374
/*
13591375
* Establish sequential order between the CPUs entering the machine
13601376
* check handler.
13611377
*/
1362-
int order = -1;
1378+
order = -1;
13631379

13641380
/*
13651381
* If no_way_out gets set, there is no safe way to recover from this
13661382
* MCE. If mca_cfg.tolerant is cranked up, we'll try anyway.
13671383
*/
1368-
int no_way_out = 0;
1384+
no_way_out = 0;
13691385

13701386
/*
13711387
* If kill_current_task is not set, there might be a way to recover from this
13721388
* error.
13731389
*/
1374-
int kill_current_task = 0;
1390+
kill_current_task = 0;
13751391

13761392
/*
13771393
* MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES
13781394
* on Intel.
13791395
*/
1380-
int lmce = 1;
1396+
lmce = 1;
13811397

13821398
this_cpu_inc(mce_exception_count);
13831399

@@ -1855,9 +1871,11 @@ static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
18551871
switch (c->x86_vendor) {
18561872
case X86_VENDOR_INTEL:
18571873
intel_p5_mcheck_init(c);
1874+
mce_flags.p5 = 1;
18581875
return 1;
18591876
case X86_VENDOR_CENTAUR:
18601877
winchip_mcheck_init(c);
1878+
mce_flags.winchip = 1;
18611879
return 1;
18621880
default:
18631881
return 0;
@@ -2012,18 +2030,6 @@ bool filter_mce(struct mce *m)
20122030
return false;
20132031
}
20142032

2015-
/* Handle unconfigured int18 (should never happen) */
2016-
static noinstr void unexpected_machine_check(struct pt_regs *regs)
2017-
{
2018-
instrumentation_begin();
2019-
pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
2020-
smp_processor_id());
2021-
instrumentation_end();
2022-
}
2023-
2024-
/* Call the installed machine check handler for this CPU setup. */
2025-
void (*machine_check_vector)(struct pt_regs *) = unexpected_machine_check;
2026-
20272033
static __always_inline void exc_machine_check_kernel(struct pt_regs *regs)
20282034
{
20292035
irqentry_state_t irq_state;
@@ -2034,31 +2040,22 @@ static __always_inline void exc_machine_check_kernel(struct pt_regs *regs)
20342040
* Only required when from kernel mode. See
20352041
* mce_check_crashing_cpu() for details.
20362042
*/
2037-
if (machine_check_vector == do_machine_check &&
2038-
mce_check_crashing_cpu())
2043+
if (mca_cfg.initialized && mce_check_crashing_cpu())
20392044
return;
20402045

20412046
irq_state = irqentry_nmi_enter(regs);
2042-
/*
2043-
* The call targets are marked noinstr, but objtool can't figure
2044-
* that out because it's an indirect call. Annotate it.
2045-
*/
2046-
instrumentation_begin();
20472047

2048-
machine_check_vector(regs);
2048+
do_machine_check(regs);
20492049

2050-
instrumentation_end();
20512050
irqentry_nmi_exit(regs, irq_state);
20522051
}
20532052

20542053
static __always_inline void exc_machine_check_user(struct pt_regs *regs)
20552054
{
20562055
irqentry_enter_from_user_mode(regs);
2057-
instrumentation_begin();
20582056

2059-
machine_check_vector(regs);
2057+
do_machine_check(regs);
20602058

2061-
instrumentation_end();
20622059
irqentry_exit_to_user_mode(regs);
20632060
}
20642061

@@ -2125,7 +2122,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
21252122
return;
21262123
}
21272124

2128-
machine_check_vector = do_machine_check;
2125+
mca_cfg.initialized = 1;
21292126

21302127
__mcheck_cpu_init_early(c);
21312128
__mcheck_cpu_init_generic();

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
#include <linux/device.h>
99
#include <asm/mce.h>
1010

11-
/* Pointer to the installed machine check handler for this CPU setup. */
12-
extern void (*machine_check_vector)(struct pt_regs *);
13-
1411
enum severity_level {
1512
MCE_NO_SEVERITY,
1613
MCE_DEFERRED_SEVERITY,
@@ -126,7 +123,9 @@ struct mca_config {
126123
ser : 1,
127124
recovery : 1,
128125
bios_cmci_threshold : 1,
129-
__reserved : 59;
126+
/* Proper #MC exception handler is set */
127+
initialized : 1,
128+
__reserved : 58;
130129

131130
s8 bootlog;
132131
int tolerant;
@@ -162,7 +161,13 @@ struct mce_vendor_flags {
162161
/* AMD-style error thresholding banks present. */
163162
amd_threshold : 1,
164163

165-
__reserved_0 : 60;
164+
/* Pentium, family 5-style MCA */
165+
p5 : 1,
166+
167+
/* Centaur Winchip C6-style MCA */
168+
winchip : 1,
169+
170+
__reserved_0 : 58;
166171
};
167172

168173
extern struct mce_vendor_flags mce_flags;
@@ -195,4 +200,18 @@ __visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
195200
unsigned long error_code,
196201
unsigned long fault_addr);
197202

203+
#ifdef CONFIG_X86_ANCIENT_MCE
204+
void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
205+
void winchip_mcheck_init(struct cpuinfo_x86 *c);
206+
noinstr void pentium_machine_check(struct pt_regs *regs);
207+
noinstr void winchip_machine_check(struct pt_regs *regs);
208+
static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
209+
#else
210+
static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
211+
static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
212+
static inline void enable_p5_mce(void) {}
213+
static inline void pentium_machine_check(struct pt_regs *regs) {}
214+
static inline void winchip_machine_check(struct pt_regs *regs) {}
215+
#endif
216+
198217
#endif /* __X86_MCE_INTERNAL_H__ */

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
int mce_p5_enabled __read_mostly;
2222

2323
/* Machine check handler for Pentium class Intel CPUs: */
24-
static noinstr void pentium_machine_check(struct pt_regs *regs)
24+
noinstr void pentium_machine_check(struct pt_regs *regs)
2525
{
2626
u32 loaddr, hi, lotype;
2727

@@ -54,10 +54,6 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
5454
if (!cpu_has(c, X86_FEATURE_MCE))
5555
return;
5656

57-
machine_check_vector = pentium_machine_check;
58-
/* Make sure the vector pointer is visible before we enable MCEs: */
59-
wmb();
60-
6157
/* Read registers before enabling: */
6258
rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
6359
rdmsr(MSR_IA32_P5_MC_TYPE, l, h);

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "internal.h"
1818

1919
/* Machine check handler for WinChip C6: */
20-
static noinstr void winchip_machine_check(struct pt_regs *regs)
20+
noinstr void winchip_machine_check(struct pt_regs *regs)
2121
{
2222
instrumentation_begin();
2323
pr_emerg("CPU0: Machine Check Exception.\n");
@@ -30,10 +30,6 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c)
3030
{
3131
u32 lo, hi;
3232

33-
machine_check_vector = winchip_machine_check;
34-
/* Make sure the vector pointer is visible before we enable MCEs: */
35-
wmb();
36-
3733
rdmsr(MSR_IDT_FCR1, lo, hi);
3834
lo |= (1<<2); /* Enable EIERRINT (int 18 MCE) */
3935
lo &= ~(1<<4); /* Enable MCE */

0 commit comments

Comments
 (0)