Skip to content

Commit d556a9a

Browse files
Merge patch series "riscv: kexec: Fxiup crash_save percpu and machine_kexec_mask_interrupts"
[email protected] <[email protected]> says: From: Guo Ren <[email protected]> Current riscv kexec can't crash_save percpu states and disable interrupts properly. The patch series fix them, make kexec work correct. * b4-shazam-merge: riscv: kexec: Fixup crash_smp_send_stop without multi cores riscv: kexec: Fixup irq controller broken in kexec crash path Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents 6fdd5d2 + 9b932aa commit d556a9a

File tree

3 files changed

+133
-13
lines changed

3 files changed

+133
-13
lines changed

arch/riscv/include/asm/smp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
5050
/* Clear IPI for current CPU */
5151
void riscv_clear_ipi(void);
5252

53+
/* Check other CPUs stop or not */
54+
bool smp_crash_stop_failed(void);
55+
5356
/* Secondary hart entry */
5457
asmlinkage void smp_callin(void);
5558

arch/riscv/kernel/machine_kexec.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <linux/compiler.h> /* For unreachable() */
1616
#include <linux/cpu.h> /* For cpu_down() */
1717
#include <linux/reboot.h>
18+
#include <linux/interrupt.h>
19+
#include <linux/irq.h>
1820

1921
/*
2022
* kexec_image_info - Print received image details
@@ -138,20 +140,35 @@ void machine_shutdown(void)
138140
#endif
139141
}
140142

141-
/* Override the weak function in kernel/panic.c */
142-
void crash_smp_send_stop(void)
143+
static void machine_kexec_mask_interrupts(void)
143144
{
144-
static int cpus_stopped;
145+
unsigned int i;
146+
struct irq_desc *desc;
145147

146-
/*
147-
* This function can be called twice in panic path, but obviously
148-
* we execute this only once.
149-
*/
150-
if (cpus_stopped)
151-
return;
148+
for_each_irq_desc(i, desc) {
149+
struct irq_chip *chip;
150+
int ret;
151+
152+
chip = irq_desc_get_chip(desc);
153+
if (!chip)
154+
continue;
155+
156+
/*
157+
* First try to remove the active state. If this
158+
* fails, try to EOI the interrupt.
159+
*/
160+
ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
161+
162+
if (ret && irqd_irq_inprogress(&desc->irq_data) &&
163+
chip->irq_eoi)
164+
chip->irq_eoi(&desc->irq_data);
152165

153-
smp_send_stop();
154-
cpus_stopped = 1;
166+
if (chip->irq_mask)
167+
chip->irq_mask(&desc->irq_data);
168+
169+
if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
170+
chip->irq_disable(&desc->irq_data);
171+
}
155172
}
156173

157174
/*
@@ -169,6 +186,8 @@ machine_crash_shutdown(struct pt_regs *regs)
169186
crash_smp_send_stop();
170187

171188
crash_save_cpu(regs, smp_processor_id());
189+
machine_kexec_mask_interrupts();
190+
172191
pr_info("Starting crashdump kernel...\n");
173192
}
174193

@@ -195,6 +214,11 @@ machine_kexec(struct kimage *image)
195214
void *control_code_buffer = page_address(image->control_code_page);
196215
riscv_kexec_method kexec_method = NULL;
197216

217+
#ifdef CONFIG_SMP
218+
WARN(smp_crash_stop_failed(),
219+
"Some CPUs may be stale, kdump will be unreliable.\n");
220+
#endif
221+
198222
if (image->type != KEXEC_TYPE_CRASH)
199223
kexec_method = control_code_buffer;
200224
else

arch/riscv/kernel/smp.c

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/clockchips.h>
1313
#include <linux/interrupt.h>
1414
#include <linux/module.h>
15+
#include <linux/kexec.h>
1516
#include <linux/profile.h>
1617
#include <linux/smp.h>
1718
#include <linux/sched.h>
@@ -22,11 +23,13 @@
2223
#include <asm/sbi.h>
2324
#include <asm/tlbflush.h>
2425
#include <asm/cacheflush.h>
26+
#include <asm/cpu_ops.h>
2527

2628
enum ipi_message_type {
2729
IPI_RESCHEDULE,
2830
IPI_CALL_FUNC,
2931
IPI_CPU_STOP,
32+
IPI_CPU_CRASH_STOP,
3033
IPI_IRQ_WORK,
3134
IPI_TIMER,
3235
IPI_MAX
@@ -71,6 +74,32 @@ static void ipi_stop(void)
7174
wait_for_interrupt();
7275
}
7376

77+
#ifdef CONFIG_KEXEC_CORE
78+
static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0);
79+
80+
static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
81+
{
82+
crash_save_cpu(regs, cpu);
83+
84+
atomic_dec(&waiting_for_crash_ipi);
85+
86+
local_irq_disable();
87+
88+
#ifdef CONFIG_HOTPLUG_CPU
89+
if (cpu_has_hotplug(cpu))
90+
cpu_ops[cpu]->cpu_stop();
91+
#endif
92+
93+
for(;;)
94+
wait_for_interrupt();
95+
}
96+
#else
97+
static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
98+
{
99+
unreachable();
100+
}
101+
#endif
102+
74103
static const struct riscv_ipi_ops *ipi_ops __ro_after_init;
75104

76105
void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
@@ -124,8 +153,9 @@ void arch_irq_work_raise(void)
124153

125154
void handle_IPI(struct pt_regs *regs)
126155
{
127-
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
128-
unsigned long *stats = ipi_data[smp_processor_id()].stats;
156+
unsigned int cpu = smp_processor_id();
157+
unsigned long *pending_ipis = &ipi_data[cpu].bits;
158+
unsigned long *stats = ipi_data[cpu].stats;
129159

130160
riscv_clear_ipi();
131161

@@ -154,6 +184,10 @@ void handle_IPI(struct pt_regs *regs)
154184
ipi_stop();
155185
}
156186

187+
if (ops & (1 << IPI_CPU_CRASH_STOP)) {
188+
ipi_cpu_crash_stop(cpu, get_irq_regs());
189+
}
190+
157191
if (ops & (1 << IPI_IRQ_WORK)) {
158192
stats[IPI_IRQ_WORK]++;
159193
irq_work_run();
@@ -176,6 +210,7 @@ static const char * const ipi_names[] = {
176210
[IPI_RESCHEDULE] = "Rescheduling interrupts",
177211
[IPI_CALL_FUNC] = "Function call interrupts",
178212
[IPI_CPU_STOP] = "CPU stop interrupts",
213+
[IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts",
179214
[IPI_IRQ_WORK] = "IRQ work interrupts",
180215
[IPI_TIMER] = "Timer broadcast interrupts",
181216
};
@@ -235,6 +270,64 @@ void smp_send_stop(void)
235270
cpumask_pr_args(cpu_online_mask));
236271
}
237272

273+
#ifdef CONFIG_KEXEC_CORE
274+
/*
275+
* The number of CPUs online, not counting this CPU (which may not be
276+
* fully online and so not counted in num_online_cpus()).
277+
*/
278+
static inline unsigned int num_other_online_cpus(void)
279+
{
280+
unsigned int this_cpu_online = cpu_online(smp_processor_id());
281+
282+
return num_online_cpus() - this_cpu_online;
283+
}
284+
285+
void crash_smp_send_stop(void)
286+
{
287+
static int cpus_stopped;
288+
cpumask_t mask;
289+
unsigned long timeout;
290+
291+
/*
292+
* This function can be called twice in panic path, but obviously
293+
* we execute this only once.
294+
*/
295+
if (cpus_stopped)
296+
return;
297+
298+
cpus_stopped = 1;
299+
300+
/*
301+
* If this cpu is the only one alive at this point in time, online or
302+
* not, there are no stop messages to be sent around, so just back out.
303+
*/
304+
if (num_other_online_cpus() == 0)
305+
return;
306+
307+
cpumask_copy(&mask, cpu_online_mask);
308+
cpumask_clear_cpu(smp_processor_id(), &mask);
309+
310+
atomic_set(&waiting_for_crash_ipi, num_other_online_cpus());
311+
312+
pr_crit("SMP: stopping secondary CPUs\n");
313+
send_ipi_mask(&mask, IPI_CPU_CRASH_STOP);
314+
315+
/* Wait up to one second for other CPUs to stop */
316+
timeout = USEC_PER_SEC;
317+
while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
318+
udelay(1);
319+
320+
if (atomic_read(&waiting_for_crash_ipi) > 0)
321+
pr_warn("SMP: failed to stop secondary CPUs %*pbl\n",
322+
cpumask_pr_args(&mask));
323+
}
324+
325+
bool smp_crash_stop_failed(void)
326+
{
327+
return (atomic_read(&waiting_for_crash_ipi) > 0);
328+
}
329+
#endif
330+
238331
void smp_send_reschedule(int cpu)
239332
{
240333
send_ipi_single(cpu, IPI_RESCHEDULE);

0 commit comments

Comments
 (0)