Skip to content

Commit 7b08729

Browse files
committed
powerpc/64: Save stack pointer when we hard disable interrupts
A CPU that gets stuck with interrupts hard disable can be difficult to debug, as on some platforms we have no way to interrupt the CPU to find out what it's doing. A stop-gap is to have the CPU save it's stack pointer (r1) in its paca when it hard disables interrupts. That way if we can't interrupt it, we can at least trace the stack based on where it last disabled interrupts. In some cases that will be total junk, but the stack trace code should handle that. In the simple case of a CPU that disable interrupts and then gets stuck in a loop, the stack trace should be informative. We could clear the saved stack pointer when we enable interrupts, but that loses information which could be useful if we have nothing else to go on. Signed-off-by: Michael Ellerman <[email protected]> Reviewed-by: Nicholas Piggin <[email protected]>
1 parent 3e37868 commit 7b08729

File tree

4 files changed

+11
-2
lines changed

4 files changed

+11
-2
lines changed

arch/powerpc/include/asm/hw_irq.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,12 @@ static inline bool arch_irqs_disabled(void)
238238
__hard_irq_disable(); \
239239
flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \
240240
local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \
241-
if (!arch_irqs_disabled_flags(flags)) \
241+
if (!arch_irqs_disabled_flags(flags)) { \
242+
asm ("stdx %%r1, 0, %1 ;" \
243+
: "=m" (local_paca->saved_r1) \
244+
: "b" (&local_paca->saved_r1)); \
242245
trace_hardirqs_off(); \
246+
} \
243247
} while(0)
244248

245249
static inline bool lazy_irq_pending(void)

arch/powerpc/include/asm/paca.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ struct paca_struct {
161161
struct task_struct *__current; /* Pointer to current */
162162
u64 kstack; /* Saved Kernel stack addr */
163163
u64 stab_rr; /* stab/slb round-robin counter */
164-
u64 saved_r1; /* r1 save for RTAS calls or PM */
164+
u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */
165165
u64 saved_msr; /* MSR saved here by enter_rtas */
166166
u16 trap_save; /* Used when bad stack is encountered */
167167
u8 irq_soft_mask; /* mask for irq soft masking */

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,7 @@ masked_##_H##interrupt: \
14991499
xori r10,r10,MSR_EE; /* clear MSR_EE */ \
15001500
mtspr SPRN_##_H##SRR1,r10; \
15011501
2: mtcrf 0x80,r9; \
1502+
std r1,PACAR1(r13); \
15021503
ld r9,PACA_EXGEN+EX_R9(r13); \
15031504
ld r10,PACA_EXGEN+EX_R10(r13); \
15041505
ld r11,PACA_EXGEN+EX_R11(r13); \

arch/powerpc/xmon/xmon.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,10 @@ static int cpu_cmd(void)
11721172
/* try to switch to cpu specified */
11731173
if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
11741174
printf("cpu 0x%lx isn't in xmon\n", cpu);
1175+
#ifdef CONFIG_PPC64
1176+
printf("backtrace of paca[0x%lx].saved_r1 (possibly stale):\n", cpu);
1177+
xmon_show_stack(paca_ptrs[cpu]->saved_r1, 0, 0);
1178+
#endif
11751179
return 0;
11761180
}
11771181
xmon_taken = 0;

0 commit comments

Comments
 (0)