Skip to content

Commit f051f69

Browse files
committed
x86/nmi: Protect NMI entry against instrumentation
Mark all functions in the fragile code parts noinstr or force inlining so they can't be instrumented. Also make the hardware latency tracer invocation explicit outside of non-instrumentable section. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Acked-by: Peter Zijlstra <[email protected]> Acked-by: Andy Lutomirski <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 6271fef commit f051f69

File tree

3 files changed

+15
-14
lines changed

3 files changed

+15
-14
lines changed

arch/x86/include/asm/desc.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static inline void native_load_gdt(const struct desc_ptr *dtr)
214214
asm volatile("lgdt %0"::"m" (*dtr));
215215
}
216216

217-
static inline void native_load_idt(const struct desc_ptr *dtr)
217+
static __always_inline void native_load_idt(const struct desc_ptr *dtr)
218218
{
219219
asm volatile("lidt %0"::"m" (*dtr));
220220
}
@@ -392,15 +392,15 @@ extern unsigned long system_vectors[];
392392

393393
#ifdef CONFIG_X86_64
394394
DECLARE_PER_CPU(u32, debug_idt_ctr);
395-
static inline bool is_debug_idt_enabled(void)
395+
static __always_inline bool is_debug_idt_enabled(void)
396396
{
397397
if (this_cpu_read(debug_idt_ctr))
398398
return true;
399399

400400
return false;
401401
}
402402

403-
static inline void load_debug_idt(void)
403+
static __always_inline void load_debug_idt(void)
404404
{
405405
load_idt((const struct desc_ptr *)&debug_idt_descr);
406406
}
@@ -422,7 +422,7 @@ static inline void load_debug_idt(void)
422422
* that doesn't need to disable interrupts, as nothing should be
423423
* bothering the CPU then.
424424
*/
425-
static inline void load_current_idt(void)
425+
static __always_inline void load_current_idt(void)
426426
{
427427
if (is_debug_idt_enabled())
428428
load_debug_idt();

arch/x86/kernel/cpu/common.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,21 +1709,19 @@ void syscall_init(void)
17091709
DEFINE_PER_CPU(int, debug_stack_usage);
17101710
DEFINE_PER_CPU(u32, debug_idt_ctr);
17111711

1712-
void debug_stack_set_zero(void)
1712+
noinstr void debug_stack_set_zero(void)
17131713
{
17141714
this_cpu_inc(debug_idt_ctr);
17151715
load_current_idt();
17161716
}
1717-
NOKPROBE_SYMBOL(debug_stack_set_zero);
17181717

1719-
void debug_stack_reset(void)
1718+
noinstr void debug_stack_reset(void)
17201719
{
17211720
if (WARN_ON(!this_cpu_read(debug_idt_ctr)))
17221721
return;
17231722
if (this_cpu_dec_return(debug_idt_ctr) == 0)
17241723
load_current_idt();
17251724
}
1726-
NOKPROBE_SYMBOL(debug_stack_reset);
17271725

17281726
#else /* CONFIG_X86_64 */
17291727

arch/x86/kernel/nmi.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ NOKPROBE_SYMBOL(unknown_nmi_error);
303303
static DEFINE_PER_CPU(bool, swallow_nmi);
304304
static DEFINE_PER_CPU(unsigned long, last_nmi_rip);
305305

306-
static void default_do_nmi(struct pt_regs *regs)
306+
static noinstr void default_do_nmi(struct pt_regs *regs)
307307
{
308308
unsigned char reason = 0;
309309
int handled;
@@ -329,6 +329,8 @@ static void default_do_nmi(struct pt_regs *regs)
329329

330330
__this_cpu_write(last_nmi_rip, regs->ip);
331331

332+
instrumentation_begin();
333+
332334
handled = nmi_handle(NMI_LOCAL, regs);
333335
__this_cpu_add(nmi_stats.normal, handled);
334336
if (handled) {
@@ -342,7 +344,7 @@ static void default_do_nmi(struct pt_regs *regs)
342344
*/
343345
if (handled > 1)
344346
__this_cpu_write(swallow_nmi, true);
345-
return;
347+
goto out;
346348
}
347349

348350
/*
@@ -374,7 +376,7 @@ static void default_do_nmi(struct pt_regs *regs)
374376
#endif
375377
__this_cpu_add(nmi_stats.external, 1);
376378
raw_spin_unlock(&nmi_reason_lock);
377-
return;
379+
goto out;
378380
}
379381
raw_spin_unlock(&nmi_reason_lock);
380382

@@ -412,8 +414,10 @@ static void default_do_nmi(struct pt_regs *regs)
412414
__this_cpu_add(nmi_stats.swallow, 1);
413415
else
414416
unknown_nmi_error(reason, regs);
417+
418+
out:
419+
instrumentation_end();
415420
}
416-
NOKPROBE_SYMBOL(default_do_nmi);
417421

418422
/*
419423
* NMIs can page fault or hit breakpoints which will cause it to lose
@@ -485,7 +489,7 @@ static DEFINE_PER_CPU(unsigned long, nmi_cr2);
485489
*/
486490
static DEFINE_PER_CPU(int, update_debug_stack);
487491

488-
static bool notrace is_debug_stack(unsigned long addr)
492+
static noinstr bool is_debug_stack(unsigned long addr)
489493
{
490494
struct cea_exception_stacks *cs = __this_cpu_read(cea_exception_stacks);
491495
unsigned long top = CEA_ESTACK_TOP(cs, DB);
@@ -500,7 +504,6 @@ static bool notrace is_debug_stack(unsigned long addr)
500504
*/
501505
return addr >= bot && addr < top;
502506
}
503-
NOKPROBE_SYMBOL(is_debug_stack);
504507
#endif
505508

506509
DEFINE_IDTENTRY_NMI(exc_nmi)

0 commit comments

Comments
 (0)