Skip to content

Commit c725505

Browse files
hbathinimpe
authored andcommitted
powerpc/crash: save cpu register data in crash_smp_send_stop()
During kdump, two set of NMI IPIs are sent to secondary CPUs, if 'crash_kexec_post_notifiers' option is set. The first set of NMI IPIs to stop the CPUs and the other set to collect register data. Instead, capture register data for secondary CPUs while stopping them itself. Also, fallback to smp_send_stop() in case the function gets called without kdump configured. Signed-off-by: Hari Bathini <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 51ac6d4 commit c725505

File tree

3 files changed

+57
-50
lines changed

3 files changed

+57
-50
lines changed

arch/powerpc/include/asm/kexec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs);
8383
extern int crash_shutdown_register(crash_shutdown_t handler);
8484
extern int crash_shutdown_unregister(crash_shutdown_t handler);
8585

86+
extern void crash_kexec_prepare(void);
8687
extern void crash_kexec_secondary(struct pt_regs *regs);
8788
int __init overlaps_crashkernel(unsigned long start, unsigned long size);
8889
extern void reserve_crashkernel(void);

arch/powerpc/kernel/smp.c

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/stackprotector.h>
3636
#include <linux/pgtable.h>
3737
#include <linux/clockchips.h>
38+
#include <linux/kexec.h>
3839

3940
#include <asm/ptrace.h>
4041
#include <linux/atomic.h>
@@ -55,7 +56,6 @@
5556
#endif
5657
#include <asm/vdso.h>
5758
#include <asm/debug.h>
58-
#include <asm/kexec.h>
5959
#include <asm/cpu_has_feature.h>
6060
#include <asm/ftrace.h>
6161
#include <asm/kup.h>
@@ -619,20 +619,6 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
619619
}
620620
#endif
621621

622-
#ifdef CONFIG_NMI_IPI
623-
static void crash_stop_this_cpu(struct pt_regs *regs)
624-
#else
625-
static void crash_stop_this_cpu(void *dummy)
626-
#endif
627-
{
628-
/*
629-
* Just busy wait here and avoid marking CPU as offline to ensure
630-
* register data is captured appropriately.
631-
*/
632-
while (1)
633-
cpu_relax();
634-
}
635-
636622
void crash_smp_send_stop(void)
637623
{
638624
static bool stopped = false;
@@ -651,11 +637,14 @@ void crash_smp_send_stop(void)
651637

652638
stopped = true;
653639

654-
#ifdef CONFIG_NMI_IPI
655-
smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, crash_stop_this_cpu, 1000000);
656-
#else
657-
smp_call_function(crash_stop_this_cpu, NULL, 0);
658-
#endif /* CONFIG_NMI_IPI */
640+
#ifdef CONFIG_KEXEC_CORE
641+
if (kexec_crash_image) {
642+
crash_kexec_prepare();
643+
return;
644+
}
645+
#endif
646+
647+
smp_send_stop();
659648
}
660649

661650
#ifdef CONFIG_NMI_IPI

arch/powerpc/kexec/crash.c

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
#define REAL_MODE_TIMEOUT 10000
4141

4242
static int time_to_dump;
43+
44+
/*
45+
* In case of system reset, secondary CPUs enter crash_kexec_secondary with out
46+
* having to send an IPI explicitly. So, indicate if the crash is via
47+
* system reset to avoid sending another IPI.
48+
*/
49+
static int is_via_system_reset;
50+
4351
/*
4452
* crash_wake_offline should be set to 1 by platforms that intend to wake
4553
* up offline cpus prior to jumping to a kdump kernel. Currently powernv
@@ -101,7 +109,7 @@ void crash_ipi_callback(struct pt_regs *regs)
101109
/* NOTREACHED */
102110
}
103111

104-
static void crash_kexec_prepare_cpus(int cpu)
112+
static void crash_kexec_prepare_cpus(void)
105113
{
106114
unsigned int msecs;
107115
volatile unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
@@ -113,7 +121,15 @@ static void crash_kexec_prepare_cpus(int cpu)
113121
if (crash_wake_offline)
114122
ncpus = num_present_cpus() - 1;
115123

116-
crash_send_ipi(crash_ipi_callback);
124+
/*
125+
* If we came in via system reset, secondaries enter via crash_kexec_secondary().
126+
* So, wait a while for the secondary CPUs to enter for that case.
127+
* Else, send IPI to all other CPUs.
128+
*/
129+
if (is_via_system_reset)
130+
mdelay(PRIMARY_TIMEOUT);
131+
else
132+
crash_send_ipi(crash_ipi_callback);
117133
smp_wmb();
118134

119135
again:
@@ -202,7 +218,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
202218

203219
#else /* ! CONFIG_SMP */
204220

205-
static void crash_kexec_prepare_cpus(int cpu)
221+
static void crash_kexec_prepare_cpus(void)
206222
{
207223
/*
208224
* move the secondaries to us so that we can copy
@@ -248,6 +264,32 @@ noinstr static void __maybe_unused crash_kexec_wait_realmode(int cpu)
248264
static inline void crash_kexec_wait_realmode(int cpu) {}
249265
#endif /* CONFIG_SMP && CONFIG_PPC64 */
250266

267+
void crash_kexec_prepare(void)
268+
{
269+
/* Avoid hardlocking with irresponsive CPU holding logbuf_lock */
270+
printk_deferred_enter();
271+
272+
/*
273+
* This function is only called after the system
274+
* has panicked or is otherwise in a critical state.
275+
* The minimum amount of code to allow a kexec'd kernel
276+
* to run successfully needs to happen here.
277+
*
278+
* In practice this means stopping other cpus in
279+
* an SMP system.
280+
* The kernel is broken so disable interrupts.
281+
*/
282+
hard_irq_disable();
283+
284+
/*
285+
* Make a note of crashing cpu. Will be used in machine_kexec
286+
* such that another IPI will not be sent.
287+
*/
288+
crashing_cpu = smp_processor_id();
289+
290+
crash_kexec_prepare_cpus();
291+
}
292+
251293
/*
252294
* Register a function to be called on shutdown. Only use this if you
253295
* can't reset your device in the second kernel.
@@ -311,35 +353,10 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
311353
unsigned int i;
312354
int (*old_handler)(struct pt_regs *regs);
313355

314-
/* Avoid hardlocking with irresponsive CPU holding logbuf_lock */
315-
printk_deferred_enter();
316-
317-
/*
318-
* This function is only called after the system
319-
* has panicked or is otherwise in a critical state.
320-
* The minimum amount of code to allow a kexec'd kernel
321-
* to run successfully needs to happen here.
322-
*
323-
* In practice this means stopping other cpus in
324-
* an SMP system.
325-
* The kernel is broken so disable interrupts.
326-
*/
327-
hard_irq_disable();
328-
329-
/*
330-
* Make a note of crashing cpu. Will be used in machine_kexec
331-
* such that another IPI will not be sent.
332-
*/
333-
crashing_cpu = smp_processor_id();
334-
335-
/*
336-
* If we came in via system reset, wait a while for the secondary
337-
* CPUs to enter.
338-
*/
339356
if (TRAP(regs) == INTERRUPT_SYSTEM_RESET)
340-
mdelay(PRIMARY_TIMEOUT);
357+
is_via_system_reset = 1;
341358

342-
crash_kexec_prepare_cpus(crashing_cpu);
359+
crash_smp_send_stop();
343360

344361
crash_save_cpu(regs, crashing_cpu);
345362

0 commit comments

Comments
 (0)