Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'x86/nmi' into x86/core, to merge dependent commits

Prepare to resolve conflicts with an upstream series of fixes that conflict
with pending x86 changes:

6f5bf947bab0 Merge tag 'its-for-linus-20250509' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Signed-off-by: Ingo Molnar <mingo@kernel.org>

Ingo Molnar d6680b00 1f82e8e1

+121 -107
+46 -3
arch/x86/include/asm/nmi.h
··· 14 14 extern int reserve_evntsel_nmi(unsigned int); 15 15 extern void release_evntsel_nmi(unsigned int); 16 16 17 - extern int unknown_nmi_panic; 18 - 19 17 #endif /* CONFIG_X86_LOCAL_APIC */ 20 18 19 + extern int unknown_nmi_panic; 20 + extern int panic_on_unrecovered_nmi; 21 + extern int panic_on_io_nmi; 22 + 23 + /* NMI handler flags */ 21 24 #define NMI_FLAG_FIRST 1 22 25 26 + /** 27 + * enum - NMI types. 28 + * @NMI_LOCAL: Local NMI, CPU-specific NMI generated by the Local APIC. 29 + * @NMI_UNKNOWN: Unknown NMI, the source of the NMI may not be identified. 30 + * @NMI_SERR: System Error NMI, typically triggered by PCI errors. 31 + * @NMI_IO_CHECK: I/O Check NMI, related to I/O errors. 32 + * @NMI_MAX: Maximum value for NMI types. 33 + * 34 + * NMI types are used to categorize NMIs and to dispatch them to the 35 + * appropriate handler. 36 + */ 23 37 enum { 24 38 NMI_LOCAL=0, 25 39 NMI_UNKNOWN, ··· 42 28 NMI_MAX 43 29 }; 44 30 31 + /* NMI handler return values */ 45 32 #define NMI_DONE 0 46 33 #define NMI_HANDLED 1 47 34 ··· 56 41 const char *name; 57 42 }; 58 43 44 + /** 45 + * register_nmi_handler - Register a handler for a specific NMI type 46 + * @t: NMI type (e.g. NMI_LOCAL) 47 + * @fn: The NMI handler 48 + * @fg: Flags associated with the NMI handler 49 + * @n: Name of the NMI handler 50 + * @init: Optional __init* attributes for struct nmiaction 51 + * 52 + * Adds the provided handler to the list of handlers for the specified 53 + * NMI type. Handlers flagged with NMI_FLAG_FIRST would be executed first. 54 + * 55 + * Sometimes the source of an NMI can't be reliably determined which 56 + * results in an NMI being tagged as "unknown". Register an additional 57 + * handler using the NMI type - NMI_UNKNOWN to handle such cases. The 58 + * caller would get one last chance to assume responsibility for the 59 + * NMI. 60 + * 61 + * Return: 0 on success, or an error code on failure. 62 + */ 59 63 #define register_nmi_handler(t, fn, fg, n, init...) \ 60 64 ({ \ 61 65 static struct nmiaction init fn##_na = { \ ··· 88 54 89 55 int __register_nmi_handler(unsigned int, struct nmiaction *); 90 56 91 - void unregister_nmi_handler(unsigned int, const char *); 57 + /** 58 + * unregister_nmi_handler - Unregister a handler for a specific NMI type 59 + * @type: NMI type (e.g. NMI_LOCAL) 60 + * @name: Name of the NMI handler used during registration 61 + * 62 + * Removes the handler associated with the specified NMI type from the 63 + * NMI handler list. The "name" is used as a lookup key to identify the 64 + * handler. 65 + */ 66 + void unregister_nmi_handler(unsigned int type, const char *name); 92 67 93 68 void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler); 94 69
+1
arch/x86/include/asm/x86_init.h
··· 292 292 * @set_wallclock: set time back to HW clock 293 293 * @is_untracked_pat_range exclude from PAT logic 294 294 * @nmi_init enable NMI on cpus 295 + * @get_nmi_reason get the reason an NMI was received 295 296 * @save_sched_clock_state: save state for sched_clock() on suspend 296 297 * @restore_sched_clock_state: restore state for sched_clock() on resume 297 298 * @apic_post_init: adjust apic if needed
-2
arch/x86/kernel/dumpstack.c
··· 23 23 #include <asm/stacktrace.h> 24 24 #include <asm/unwind.h> 25 25 26 - int panic_on_unrecovered_nmi; 27 - int panic_on_io_nmi; 28 26 static int die_counter; 29 27 30 28 static struct pt_regs exec_summary_regs;
+43 -44
arch/x86/kernel/nmi.c
··· 49 49 struct list_head head; 50 50 }; 51 51 52 - static struct nmi_desc nmi_desc[NMI_MAX] = 53 - { 54 - { 55 - .lock = __RAW_SPIN_LOCK_UNLOCKED(&nmi_desc[0].lock), 56 - .head = LIST_HEAD_INIT(nmi_desc[0].head), 57 - }, 58 - { 59 - .lock = __RAW_SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock), 60 - .head = LIST_HEAD_INIT(nmi_desc[1].head), 61 - }, 62 - { 63 - .lock = __RAW_SPIN_LOCK_UNLOCKED(&nmi_desc[2].lock), 64 - .head = LIST_HEAD_INIT(nmi_desc[2].head), 65 - }, 66 - { 67 - .lock = __RAW_SPIN_LOCK_UNLOCKED(&nmi_desc[3].lock), 68 - .head = LIST_HEAD_INIT(nmi_desc[3].head), 69 - }, 52 + #define NMI_DESC_INIT(type) { \ 53 + .lock = __RAW_SPIN_LOCK_UNLOCKED(&nmi_desc[type].lock), \ 54 + .head = LIST_HEAD_INIT(nmi_desc[type].head), \ 55 + } 70 56 57 + static struct nmi_desc nmi_desc[NMI_MAX] = { 58 + NMI_DESC_INIT(NMI_LOCAL), 59 + NMI_DESC_INIT(NMI_UNKNOWN), 60 + NMI_DESC_INIT(NMI_SERR), 61 + NMI_DESC_INIT(NMI_IO_CHECK), 71 62 }; 63 + 64 + #define nmi_to_desc(type) (&nmi_desc[type]) 72 65 73 66 struct nmi_stats { 74 67 unsigned int normal; ··· 84 91 static int ignore_nmis __read_mostly; 85 92 86 93 int unknown_nmi_panic; 94 + int panic_on_unrecovered_nmi; 95 + int panic_on_io_nmi; 96 + 87 97 /* 88 98 * Prevent NMI reason port (0x61) being accessed simultaneously, can 89 99 * only be used in NMI handler. ··· 99 103 return 1; 100 104 } 101 105 __setup("unknown_nmi_panic", setup_unknown_nmi_panic); 102 - 103 - #define nmi_to_desc(type) (&nmi_desc[type]) 104 106 105 107 static u64 nmi_longest_ns = 1 * NSEC_PER_MSEC; 106 108 ··· 119 125 120 126 action->max_duration = duration; 121 127 122 - remainder_ns = do_div(duration, (1000 * 1000)); 123 - decimal_msecs = remainder_ns / 1000; 128 + /* Convert duration from nsec to msec */ 129 + remainder_ns = do_div(duration, NSEC_PER_MSEC); 130 + decimal_msecs = remainder_ns / NSEC_PER_USEC; 124 131 125 - printk_ratelimited(KERN_INFO 126 - "INFO: NMI handler (%ps) took too long to run: %lld.%03d msecs\n", 127 - action->handler, duration, decimal_msecs); 132 + pr_info_ratelimited("INFO: NMI handler (%ps) took too long to run: %lld.%03d msecs\n", 133 + action->handler, duration, decimal_msecs); 128 134 } 129 135 130 136 static int nmi_handle(unsigned int type, struct pt_regs *regs) ··· 327 333 int handled; 328 334 329 335 /* 330 - * Use 'false' as back-to-back NMIs are dealt with one level up. 331 - * Of course this makes having multiple 'unknown' handlers useless 332 - * as only the first one is ever run (unless it can actually determine 333 - * if it caused the NMI) 336 + * As a last resort, let the "unknown" handlers make a 337 + * best-effort attempt to figure out if they can claim 338 + * responsibility for this Unknown NMI. 334 339 */ 335 340 handled = nmi_handle(NMI_UNKNOWN, regs); 336 341 if (handled) { ··· 359 366 bool b2b = false; 360 367 361 368 /* 362 - * CPU-specific NMI must be processed before non-CPU-specific 363 - * NMI, otherwise we may lose it, because the CPU-specific 364 - * NMI can not be detected/processed on other CPUs. 365 - */ 366 - 367 - /* 368 - * Back-to-back NMIs are interesting because they can either 369 - * be two NMI or more than two NMIs (any thing over two is dropped 370 - * due to NMI being edge-triggered). If this is the second half 371 - * of the back-to-back NMI, assume we dropped things and process 372 - * more handlers. Otherwise reset the 'swallow' NMI behaviour 369 + * Back-to-back NMIs are detected by comparing the RIP of the 370 + * current NMI with that of the previous NMI. If it is the same, 371 + * it is assumed that the CPU did not have a chance to jump back 372 + * into a non-NMI context and execute code in between the two 373 + * NMIs. 374 + * 375 + * They are interesting because even if there are more than two, 376 + * only a maximum of two can be detected (anything over two is 377 + * dropped due to NMI being edge-triggered). If this is the 378 + * second half of the back-to-back NMI, assume we dropped things 379 + * and process more handlers. Otherwise, reset the 'swallow' NMI 380 + * behavior. 373 381 */ 374 382 if (regs->ip == __this_cpu_read(last_nmi_rip)) 375 383 b2b = true; ··· 384 390 if (microcode_nmi_handler_enabled() && microcode_nmi_handler()) 385 391 goto out; 386 392 393 + /* 394 + * CPU-specific NMI must be processed before non-CPU-specific 395 + * NMI, otherwise we may lose it, because the CPU-specific 396 + * NMI can not be detected/processed on other CPUs. 397 + */ 387 398 handled = nmi_handle(NMI_LOCAL, regs); 388 399 __this_cpu_add(nmi_stats.normal, handled); 389 400 if (handled) { ··· 425 426 pci_serr_error(reason, regs); 426 427 else if (reason & NMI_REASON_IOCHK) 427 428 io_check_error(reason, regs); 428 - #ifdef CONFIG_X86_32 429 + 429 430 /* 430 431 * Reassert NMI in case it became active 431 432 * meanwhile as it's edge-triggered: 432 433 */ 433 - reassert_nmi(); 434 - #endif 434 + if (IS_ENABLED(CONFIG_X86_32)) 435 + reassert_nmi(); 436 + 435 437 __this_cpu_add(nmi_stats.external, 1); 436 438 raw_spin_unlock(&nmi_reason_lock); 437 439 goto out; ··· 751 751 { 752 752 __this_cpu_write(last_nmi_rip, 0); 753 753 } 754 - EXPORT_SYMBOL_GPL(local_touch_nmi);
+16 -36
arch/x86/kernel/nmi_selftest.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * arch/x86/kernel/nmi-selftest.c 4 - * 5 3 * Testsuite for NMI: IPIs 6 4 * 7 5 * Started by Don Zickus: ··· 28 30 29 31 static int __initdata testcase_total; 30 32 static int __initdata testcase_successes; 31 - static int __initdata expected_testcase_failures; 32 33 static int __initdata unexpected_testcase_failures; 33 34 static int __initdata unexpected_testcase_unknowns; 34 35 ··· 117 120 unexpected_testcase_failures++; 118 121 119 122 if (nmi_fail == FAILURE) 120 - printk(KERN_CONT "FAILED |"); 123 + pr_cont("FAILED |"); 121 124 else if (nmi_fail == TIMEOUT) 122 - printk(KERN_CONT "TIMEOUT|"); 125 + pr_cont("TIMEOUT|"); 123 126 else 124 - printk(KERN_CONT "ERROR |"); 127 + pr_cont("ERROR |"); 125 128 dump_stack(); 126 129 } else { 127 130 testcase_successes++; 128 - printk(KERN_CONT " ok |"); 131 + pr_cont(" ok |"); 129 132 } 133 + pr_cont("\n"); 134 + 130 135 testcase_total++; 131 - 132 136 reset_nmi(); 133 - } 134 - 135 - static inline void __init print_testname(const char *testname) 136 - { 137 - printk("%12s:", testname); 138 137 } 139 138 140 139 void __init nmi_selftest(void) ··· 140 147 /* 141 148 * Run the testsuite: 142 149 */ 143 - printk("----------------\n"); 144 - printk("| NMI testsuite:\n"); 145 - printk("--------------------\n"); 150 + pr_info("----------------\n"); 151 + pr_info("| NMI testsuite:\n"); 152 + pr_info("--------------------\n"); 146 153 147 - print_testname("remote IPI"); 154 + pr_info("%12s:", "remote IPI"); 148 155 dotest(remote_ipi, SUCCESS); 149 - printk(KERN_CONT "\n"); 150 - print_testname("local IPI"); 156 + 157 + pr_info("%12s:", "local IPI"); 151 158 dotest(local_ipi, SUCCESS); 152 - printk(KERN_CONT "\n"); 153 159 154 160 cleanup_nmi_testsuite(); 155 161 162 + pr_info("--------------------\n"); 156 163 if (unexpected_testcase_failures) { 157 - printk("--------------------\n"); 158 - printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n", 164 + pr_info("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n", 159 165 unexpected_testcase_failures, testcase_total); 160 - printk("-----------------------------------------------------------------\n"); 161 - } else if (expected_testcase_failures && testcase_successes) { 162 - printk("--------------------\n"); 163 - printk("%3d out of %3d testcases failed, as expected. |\n", 164 - expected_testcase_failures, testcase_total); 165 - printk("----------------------------------------------------\n"); 166 - } else if (expected_testcase_failures && !testcase_successes) { 167 - printk("--------------------\n"); 168 - printk("All %3d testcases failed, as expected. |\n", 169 - expected_testcase_failures); 170 - printk("----------------------------------------\n"); 171 166 } else { 172 - printk("--------------------\n"); 173 - printk("Good, all %3d testcases passed! |\n", 167 + pr_info("Good, all %3d testcases passed! |\n", 174 168 testcase_successes); 175 - printk("---------------------------------\n"); 176 169 } 170 + pr_info("-----------------------------------------------------------------\n"); 177 171 }
+15 -20
arch/x86/kernel/setup.c
··· 11 11 #include <linux/crash_dump.h> 12 12 #include <linux/dma-map-ops.h> 13 13 #include <linux/efi.h> 14 + #include <linux/hugetlb.h> 14 15 #include <linux/ima.h> 15 16 #include <linux/init_ohci1394_dma.h> 16 17 #include <linux/initrd.h> ··· 19 18 #include <linux/memblock.h> 20 19 #include <linux/panic_notifier.h> 21 20 #include <linux/pci.h> 21 + #include <linux/random.h> 22 22 #include <linux/root_dev.h> 23 - #include <linux/hugetlb.h> 24 - #include <linux/tboot.h> 25 - #include <linux/usb/xhci-dbgp.h> 26 23 #include <linux/static_call.h> 27 24 #include <linux/swiotlb.h> 28 - #include <linux/random.h> 25 + #include <linux/tboot.h> 26 + #include <linux/usb/xhci-dbgp.h> 27 + #include <linux/vmalloc.h> 29 28 30 29 #include <uapi/linux/mount.h> 31 30 32 31 #include <xen/xen.h> 33 32 34 33 #include <asm/apic.h> 35 - #include <asm/efi.h> 36 - #include <asm/numa.h> 37 34 #include <asm/bios_ebda.h> 38 35 #include <asm/bugs.h> 39 36 #include <asm/cacheinfo.h> ··· 46 47 #include <asm/mce.h> 47 48 #include <asm/memtype.h> 48 49 #include <asm/mtrr.h> 49 - #include <asm/realmode.h> 50 + #include <asm/nmi.h> 51 + #include <asm/numa.h> 50 52 #include <asm/olpc_ofw.h> 51 53 #include <asm/pci-direct.h> 52 54 #include <asm/prom.h> 53 55 #include <asm/proto.h> 56 + #include <asm/realmode.h> 54 57 #include <asm/thermal.h> 55 58 #include <asm/unwind.h> 56 59 #include <asm/vsyscall.h> 57 - #include <linux/vmalloc.h> 58 - #if defined(CONFIG_X86_LOCAL_APIC) 59 - #include <asm/nmi.h> 60 - #endif 61 60 62 61 /* 63 62 * max_low_pfn_mapped: highest directly mapped pfn < 4 GB ··· 149 152 150 153 static const struct ctl_table x86_sysctl_table[] = { 151 154 { 155 + .procname = "unknown_nmi_panic", 156 + .data = &unknown_nmi_panic, 157 + .maxlen = sizeof(int), 158 + .mode = 0644, 159 + .proc_handler = proc_dointvec, 160 + }, 161 + { 152 162 .procname = "panic_on_unrecovered_nmi", 153 163 .data = &panic_on_unrecovered_nmi, 154 164 .maxlen = sizeof(int), ··· 190 186 .mode = 0644, 191 187 .proc_handler = proc_dointvec, 192 188 }, 193 - #if defined(CONFIG_X86_LOCAL_APIC) 194 - { 195 - .procname = "unknown_nmi_panic", 196 - .data = &unknown_nmi_panic, 197 - .maxlen = sizeof(int), 198 - .mode = 0644, 199 - .proc_handler = proc_dointvec, 200 - }, 201 - #endif 202 189 #if defined(CONFIG_ACPI_SLEEP) 203 190 { 204 191 .procname = "acpi_video_flags",
-2
include/linux/panic.h
··· 20 20 extern int panic_timeout; 21 21 extern unsigned long panic_print; 22 22 extern int panic_on_oops; 23 - extern int panic_on_unrecovered_nmi; 24 - extern int panic_on_io_nmi; 25 23 extern int panic_on_warn; 26 24 27 25 extern unsigned long panic_on_taint;