diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 18:37:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 18:37:06 -0500 |
commit | 4f19b8803bddbecbd8c3ac44a2cfadd9d2b85b8f (patch) | |
tree | 8abc90bf4c31f6ce9575e3611f21368ff65341ac | |
parent | af345201ea948d0976d775958d8aa22fe5e5ba58 (diff) | |
parent | c8f3e518d3444ee9200a4987421fcee60f768f11 (diff) |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 apic updates from Ingo Molnar:
"The main changes in this cycle were:
- introduce optimized single IPI sending methods on modern APICs
(Linus Torvalds, Thomas Gleixner)
- kexec/crash APIC handling fixes and enhancements (Hidehiro Kawai)
- extend lapic vector saving/restoring to the CMCI (MCE) vector as
well (Juergen Gross)
- various fixes and enhancements (Jake Oshins, Len Brown)"
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
x86/irq: Export functions to allow MSI domains in modules
Documentation: Document kernel.panic_on_io_nmi sysctl
x86/nmi: Save regs in crash dump on external NMI
x86/apic: Introduce apic_extnmi command line parameter
kexec: Fix race between panic() and crash_kexec()
panic, x86: Allow CPUs to save registers even if looping in NMI context
panic, x86: Fix re-entrance problem due to panic on NMI
x86/apic: Fix the saving and restoring of lapic vectors during suspend/resume
x86/smpboot: Re-enable init_udelay=0 by default on modern CPUs
x86/smp: Remove single IPI wrapper
x86/apic: Use default send single IPI wrapper
x86/apic: Provide default send single IPI wrapper
x86/apic: Implement single IPI for apic_noop
x86/apic: Wire up single IPI for apic_numachip
x86/apic: Wire up single IPI for x2apic_uv
x86/apic: Implement single IPI for x2apic_phys
x86/apic: Wire up single IPI for bigsmp_apic
x86/apic: Remove pointless indirections from bigsmp_apic
x86/apic: Wire up single IPI for apic_physflat
x86/apic: Remove pointless indirections from apic_physflat
...
26 files changed, 284 insertions, 42 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d8186da15ca1..1a44a7a7f71d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -472,6 +472,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
472 | Change the amount of debugging information output | 472 | Change the amount of debugging information output |
473 | when initialising the APIC and IO-APIC components. | 473 | when initialising the APIC and IO-APIC components. |
474 | 474 | ||
475 | apic_extnmi= [APIC,X86] External NMI delivery setting | ||
476 | Format: { bsp (default) | all | none } | ||
477 | bsp: External NMI is delivered only to CPU 0 | ||
478 | all: External NMIs are broadcast to all CPUs as a | ||
479 | backup of CPU 0 | ||
480 | none: External NMI is masked for all CPUs. This is | ||
481 | useful so that a dump capture kernel won't be | ||
482 | shot down by NMI | ||
483 | |||
475 | autoconf= [IPV6] | 484 | autoconf= [IPV6] |
476 | See Documentation/networking/ipv6.txt. | 485 | See Documentation/networking/ipv6.txt. |
477 | 486 | ||
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index af70d1541d3a..73c6b1ef0e84 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
@@ -551,6 +551,21 @@ the recommended setting is 60. | |||
551 | 551 | ||
552 | ============================================================== | 552 | ============================================================== |
553 | 553 | ||
554 | panic_on_io_nmi: | ||
555 | |||
556 | Controls the kernel's behavior when a CPU receives an NMI caused by | ||
557 | an IO error. | ||
558 | |||
559 | 0: try to continue operation (default) | ||
560 | |||
561 | 1: panic immediately. The IO error triggered an NMI. This indicates a | ||
562 | serious system condition which could result in IO data corruption. | ||
563 | Rather than continuing, panicking might be a better choice. Some | ||
564 | servers issue this sort of NMI when the dump button is pushed, | ||
565 | and you can use this option to take a crash dump. | ||
566 | |||
567 | ============================================================== | ||
568 | |||
554 | panic_on_oops: | 569 | panic_on_oops: |
555 | 570 | ||
556 | Controls the kernel's behaviour when an oops or BUG is encountered. | 571 | Controls the kernel's behaviour when an oops or BUG is encountered. |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index a30316bf801a..c80f6b6f3da2 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -23,6 +23,11 @@ | |||
23 | #define APIC_VERBOSE 1 | 23 | #define APIC_VERBOSE 1 |
24 | #define APIC_DEBUG 2 | 24 | #define APIC_DEBUG 2 |
25 | 25 | ||
26 | /* Macros for apic_extnmi which controls external NMI masking */ | ||
27 | #define APIC_EXTNMI_BSP 0 /* Default */ | ||
28 | #define APIC_EXTNMI_ALL 1 | ||
29 | #define APIC_EXTNMI_NONE 2 | ||
30 | |||
26 | /* | 31 | /* |
27 | * Define the default level of output to be very little | 32 | * Define the default level of output to be very little |
28 | * This can be turned up by using apic=verbose for more | 33 | * This can be turned up by using apic=verbose for more |
@@ -303,6 +308,7 @@ struct apic { | |||
303 | unsigned int *apicid); | 308 | unsigned int *apicid); |
304 | 309 | ||
305 | /* ipi */ | 310 | /* ipi */ |
311 | void (*send_IPI)(int cpu, int vector); | ||
306 | void (*send_IPI_mask)(const struct cpumask *mask, int vector); | 312 | void (*send_IPI_mask)(const struct cpumask *mask, int vector); |
307 | void (*send_IPI_mask_allbutself)(const struct cpumask *mask, | 313 | void (*send_IPI_mask_allbutself)(const struct cpumask *mask, |
308 | int vector); | 314 | int vector); |
diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index 615fa9061b57..cfc9a0d2d07c 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h | |||
@@ -119,6 +119,8 @@ static inline void | |||
119 | native_apic_mem_write(APIC_ICR, cfg); | 119 | native_apic_mem_write(APIC_ICR, cfg); |
120 | } | 120 | } |
121 | 121 | ||
122 | extern void default_send_IPI_single(int cpu, int vector); | ||
123 | extern void default_send_IPI_single_phys(int cpu, int vector); | ||
122 | extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, | 124 | extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, |
123 | int vector); | 125 | int vector); |
124 | extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, | 126 | extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, |
diff --git a/arch/x86/include/asm/msi.h b/arch/x86/include/asm/msi.h index 93724cc62177..eb4b09b41df5 100644 --- a/arch/x86/include/asm/msi.h +++ b/arch/x86/include/asm/msi.h | |||
@@ -1,7 +1,13 @@ | |||
1 | #ifndef _ASM_X86_MSI_H | 1 | #ifndef _ASM_X86_MSI_H |
2 | #define _ASM_X86_MSI_H | 2 | #define _ASM_X86_MSI_H |
3 | #include <asm/hw_irq.h> | 3 | #include <asm/hw_irq.h> |
4 | #include <asm/irqdomain.h> | ||
4 | 5 | ||
5 | typedef struct irq_alloc_info msi_alloc_info_t; | 6 | typedef struct irq_alloc_info msi_alloc_info_t; |
6 | 7 | ||
8 | int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, | ||
9 | msi_alloc_info_t *arg); | ||
10 | |||
11 | void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc); | ||
12 | |||
7 | #endif /* _ASM_X86_MSI_H */ | 13 | #endif /* _ASM_X86_MSI_H */ |
diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index a82c4f1b4d83..2cb1cc253d51 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h | |||
@@ -25,5 +25,6 @@ void __noreturn machine_real_restart(unsigned int type); | |||
25 | 25 | ||
26 | typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); | 26 | typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); |
27 | void nmi_shootdown_cpus(nmi_shootdown_cb callback); | 27 | void nmi_shootdown_cpus(nmi_shootdown_cb callback); |
28 | void run_crash_ipi_callback(struct pt_regs *regs); | ||
28 | 29 | ||
29 | #endif /* _ASM_X86_REBOOT_H */ | 30 | #endif /* _ASM_X86_REBOOT_H */ |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 2f69e3b184f6..8a5cddac7d44 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -82,6 +82,12 @@ physid_mask_t phys_cpu_present_map; | |||
82 | static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID; | 82 | static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID; |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * This variable controls which CPUs receive external NMIs. By default, | ||
86 | * external NMIs are delivered only to the BSP. | ||
87 | */ | ||
88 | static int apic_extnmi = APIC_EXTNMI_BSP; | ||
89 | |||
90 | /* | ||
85 | * Map cpu index to physical APIC ID | 91 | * Map cpu index to physical APIC ID |
86 | */ | 92 | */ |
87 | DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); | 93 | DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); |
@@ -1161,6 +1167,8 @@ void __init init_bsp_APIC(void) | |||
1161 | value = APIC_DM_NMI; | 1167 | value = APIC_DM_NMI; |
1162 | if (!lapic_is_integrated()) /* 82489DX */ | 1168 | if (!lapic_is_integrated()) /* 82489DX */ |
1163 | value |= APIC_LVT_LEVEL_TRIGGER; | 1169 | value |= APIC_LVT_LEVEL_TRIGGER; |
1170 | if (apic_extnmi == APIC_EXTNMI_NONE) | ||
1171 | value |= APIC_LVT_MASKED; | ||
1164 | apic_write(APIC_LVT1, value); | 1172 | apic_write(APIC_LVT1, value); |
1165 | } | 1173 | } |
1166 | 1174 | ||
@@ -1378,9 +1386,11 @@ void setup_local_APIC(void) | |||
1378 | apic_write(APIC_LVT0, value); | 1386 | apic_write(APIC_LVT0, value); |
1379 | 1387 | ||
1380 | /* | 1388 | /* |
1381 | * only the BP should see the LINT1 NMI signal, obviously. | 1389 | * Only the BSP sees the LINT1 NMI signal by default. This can be |
1390 | * modified by apic_extnmi= boot option. | ||
1382 | */ | 1391 | */ |
1383 | if (!cpu) | 1392 | if ((!cpu && apic_extnmi != APIC_EXTNMI_NONE) || |
1393 | apic_extnmi == APIC_EXTNMI_ALL) | ||
1384 | value = APIC_DM_NMI; | 1394 | value = APIC_DM_NMI; |
1385 | else | 1395 | else |
1386 | value = APIC_DM_NMI | APIC_LVT_MASKED; | 1396 | value = APIC_DM_NMI | APIC_LVT_MASKED; |
@@ -2270,6 +2280,7 @@ static struct { | |||
2270 | unsigned int apic_tmict; | 2280 | unsigned int apic_tmict; |
2271 | unsigned int apic_tdcr; | 2281 | unsigned int apic_tdcr; |
2272 | unsigned int apic_thmr; | 2282 | unsigned int apic_thmr; |
2283 | unsigned int apic_cmci; | ||
2273 | } apic_pm_state; | 2284 | } apic_pm_state; |
2274 | 2285 | ||
2275 | static int lapic_suspend(void) | 2286 | static int lapic_suspend(void) |
@@ -2299,6 +2310,10 @@ static int lapic_suspend(void) | |||
2299 | if (maxlvt >= 5) | 2310 | if (maxlvt >= 5) |
2300 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 2311 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); |
2301 | #endif | 2312 | #endif |
2313 | #ifdef CONFIG_X86_MCE_INTEL | ||
2314 | if (maxlvt >= 6) | ||
2315 | apic_pm_state.apic_cmci = apic_read(APIC_LVTCMCI); | ||
2316 | #endif | ||
2302 | 2317 | ||
2303 | local_irq_save(flags); | 2318 | local_irq_save(flags); |
2304 | disable_local_APIC(); | 2319 | disable_local_APIC(); |
@@ -2355,10 +2370,14 @@ static void lapic_resume(void) | |||
2355 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | 2370 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); |
2356 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | 2371 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); |
2357 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | 2372 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); |
2358 | #if defined(CONFIG_X86_MCE_INTEL) | 2373 | #ifdef CONFIG_X86_THERMAL_VECTOR |
2359 | if (maxlvt >= 5) | 2374 | if (maxlvt >= 5) |
2360 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | 2375 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); |
2361 | #endif | 2376 | #endif |
2377 | #ifdef CONFIG_X86_MCE_INTEL | ||
2378 | if (maxlvt >= 6) | ||
2379 | apic_write(APIC_LVTCMCI, apic_pm_state.apic_cmci); | ||
2380 | #endif | ||
2362 | if (maxlvt >= 4) | 2381 | if (maxlvt >= 4) |
2363 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | 2382 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); |
2364 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); | 2383 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); |
@@ -2548,3 +2567,23 @@ static int __init apic_set_disabled_cpu_apicid(char *arg) | |||
2548 | return 0; | 2567 | return 0; |
2549 | } | 2568 | } |
2550 | early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid); | 2569 | early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid); |
2570 | |||
2571 | static int __init apic_set_extnmi(char *arg) | ||
2572 | { | ||
2573 | if (!arg) | ||
2574 | return -EINVAL; | ||
2575 | |||
2576 | if (!strncmp("all", arg, 3)) | ||
2577 | apic_extnmi = APIC_EXTNMI_ALL; | ||
2578 | else if (!strncmp("none", arg, 4)) | ||
2579 | apic_extnmi = APIC_EXTNMI_NONE; | ||
2580 | else if (!strncmp("bsp", arg, 3)) | ||
2581 | apic_extnmi = APIC_EXTNMI_BSP; | ||
2582 | else { | ||
2583 | pr_warn("Unknown external NMI delivery mode `%s' ignored\n", arg); | ||
2584 | return -EINVAL; | ||
2585 | } | ||
2586 | |||
2587 | return 0; | ||
2588 | } | ||
2589 | early_param("apic_extnmi", apic_set_extnmi); | ||
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index f92ab36979a2..9968f30cca3e 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
@@ -185,6 +185,7 @@ static struct apic apic_flat = { | |||
185 | 185 | ||
186 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, | 186 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, |
187 | 187 | ||
188 | .send_IPI = default_send_IPI_single, | ||
188 | .send_IPI_mask = flat_send_IPI_mask, | 189 | .send_IPI_mask = flat_send_IPI_mask, |
189 | .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, | 190 | .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, |
190 | .send_IPI_allbutself = flat_send_IPI_allbutself, | 191 | .send_IPI_allbutself = flat_send_IPI_allbutself, |
@@ -230,17 +231,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
230 | return 0; | 231 | return 0; |
231 | } | 232 | } |
232 | 233 | ||
233 | static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) | ||
234 | { | ||
235 | default_send_IPI_mask_sequence_phys(cpumask, vector); | ||
236 | } | ||
237 | |||
238 | static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask, | ||
239 | int vector) | ||
240 | { | ||
241 | default_send_IPI_mask_allbutself_phys(cpumask, vector); | ||
242 | } | ||
243 | |||
244 | static void physflat_send_IPI_allbutself(int vector) | 234 | static void physflat_send_IPI_allbutself(int vector) |
245 | { | 235 | { |
246 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | 236 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); |
@@ -248,7 +238,7 @@ static void physflat_send_IPI_allbutself(int vector) | |||
248 | 238 | ||
249 | static void physflat_send_IPI_all(int vector) | 239 | static void physflat_send_IPI_all(int vector) |
250 | { | 240 | { |
251 | physflat_send_IPI_mask(cpu_online_mask, vector); | 241 | default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); |
252 | } | 242 | } |
253 | 243 | ||
254 | static int physflat_probe(void) | 244 | static int physflat_probe(void) |
@@ -292,8 +282,9 @@ static struct apic apic_physflat = { | |||
292 | 282 | ||
293 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, | 283 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
294 | 284 | ||
295 | .send_IPI_mask = physflat_send_IPI_mask, | 285 | .send_IPI = default_send_IPI_single_phys, |
296 | .send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself, | 286 | .send_IPI_mask = default_send_IPI_mask_sequence_phys, |
287 | .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_phys, | ||
297 | .send_IPI_allbutself = physflat_send_IPI_allbutself, | 288 | .send_IPI_allbutself = physflat_send_IPI_allbutself, |
298 | .send_IPI_all = physflat_send_IPI_all, | 289 | .send_IPI_all = physflat_send_IPI_all, |
299 | .send_IPI_self = apic_send_IPI_self, | 290 | .send_IPI_self = apic_send_IPI_self, |
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 0d96749cfcac..331a7a07c48f 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/e820.h> | 30 | #include <asm/e820.h> |
31 | 31 | ||
32 | static void noop_init_apic_ldr(void) { } | 32 | static void noop_init_apic_ldr(void) { } |
33 | static void noop_send_IPI(int cpu, int vector) { } | ||
33 | static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { } | 34 | static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { } |
34 | static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { } | 35 | static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { } |
35 | static void noop_send_IPI_allbutself(int vector) { } | 36 | static void noop_send_IPI_allbutself(int vector) { } |
@@ -144,6 +145,7 @@ struct apic apic_noop = { | |||
144 | 145 | ||
145 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, | 146 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, |
146 | 147 | ||
148 | .send_IPI = noop_send_IPI, | ||
147 | .send_IPI_mask = noop_send_IPI_mask, | 149 | .send_IPI_mask = noop_send_IPI_mask, |
148 | .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself, | 150 | .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself, |
149 | .send_IPI_allbutself = noop_send_IPI_allbutself, | 151 | .send_IPI_allbutself = noop_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 2bd2292a316d..c80c02c6ec49 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c | |||
@@ -273,6 +273,7 @@ static const struct apic apic_numachip1 __refconst = { | |||
273 | 273 | ||
274 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, | 274 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
275 | 275 | ||
276 | .send_IPI = numachip_send_IPI_one, | ||
276 | .send_IPI_mask = numachip_send_IPI_mask, | 277 | .send_IPI_mask = numachip_send_IPI_mask, |
277 | .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, | 278 | .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, |
278 | .send_IPI_allbutself = numachip_send_IPI_allbutself, | 279 | .send_IPI_allbutself = numachip_send_IPI_allbutself, |
@@ -324,6 +325,7 @@ static const struct apic apic_numachip2 __refconst = { | |||
324 | 325 | ||
325 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, | 326 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
326 | 327 | ||
328 | .send_IPI = numachip_send_IPI_one, | ||
327 | .send_IPI_mask = numachip_send_IPI_mask, | 329 | .send_IPI_mask = numachip_send_IPI_mask, |
328 | .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, | 330 | .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, |
329 | .send_IPI_allbutself = numachip_send_IPI_allbutself, | 331 | .send_IPI_allbutself = numachip_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 971cf8875939..cf9bd896c12d 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c | |||
@@ -96,11 +96,6 @@ static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | |||
96 | return cpuid_apic >> index_msb; | 96 | return cpuid_apic >> index_msb; |
97 | } | 97 | } |
98 | 98 | ||
99 | static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector) | ||
100 | { | ||
101 | default_send_IPI_mask_sequence_phys(mask, vector); | ||
102 | } | ||
103 | |||
104 | static void bigsmp_send_IPI_allbutself(int vector) | 99 | static void bigsmp_send_IPI_allbutself(int vector) |
105 | { | 100 | { |
106 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | 101 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); |
@@ -108,7 +103,7 @@ static void bigsmp_send_IPI_allbutself(int vector) | |||
108 | 103 | ||
109 | static void bigsmp_send_IPI_all(int vector) | 104 | static void bigsmp_send_IPI_all(int vector) |
110 | { | 105 | { |
111 | bigsmp_send_IPI_mask(cpu_online_mask, vector); | 106 | default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); |
112 | } | 107 | } |
113 | 108 | ||
114 | static int dmi_bigsmp; /* can be set by dmi scanners */ | 109 | static int dmi_bigsmp; /* can be set by dmi scanners */ |
@@ -180,7 +175,8 @@ static struct apic apic_bigsmp = { | |||
180 | 175 | ||
181 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, | 176 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
182 | 177 | ||
183 | .send_IPI_mask = bigsmp_send_IPI_mask, | 178 | .send_IPI = default_send_IPI_single_phys, |
179 | .send_IPI_mask = default_send_IPI_mask_sequence_phys, | ||
184 | .send_IPI_mask_allbutself = NULL, | 180 | .send_IPI_mask_allbutself = NULL, |
185 | .send_IPI_allbutself = bigsmp_send_IPI_allbutself, | 181 | .send_IPI_allbutself = bigsmp_send_IPI_allbutself, |
186 | .send_IPI_all = bigsmp_send_IPI_all, | 182 | .send_IPI_all = bigsmp_send_IPI_all, |
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 62071569bd50..eb45fc9b6124 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c | |||
@@ -18,6 +18,16 @@ | |||
18 | #include <asm/proto.h> | 18 | #include <asm/proto.h> |
19 | #include <asm/ipi.h> | 19 | #include <asm/ipi.h> |
20 | 20 | ||
21 | void default_send_IPI_single_phys(int cpu, int vector) | ||
22 | { | ||
23 | unsigned long flags; | ||
24 | |||
25 | local_irq_save(flags); | ||
26 | __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, cpu), | ||
27 | vector, APIC_DEST_PHYSICAL); | ||
28 | local_irq_restore(flags); | ||
29 | } | ||
30 | |||
21 | void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) | 31 | void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) |
22 | { | 32 | { |
23 | unsigned long query_cpu; | 33 | unsigned long query_cpu; |
@@ -55,6 +65,14 @@ void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, | |||
55 | local_irq_restore(flags); | 65 | local_irq_restore(flags); |
56 | } | 66 | } |
57 | 67 | ||
68 | /* | ||
69 | * Helper function for APICs which insist on cpumasks | ||
70 | */ | ||
71 | void default_send_IPI_single(int cpu, int vector) | ||
72 | { | ||
73 | apic->send_IPI_mask(cpumask_of(cpu), vector); | ||
74 | } | ||
75 | |||
58 | #ifdef CONFIG_X86_32 | 76 | #ifdef CONFIG_X86_32 |
59 | 77 | ||
60 | void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, | 78 | void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, |
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c index 5f1feb6854af..ade25320df96 100644 --- a/arch/x86/kernel/apic/msi.c +++ b/arch/x86/kernel/apic/msi.c | |||
@@ -96,8 +96,8 @@ static irq_hw_number_t pci_msi_get_hwirq(struct msi_domain_info *info, | |||
96 | return arg->msi_hwirq; | 96 | return arg->msi_hwirq; |
97 | } | 97 | } |
98 | 98 | ||
99 | static int pci_msi_prepare(struct irq_domain *domain, struct device *dev, | 99 | int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, |
100 | int nvec, msi_alloc_info_t *arg) | 100 | msi_alloc_info_t *arg) |
101 | { | 101 | { |
102 | struct pci_dev *pdev = to_pci_dev(dev); | 102 | struct pci_dev *pdev = to_pci_dev(dev); |
103 | struct msi_desc *desc = first_pci_msi_entry(pdev); | 103 | struct msi_desc *desc = first_pci_msi_entry(pdev); |
@@ -113,11 +113,13 @@ static int pci_msi_prepare(struct irq_domain *domain, struct device *dev, | |||
113 | 113 | ||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | EXPORT_SYMBOL_GPL(pci_msi_prepare); | ||
116 | 117 | ||
117 | static void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) | 118 | void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) |
118 | { | 119 | { |
119 | arg->msi_hwirq = pci_msi_domain_calc_hwirq(arg->msi_dev, desc); | 120 | arg->msi_hwirq = pci_msi_domain_calc_hwirq(arg->msi_dev, desc); |
120 | } | 121 | } |
122 | EXPORT_SYMBOL_GPL(pci_msi_set_desc); | ||
121 | 123 | ||
122 | static struct msi_domain_ops pci_msi_domain_ops = { | 124 | static struct msi_domain_ops pci_msi_domain_ops = { |
123 | .get_hwirq = pci_msi_get_hwirq, | 125 | .get_hwirq = pci_msi_get_hwirq, |
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 7694ae6c1199..f316e34abb42 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
@@ -105,6 +105,7 @@ static struct apic apic_default = { | |||
105 | 105 | ||
106 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, | 106 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, |
107 | 107 | ||
108 | .send_IPI = default_send_IPI_single, | ||
108 | .send_IPI_mask = default_send_IPI_mask_logical, | 109 | .send_IPI_mask = default_send_IPI_mask_logical, |
109 | .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical, | 110 | .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical, |
110 | .send_IPI_allbutself = default_send_IPI_allbutself, | 111 | .send_IPI_allbutself = default_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 861bc59c8f25..908cb37da171 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
@@ -29,6 +29,7 @@ struct apic_chip_data { | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | struct irq_domain *x86_vector_domain; | 31 | struct irq_domain *x86_vector_domain; |
32 | EXPORT_SYMBOL_GPL(x86_vector_domain); | ||
32 | static DEFINE_RAW_SPINLOCK(vector_lock); | 33 | static DEFINE_RAW_SPINLOCK(vector_lock); |
33 | static cpumask_var_t vector_cpumask; | 34 | static cpumask_var_t vector_cpumask; |
34 | static struct irq_chip lapic_controller; | 35 | static struct irq_chip lapic_controller; |
@@ -66,6 +67,7 @@ struct irq_cfg *irqd_cfg(struct irq_data *irq_data) | |||
66 | 67 | ||
67 | return data ? &data->cfg : NULL; | 68 | return data ? &data->cfg : NULL; |
68 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(irqd_cfg); | ||
69 | 71 | ||
70 | struct irq_cfg *irq_cfg(unsigned int irq) | 72 | struct irq_cfg *irq_cfg(unsigned int irq) |
71 | { | 73 | { |
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index cc8311c4d298..aca8b75c1552 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -23,6 +23,14 @@ static inline u32 x2apic_cluster(int cpu) | |||
23 | return per_cpu(x86_cpu_to_logical_apicid, cpu) >> 16; | 23 | return per_cpu(x86_cpu_to_logical_apicid, cpu) >> 16; |
24 | } | 24 | } |
25 | 25 | ||
26 | static void x2apic_send_IPI(int cpu, int vector) | ||
27 | { | ||
28 | u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
29 | |||
30 | x2apic_wrmsr_fence(); | ||
31 | __x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL); | ||
32 | } | ||
33 | |||
26 | static void | 34 | static void |
27 | __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) | 35 | __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) |
28 | { | 36 | { |
@@ -266,6 +274,7 @@ static struct apic apic_x2apic_cluster = { | |||
266 | 274 | ||
267 | .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, | 275 | .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, |
268 | 276 | ||
277 | .send_IPI = x2apic_send_IPI, | ||
269 | .send_IPI_mask = x2apic_send_IPI_mask, | 278 | .send_IPI_mask = x2apic_send_IPI_mask, |
270 | .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, | 279 | .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, |
271 | .send_IPI_allbutself = x2apic_send_IPI_allbutself, | 280 | .send_IPI_allbutself = x2apic_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 662e9150ea6f..a1242e2c12e6 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c | |||
@@ -36,6 +36,14 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
36 | return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); | 36 | return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); |
37 | } | 37 | } |
38 | 38 | ||
39 | static void x2apic_send_IPI(int cpu, int vector) | ||
40 | { | ||
41 | u32 dest = per_cpu(x86_cpu_to_apicid, cpu); | ||
42 | |||
43 | x2apic_wrmsr_fence(); | ||
44 | __x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL); | ||
45 | } | ||
46 | |||
39 | static void | 47 | static void |
40 | __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) | 48 | __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) |
41 | { | 49 | { |
@@ -122,6 +130,7 @@ static struct apic apic_x2apic_phys = { | |||
122 | 130 | ||
123 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, | 131 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
124 | 132 | ||
133 | .send_IPI = x2apic_send_IPI, | ||
125 | .send_IPI_mask = x2apic_send_IPI_mask, | 134 | .send_IPI_mask = x2apic_send_IPI_mask, |
126 | .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, | 135 | .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, |
127 | .send_IPI_allbutself = x2apic_send_IPI_allbutself, | 136 | .send_IPI_allbutself = x2apic_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 4a139465f1d4..d760c6bb37b5 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -406,6 +406,7 @@ static struct apic __refdata apic_x2apic_uv_x = { | |||
406 | 406 | ||
407 | .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and, | 407 | .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and, |
408 | 408 | ||
409 | .send_IPI = uv_send_IPI_one, | ||
409 | .send_IPI_mask = uv_send_IPI_mask, | 410 | .send_IPI_mask = uv_send_IPI_mask, |
410 | .send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself, | 411 | .send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself, |
411 | .send_IPI_allbutself = uv_send_IPI_allbutself, | 412 | .send_IPI_allbutself = uv_send_IPI_allbutself, |
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 697f90db0e37..8a2cdd736fa4 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/mach_traps.h> | 29 | #include <asm/mach_traps.h> |
30 | #include <asm/nmi.h> | 30 | #include <asm/nmi.h> |
31 | #include <asm/x86_init.h> | 31 | #include <asm/x86_init.h> |
32 | #include <asm/reboot.h> | ||
32 | 33 | ||
33 | #define CREATE_TRACE_POINTS | 34 | #define CREATE_TRACE_POINTS |
34 | #include <trace/events/nmi.h> | 35 | #include <trace/events/nmi.h> |
@@ -231,7 +232,7 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs) | |||
231 | #endif | 232 | #endif |
232 | 233 | ||
233 | if (panic_on_unrecovered_nmi) | 234 | if (panic_on_unrecovered_nmi) |
234 | panic("NMI: Not continuing"); | 235 | nmi_panic(regs, "NMI: Not continuing"); |
235 | 236 | ||
236 | pr_emerg("Dazed and confused, but trying to continue\n"); | 237 | pr_emerg("Dazed and confused, but trying to continue\n"); |
237 | 238 | ||
@@ -255,8 +256,16 @@ io_check_error(unsigned char reason, struct pt_regs *regs) | |||
255 | reason, smp_processor_id()); | 256 | reason, smp_processor_id()); |
256 | show_regs(regs); | 257 | show_regs(regs); |
257 | 258 | ||
258 | if (panic_on_io_nmi) | 259 | if (panic_on_io_nmi) { |
259 | panic("NMI IOCK error: Not continuing"); | 260 | nmi_panic(regs, "NMI IOCK error: Not continuing"); |
261 | |||
262 | /* | ||
263 | * If we end up here, it means we have received an NMI while | ||
264 | * processing panic(). Simply return without delaying and | ||
265 | * re-enabling NMIs. | ||
266 | */ | ||
267 | return; | ||
268 | } | ||
260 | 269 | ||
261 | /* Re-enable the IOCK line, wait for a few seconds */ | 270 | /* Re-enable the IOCK line, wait for a few seconds */ |
262 | reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK; | 271 | reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK; |
@@ -297,7 +306,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) | |||
297 | 306 | ||
298 | pr_emerg("Do you have a strange power saving mode enabled?\n"); | 307 | pr_emerg("Do you have a strange power saving mode enabled?\n"); |
299 | if (unknown_nmi_panic || panic_on_unrecovered_nmi) | 308 | if (unknown_nmi_panic || panic_on_unrecovered_nmi) |
300 | panic("NMI: Not continuing"); | 309 | nmi_panic(regs, "NMI: Not continuing"); |
301 | 310 | ||
302 | pr_emerg("Dazed and confused, but trying to continue\n"); | 311 | pr_emerg("Dazed and confused, but trying to continue\n"); |
303 | } | 312 | } |
@@ -348,8 +357,19 @@ static void default_do_nmi(struct pt_regs *regs) | |||
348 | return; | 357 | return; |
349 | } | 358 | } |
350 | 359 | ||
351 | /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ | 360 | /* |
352 | raw_spin_lock(&nmi_reason_lock); | 361 | * Non-CPU-specific NMI: NMI sources can be processed on any CPU. |
362 | * | ||
363 | * Another CPU may be processing panic routines while holding | ||
364 | * nmi_reason_lock. Check if the CPU issued the IPI for crash dumping, | ||
365 | * and if so, call its callback directly. If there is no CPU preparing | ||
366 | * crash dump, we simply loop here. | ||
367 | */ | ||
368 | while (!raw_spin_trylock(&nmi_reason_lock)) { | ||
369 | run_crash_ipi_callback(regs); | ||
370 | cpu_relax(); | ||
371 | } | ||
372 | |||
353 | reason = x86_platform.get_nmi_reason(); | 373 | reason = x86_platform.get_nmi_reason(); |
354 | 374 | ||
355 | if (reason & NMI_REASON_MASK) { | 375 | if (reason & NMI_REASON_MASK) { |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 02693dd9a079..d64889aa2d46 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -718,6 +718,7 @@ static int crashing_cpu; | |||
718 | static nmi_shootdown_cb shootdown_callback; | 718 | static nmi_shootdown_cb shootdown_callback; |
719 | 719 | ||
720 | static atomic_t waiting_for_crash_ipi; | 720 | static atomic_t waiting_for_crash_ipi; |
721 | static int crash_ipi_issued; | ||
721 | 722 | ||
722 | static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) | 723 | static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) |
723 | { | 724 | { |
@@ -780,6 +781,9 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) | |||
780 | 781 | ||
781 | smp_send_nmi_allbutself(); | 782 | smp_send_nmi_allbutself(); |
782 | 783 | ||
784 | /* Kick CPUs looping in NMI context. */ | ||
785 | WRITE_ONCE(crash_ipi_issued, 1); | ||
786 | |||
783 | msecs = 1000; /* Wait at most a second for the other cpus to stop */ | 787 | msecs = 1000; /* Wait at most a second for the other cpus to stop */ |
784 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { | 788 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { |
785 | mdelay(1); | 789 | mdelay(1); |
@@ -788,9 +792,35 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) | |||
788 | 792 | ||
789 | /* Leave the nmi callback set */ | 793 | /* Leave the nmi callback set */ |
790 | } | 794 | } |
795 | |||
796 | /* | ||
797 | * Check if the crash dumping IPI got issued and if so, call its callback | ||
798 | * directly. This function is used when we have already been in NMI handler. | ||
799 | * It doesn't return. | ||
800 | */ | ||
801 | void run_crash_ipi_callback(struct pt_regs *regs) | ||
802 | { | ||
803 | if (crash_ipi_issued) | ||
804 | crash_nmi_callback(0, regs); | ||
805 | } | ||
806 | |||
807 | /* Override the weak function in kernel/panic.c */ | ||
808 | void nmi_panic_self_stop(struct pt_regs *regs) | ||
809 | { | ||
810 | while (1) { | ||
811 | /* If no CPU is preparing crash dump, we simply loop here. */ | ||
812 | run_crash_ipi_callback(regs); | ||
813 | cpu_relax(); | ||
814 | } | ||
815 | } | ||
816 | |||
791 | #else /* !CONFIG_SMP */ | 817 | #else /* !CONFIG_SMP */ |
792 | void nmi_shootdown_cpus(nmi_shootdown_cb callback) | 818 | void nmi_shootdown_cpus(nmi_shootdown_cb callback) |
793 | { | 819 | { |
794 | /* No other CPUs to shoot down */ | 820 | /* No other CPUs to shoot down */ |
795 | } | 821 | } |
822 | |||
823 | void run_crash_ipi_callback(struct pt_regs *regs) | ||
824 | { | ||
825 | } | ||
796 | #endif | 826 | #endif |
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 12c8286206ce..658777cf3851 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
@@ -125,12 +125,12 @@ static void native_smp_send_reschedule(int cpu) | |||
125 | WARN_ON(1); | 125 | WARN_ON(1); |
126 | return; | 126 | return; |
127 | } | 127 | } |
128 | apic->send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR); | 128 | apic->send_IPI(cpu, RESCHEDULE_VECTOR); |
129 | } | 129 | } |
130 | 130 | ||
131 | void native_send_call_func_single_ipi(int cpu) | 131 | void native_send_call_func_single_ipi(int cpu) |
132 | { | 132 | { |
133 | apic->send_IPI_mask(cpumask_of(cpu), CALL_FUNCTION_SINGLE_VECTOR); | 133 | apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR); |
134 | } | 134 | } |
135 | 135 | ||
136 | void native_send_call_func_ipi(const struct cpumask *mask) | 136 | void native_send_call_func_ipi(const struct cpumask *mask) |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 350dfb08aee3..7311c3294e25 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -255,6 +255,7 @@ extern long (*panic_blink)(int state); | |||
255 | __printf(1, 2) | 255 | __printf(1, 2) |
256 | void panic(const char *fmt, ...) | 256 | void panic(const char *fmt, ...) |
257 | __noreturn __cold; | 257 | __noreturn __cold; |
258 | void nmi_panic_self_stop(struct pt_regs *); | ||
258 | extern void oops_enter(void); | 259 | extern void oops_enter(void); |
259 | extern void oops_exit(void); | 260 | extern void oops_exit(void); |
260 | void print_oops_end_marker(void); | 261 | void print_oops_end_marker(void); |
@@ -446,6 +447,33 @@ extern int sysctl_panic_on_stackoverflow; | |||
446 | extern bool crash_kexec_post_notifiers; | 447 | extern bool crash_kexec_post_notifiers; |
447 | 448 | ||
448 | /* | 449 | /* |
450 | * panic_cpu is used for synchronizing panic() and crash_kexec() execution. It | ||
451 | * holds a CPU number which is executing panic() currently. A value of | ||
452 | * PANIC_CPU_INVALID means no CPU has entered panic() or crash_kexec(). | ||
453 | */ | ||
454 | extern atomic_t panic_cpu; | ||
455 | #define PANIC_CPU_INVALID -1 | ||
456 | |||
457 | /* | ||
458 | * A variant of panic() called from NMI context. We return if we've already | ||
459 | * panicked on this CPU. If another CPU already panicked, loop in | ||
460 | * nmi_panic_self_stop() which can provide architecture dependent code such | ||
461 | * as saving register state for crash dump. | ||
462 | */ | ||
463 | #define nmi_panic(regs, fmt, ...) \ | ||
464 | do { \ | ||
465 | int old_cpu, cpu; \ | ||
466 | \ | ||
467 | cpu = raw_smp_processor_id(); \ | ||
468 | old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, cpu); \ | ||
469 | \ | ||
470 | if (old_cpu == PANIC_CPU_INVALID) \ | ||
471 | panic(fmt, ##__VA_ARGS__); \ | ||
472 | else if (old_cpu != cpu) \ | ||
473 | nmi_panic_self_stop(regs); \ | ||
474 | } while (0) | ||
475 | |||
476 | /* | ||
449 | * Only to be used by arch init code. If the user over-wrote the default | 477 | * Only to be used by arch init code. If the user over-wrote the default |
450 | * CONFIG_PANIC_TIMEOUT, honor it. | 478 | * CONFIG_PANIC_TIMEOUT, honor it. |
451 | */ | 479 | */ |
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index d140b1e9faa7..7b68d2788a56 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
@@ -237,6 +237,7 @@ extern int kexec_purgatory_get_set_symbol(struct kimage *image, | |||
237 | unsigned int size, bool get_value); | 237 | unsigned int size, bool get_value); |
238 | extern void *kexec_purgatory_get_symbol_addr(struct kimage *image, | 238 | extern void *kexec_purgatory_get_symbol_addr(struct kimage *image, |
239 | const char *name); | 239 | const char *name); |
240 | extern void __crash_kexec(struct pt_regs *); | ||
240 | extern void crash_kexec(struct pt_regs *); | 241 | extern void crash_kexec(struct pt_regs *); |
241 | int kexec_should_crash(struct task_struct *); | 242 | int kexec_should_crash(struct task_struct *); |
242 | void crash_save_cpu(struct pt_regs *regs, int cpu); | 243 | void crash_save_cpu(struct pt_regs *regs, int cpu); |
@@ -332,6 +333,7 @@ int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
332 | #else /* !CONFIG_KEXEC_CORE */ | 333 | #else /* !CONFIG_KEXEC_CORE */ |
333 | struct pt_regs; | 334 | struct pt_regs; |
334 | struct task_struct; | 335 | struct task_struct; |
336 | static inline void __crash_kexec(struct pt_regs *regs) { } | ||
335 | static inline void crash_kexec(struct pt_regs *regs) { } | 337 | static inline void crash_kexec(struct pt_regs *regs) { } |
336 | static inline int kexec_should_crash(struct task_struct *p) { return 0; } | 338 | static inline int kexec_should_crash(struct task_struct *p) { return 0; } |
337 | #define kexec_in_progress false | 339 | #define kexec_in_progress false |
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 11b64a63c0f8..c823f3001e12 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c | |||
@@ -853,7 +853,12 @@ struct kimage *kexec_image; | |||
853 | struct kimage *kexec_crash_image; | 853 | struct kimage *kexec_crash_image; |
854 | int kexec_load_disabled; | 854 | int kexec_load_disabled; |
855 | 855 | ||
856 | void crash_kexec(struct pt_regs *regs) | 856 | /* |
857 | * No panic_cpu check version of crash_kexec(). This function is called | ||
858 | * only when panic_cpu holds the current CPU number; this is the only CPU | ||
859 | * which processes crash_kexec routines. | ||
860 | */ | ||
861 | void __crash_kexec(struct pt_regs *regs) | ||
857 | { | 862 | { |
858 | /* Take the kexec_mutex here to prevent sys_kexec_load | 863 | /* Take the kexec_mutex here to prevent sys_kexec_load |
859 | * running on one cpu from replacing the crash kernel | 864 | * running on one cpu from replacing the crash kernel |
@@ -876,6 +881,29 @@ void crash_kexec(struct pt_regs *regs) | |||
876 | } | 881 | } |
877 | } | 882 | } |
878 | 883 | ||
884 | void crash_kexec(struct pt_regs *regs) | ||
885 | { | ||
886 | int old_cpu, this_cpu; | ||
887 | |||
888 | /* | ||
889 | * Only one CPU is allowed to execute the crash_kexec() code as with | ||
890 | * panic(). Otherwise parallel calls of panic() and crash_kexec() | ||
891 | * may stop each other. To exclude them, we use panic_cpu here too. | ||
892 | */ | ||
893 | this_cpu = raw_smp_processor_id(); | ||
894 | old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu); | ||
895 | if (old_cpu == PANIC_CPU_INVALID) { | ||
896 | /* This is the 1st CPU which comes here, so go ahead. */ | ||
897 | __crash_kexec(regs); | ||
898 | |||
899 | /* | ||
900 | * Reset panic_cpu to allow another panic()/crash_kexec() | ||
901 | * call. | ||
902 | */ | ||
903 | atomic_set(&panic_cpu, PANIC_CPU_INVALID); | ||
904 | } | ||
905 | } | ||
906 | |||
879 | size_t crash_get_memory_size(void) | 907 | size_t crash_get_memory_size(void) |
880 | { | 908 | { |
881 | size_t size = 0; | 909 | size_t size = 0; |
diff --git a/kernel/panic.c b/kernel/panic.c index 4b150bc0c6c1..b333380c6bb2 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -61,6 +61,17 @@ void __weak panic_smp_self_stop(void) | |||
61 | cpu_relax(); | 61 | cpu_relax(); |
62 | } | 62 | } |
63 | 63 | ||
64 | /* | ||
65 | * Stop ourselves in NMI context if another CPU has already panicked. Arch code | ||
66 | * may override this to prepare for crash dumping, e.g. save regs info. | ||
67 | */ | ||
68 | void __weak nmi_panic_self_stop(struct pt_regs *regs) | ||
69 | { | ||
70 | panic_smp_self_stop(); | ||
71 | } | ||
72 | |||
73 | atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID); | ||
74 | |||
64 | /** | 75 | /** |
65 | * panic - halt the system | 76 | * panic - halt the system |
66 | * @fmt: The text string to print | 77 | * @fmt: The text string to print |
@@ -71,17 +82,17 @@ void __weak panic_smp_self_stop(void) | |||
71 | */ | 82 | */ |
72 | void panic(const char *fmt, ...) | 83 | void panic(const char *fmt, ...) |
73 | { | 84 | { |
74 | static DEFINE_SPINLOCK(panic_lock); | ||
75 | static char buf[1024]; | 85 | static char buf[1024]; |
76 | va_list args; | 86 | va_list args; |
77 | long i, i_next = 0; | 87 | long i, i_next = 0; |
78 | int state = 0; | 88 | int state = 0; |
89 | int old_cpu, this_cpu; | ||
79 | 90 | ||
80 | /* | 91 | /* |
81 | * Disable local interrupts. This will prevent panic_smp_self_stop | 92 | * Disable local interrupts. This will prevent panic_smp_self_stop |
82 | * from deadlocking the first cpu that invokes the panic, since | 93 | * from deadlocking the first cpu that invokes the panic, since |
83 | * there is nothing to prevent an interrupt handler (that runs | 94 | * there is nothing to prevent an interrupt handler (that runs |
84 | * after the panic_lock is acquired) from invoking panic again. | 95 | * after setting panic_cpu) from invoking panic() again. |
85 | */ | 96 | */ |
86 | local_irq_disable(); | 97 | local_irq_disable(); |
87 | 98 | ||
@@ -94,8 +105,16 @@ void panic(const char *fmt, ...) | |||
94 | * multiple parallel invocations of panic, all other CPUs either | 105 | * multiple parallel invocations of panic, all other CPUs either |
95 | * stop themself or will wait until they are stopped by the 1st CPU | 106 | * stop themself or will wait until they are stopped by the 1st CPU |
96 | * with smp_send_stop(). | 107 | * with smp_send_stop(). |
108 | * | ||
109 | * `old_cpu == PANIC_CPU_INVALID' means this is the 1st CPU which | ||
110 | * comes here, so go ahead. | ||
111 | * `old_cpu == this_cpu' means we came from nmi_panic() which sets | ||
112 | * panic_cpu to this CPU. In this case, this is also the 1st CPU. | ||
97 | */ | 113 | */ |
98 | if (!spin_trylock(&panic_lock)) | 114 | this_cpu = raw_smp_processor_id(); |
115 | old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu); | ||
116 | |||
117 | if (old_cpu != PANIC_CPU_INVALID && old_cpu != this_cpu) | ||
99 | panic_smp_self_stop(); | 118 | panic_smp_self_stop(); |
100 | 119 | ||
101 | console_verbose(); | 120 | console_verbose(); |
@@ -117,9 +136,11 @@ void panic(const char *fmt, ...) | |||
117 | * everything else. | 136 | * everything else. |
118 | * If we want to run this after calling panic_notifiers, pass | 137 | * If we want to run this after calling panic_notifiers, pass |
119 | * the "crash_kexec_post_notifiers" option to the kernel. | 138 | * the "crash_kexec_post_notifiers" option to the kernel. |
139 | * | ||
140 | * Bypass the panic_cpu check and call __crash_kexec directly. | ||
120 | */ | 141 | */ |
121 | if (!crash_kexec_post_notifiers) | 142 | if (!crash_kexec_post_notifiers) |
122 | crash_kexec(NULL); | 143 | __crash_kexec(NULL); |
123 | 144 | ||
124 | /* | 145 | /* |
125 | * Note smp_send_stop is the usual smp shutdown function, which | 146 | * Note smp_send_stop is the usual smp shutdown function, which |
@@ -142,9 +163,11 @@ void panic(const char *fmt, ...) | |||
142 | * panic_notifiers and dumping kmsg before kdump. | 163 | * panic_notifiers and dumping kmsg before kdump. |
143 | * Note: since some panic_notifiers can make crashed kernel | 164 | * Note: since some panic_notifiers can make crashed kernel |
144 | * more unstable, it can increase risks of the kdump failure too. | 165 | * more unstable, it can increase risks of the kdump failure too. |
166 | * | ||
167 | * Bypass the panic_cpu check and call __crash_kexec directly. | ||
145 | */ | 168 | */ |
146 | if (crash_kexec_post_notifiers) | 169 | if (crash_kexec_post_notifiers) |
147 | crash_kexec(NULL); | 170 | __crash_kexec(NULL); |
148 | 171 | ||
149 | bust_spinlocks(0); | 172 | bust_spinlocks(0); |
150 | 173 | ||
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 18f34cf75f74..84b5035cb6a5 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
@@ -351,7 +351,7 @@ static void watchdog_overflow_callback(struct perf_event *event, | |||
351 | trigger_allbutself_cpu_backtrace(); | 351 | trigger_allbutself_cpu_backtrace(); |
352 | 352 | ||
353 | if (hardlockup_panic) | 353 | if (hardlockup_panic) |
354 | panic("Hard LOCKUP"); | 354 | nmi_panic(regs, "Hard LOCKUP"); |
355 | 355 | ||
356 | __this_cpu_write(hard_watchdog_warn, true); | 356 | __this_cpu_write(hard_watchdog_warn, true); |
357 | return; | 357 | return; |