* [PATCH 2/2] kdump shutdown hook support
@ 2007-12-12 5:45 Michael Neuling
2007-12-12 7:01 ` Olof Johansson
` (2 more replies)
0 siblings, 3 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-12 5:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
I've tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 90 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 88 insertions(+), 5 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_SHUTDOWN_HANDLES_NUM 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NUM+1];
+static DEFINE_SPINLOCK(crash_handles_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i;
+
+ spin_lock(&crash_handles_lock);
+ for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
+ if (!crash_shutdown_handles[i])
+ break;
+
+ if (i == CRASH_SHUTDOWN_HANDLES_NUM){
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ spin_unlock(&crash_handles_lock);
+ return 1;
+ }
+
+ /* Insert handle at end */
+ crash_shutdown_handles[i] = handler;
+ spin_unlock(&crash_handles_lock);
+ return 0;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i;
+
+ spin_lock(&crash_handles_lock);
+ for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_SHUTDOWN_HANDLES_NUM){
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ spin_unlock(&crash_handles_lock);
+ return 1;
+ }
+
+ /* Shift handles down */
+ while(crash_shutdown_handles[i]) {
+ crash_shutdown_handles[i] = crash_shutdown_handles[i+1];
+ i++;
+ }
+ spin_unlock(&crash_handles_lock);
+ return 0;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static long crash_shutdown_buf[SETJMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
/*
* This function is only called after the system
@@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /* Call registered shutdown routines */
+ __debugger_fault_handler = handle_fault;
+ i = 0;
+ while(crash_shutdown_handles[i]){
+ if (setjmp(crash_shutdown_buf) == 0) {
+ asm volatile("sync; isync");
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ __delay(200);
+ }
+ i++;
}
/*
Index: linux-2.6-ozlabs/include/asm-powerpc/kexec.h
===================================================================
--- linux-2.6-ozlabs.orig/include/asm-powerpc/kexec.h
+++ linux-2.6-ozlabs/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/2] Make setjmp/longjmp code generic
@ 2007-12-12 5:45 Michael Neuling
2007-12-12 7:59 ` Kumar Gala
2007-12-12 22:56 ` Michael Ellerman
0 siblings, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-12 5:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc_64.S | 124 ++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 -
arch/powerpc/xmon/Makefile | 2
arch/powerpc/xmon/setjmp.S | 135 ------------------------------------------
arch/powerpc/xmon/xmon.c | 10 ---
include/asm-powerpc/setjmp.h | 12 +++
6 files changed, 142 insertions(+), 147 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/misc_64.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/misc_64.S
+++ linux-2.6-ozlabs/arch/powerpc/kernel/misc_64.S
@@ -518,6 +518,130 @@ _GLOBAL(giveup_altivec)
#endif /* CONFIG_ALTIVEC */
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
+
+#ifdef CONFIG_XMON
+/*
+ * Grab the register values as they are now.
+ * This won't do a particularily good job because we really
+ * want our caller's caller's registers, and our caller has
+ * already executed its prologue.
+ * ToDo: We could reach back into the caller's save area to do
+ * a better job of representing the caller's state (note that
+ * that will be different for 32-bit and 64-bit, because of the
+ * different ABIs, though).
+ */
+_GLOBAL(xmon_save_regs)
+ PPC_STL r0,0*SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ PPC_STL r3,3*SZL(r3)
+ PPC_STL r4,4*SZL(r3)
+ PPC_STL r5,5*SZL(r3)
+ PPC_STL r6,6*SZL(r3)
+ PPC_STL r7,7*SZL(r3)
+ PPC_STL r8,8*SZL(r3)
+ PPC_STL r9,9*SZL(r3)
+ PPC_STL r10,10*SZL(r3)
+ PPC_STL r11,11*SZL(r3)
+ PPC_STL r12,12*SZL(r3)
+ PPC_STL r13,13*SZL(r3)
+ PPC_STL r14,14*SZL(r3)
+ PPC_STL r15,15*SZL(r3)
+ PPC_STL r16,16*SZL(r3)
+ PPC_STL r17,17*SZL(r3)
+ PPC_STL r18,18*SZL(r3)
+ PPC_STL r19,19*SZL(r3)
+ PPC_STL r20,20*SZL(r3)
+ PPC_STL r21,21*SZL(r3)
+ PPC_STL r22,22*SZL(r3)
+ PPC_STL r23,23*SZL(r3)
+ PPC_STL r24,24*SZL(r3)
+ PPC_STL r25,25*SZL(r3)
+ PPC_STL r26,26*SZL(r3)
+ PPC_STL r27,27*SZL(r3)
+ PPC_STL r28,28*SZL(r3)
+ PPC_STL r29,29*SZL(r3)
+ PPC_STL r30,30*SZL(r3)
+ PPC_STL r31,31*SZL(r3)
+ /* go up one stack frame for SP */
+ PPC_LL r4,0(r1)
+ PPC_STL r4,1*SZL(r3)
+ /* get caller's LR */
+ PPC_LL r0,LRSAVE(r4)
+ PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
+ PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
+ mfmsr r0
+ PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
+ mfctr r0
+ PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
+ mfxer r0
+ PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
+ mfcr r0
+ PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
+ li r0,0
+ PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
+ blr
+#endif
+
/* kexec_wait(phys_cpu)
*
* wait for the flag to change, indicating this kernel is going away but
Index: linux-2.6-ozlabs/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: linux-2.6-ozlabs/arch/powerpc/xmon/Makefile
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/Makefile
+++ linux-2.6-ozlabs/arch/powerpc/xmon/Makefile
@@ -4,7 +4,7 @@ ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y += xmon.o setjmp.o start.o nonstdio.o
+obj-y += xmon.o start.o nonstdio.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
Index: linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
Index: linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/xmon.c
+++ linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
-static long bus_error_jmp[JMP_BUF_LEN];
+static long bus_error_jmp[SETJMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
@@ -338,7 +334,7 @@ static int xmon_core(struct pt_regs *reg
{
int cmd = 0;
struct bpt *bp;
- long recurse_jmp[JMP_BUF_LEN];
+ long recurse_jmp[SETJMP_BUF_LEN];
unsigned long offset;
unsigned long flags;
#ifdef CONFIG_SMP
Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define SETJMP_BUF_LEN 23
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-12 5:45 [PATCH 2/2] kdump shutdown hook support Michael Neuling
@ 2007-12-12 7:01 ` Olof Johansson
2007-12-13 0:53 ` Michael Neuling
2007-12-12 23:07 ` Michael Ellerman
2007-12-13 3:16 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2 siblings, 1 reply; 35+ messages in thread
From: Olof Johansson @ 2007-12-12 7:01 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
Hi,
A couple of comments below.
-Olof
On Wed, Dec 12, 2007 at 04:45:12PM +1100, Michael Neuling wrote:
> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> ===================================================================
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_SHUTDOWN_HANDLES_NUM 1
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NUM+1];
> +static DEFINE_SPINLOCK(crash_handles_lock);
Not 'handlers'?
> +
> #ifdef CONFIG_SMP
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
Missing space after for. There's a handful more of these through the
patch.
> + if (!crash_shutdown_handles[i])
> + break;
> +
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + spin_unlock(&crash_handles_lock);
> + return 1;
> + }
> +
> + /* Insert handle at end */
> + crash_shutdown_handles[i] = handler;
> + spin_unlock(&crash_handles_lock);
> + return 0;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + spin_unlock(&crash_handles_lock);
> + return 1;
> + }
> +
> + /* Shift handles down */
> + while(crash_shutdown_handles[i]) {
> + crash_shutdown_handles[i] = crash_shutdown_handles[i+1];
> + i++;
> + }
> + spin_unlock(&crash_handles_lock);
> + return 0;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static long crash_shutdown_buf[SETJMP_BUF_LEN];
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
>
> /*
> * This function is only called after the system
> @@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /* Call registered shutdown routines */
> + __debugger_fault_handler = handle_fault;
> + i = 0;
> + while(crash_shutdown_handles[i]){
This could do nicely as a for loop instead:
for (i = 0; crash_shutdown_handles[i]; i++) {
> + if (setjmp(crash_shutdown_buf) == 0) {
> + asm volatile("sync; isync");
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(200);
This looks a bit random. Why the handcoded barriers, and why the delay?
At least comment why the delay is needed (and why just 200 is
sufficient). I don't see a need for the barriers at all here?
> + }
> + i++;
> }
>
> /*
> Index: linux-2.6-ozlabs/include/asm-powerpc/kexec.h
> ===================================================================
> --- linux-2.6-ozlabs.orig/include/asm-powerpc/kexec.h
> +++ linux-2.6-ozlabs/include/asm-powerpc/kexec.h
> @@ -123,6 +123,9 @@ struct pt_regs;
> extern void default_machine_kexec(struct kimage *image);
> extern int default_machine_kexec_prepare(struct kimage *image);
> extern void default_machine_crash_shutdown(struct pt_regs *regs);
> +typedef void (*crash_shutdown_t)(void);
> +extern int crash_shutdown_register(crash_shutdown_t handler);
> +extern int crash_shutdown_unregister(crash_shutdown_t handler);
>
> extern void machine_kexec_simple(struct kimage *image);
> extern void crash_kexec_secondary(struct pt_regs *regs);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 5:45 Michael Neuling
@ 2007-12-12 7:59 ` Kumar Gala
2007-12-12 8:06 ` Benjamin Herrenschmidt
2007-12-12 22:56 ` Michael Ellerman
1 sibling, 1 reply; 35+ messages in thread
From: Kumar Gala @ 2007-12-12 7:59 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
On Dec 11, 2007, at 11:45 PM, Michael Neuling wrote:
> This makes the setjmp/longjmp code used by xmon, generically available
> to other code. It also removes the requirement for debugger hooks to
> be only called on 0x300 (data storage) exception.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
>
> arch/powerpc/kernel/misc_64.S | 124 ++++++++++++++++++++++++++++++++
> ++++++
> arch/powerpc/mm/fault.c | 6 -
> arch/powerpc/xmon/Makefile | 2
> arch/powerpc/xmon/setjmp.S | 135
> ------------------------------------------
> arch/powerpc/xmon/xmon.c | 10 ---
> include/asm-powerpc/setjmp.h | 12 +++
> 6 files changed, 142 insertions(+), 147 deletions(-)
it would seem that moving this code out of xmon.c into misc_64.s would
break ppc32 usage.
- k
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 7:59 ` Kumar Gala
@ 2007-12-12 8:06 ` Benjamin Herrenschmidt
2007-12-12 9:37 ` Stephen Rothwell
0 siblings, 1 reply; 35+ messages in thread
From: Benjamin Herrenschmidt @ 2007-12-12 8:06 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Michael Neuling, RAISCH, Paul Mackerras, THEMANN
On Wed, 2007-12-12 at 01:59 -0600, Kumar Gala wrote:
> On Dec 11, 2007, at 11:45 PM, Michael Neuling wrote:
>
> > This makes the setjmp/longjmp code used by xmon, generically available
> > to other code. It also removes the requirement for debugger hooks to
> > be only called on 0x300 (data storage) exception.
> >
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > ---
> >
> > arch/powerpc/kernel/misc_64.S | 124 ++++++++++++++++++++++++++++++++
> > ++++++
> > arch/powerpc/mm/fault.c | 6 -
> > arch/powerpc/xmon/Makefile | 2
> > arch/powerpc/xmon/setjmp.S | 135
> > ------------------------------------------
> > arch/powerpc/xmon/xmon.c | 10 ---
> > include/asm-powerpc/setjmp.h | 12 +++
> > 6 files changed, 142 insertions(+), 147 deletions(-)
>
> it would seem that moving this code out of xmon.c into misc_64.s would
> break ppc32 usage.
Time to introduce a merged misc.S ? :-)
Ben.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 8:06 ` Benjamin Herrenschmidt
@ 2007-12-12 9:37 ` Stephen Rothwell
2007-12-12 9:44 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 35+ messages in thread
From: Stephen Rothwell @ 2007-12-12 9:37 UTC (permalink / raw)
To: benh; +Cc: Neuling, THEMANN, Michael, linuxppc-dev, RAISCH, Paul Mackerras
[-- Attachment #1: Type: text/plain, Size: 275 bytes --]
On Wed, 12 Dec 2007 19:06:54 +1100 Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> Time to introduce a merged misc.S ? :-)
We already have one ...
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 9:37 ` Stephen Rothwell
@ 2007-12-12 9:44 ` Benjamin Herrenschmidt
2007-12-12 11:09 ` Michael Neuling
0 siblings, 1 reply; 35+ messages in thread
From: Benjamin Herrenschmidt @ 2007-12-12 9:44 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Michael Neuling, THEMANN, linuxppc-dev, RAISCH, Paul Mackerras
On Wed, 2007-12-12 at 20:37 +1100, Stephen Rothwell wrote:
> On Wed, 12 Dec 2007 19:06:54 +1100 Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > Time to introduce a merged misc.S ? :-)
>
> We already have one ...
Hah ! I should have looked :-)
Ben.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 9:44 ` Benjamin Herrenschmidt
@ 2007-12-12 11:09 ` Michael Neuling
0 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-12 11:09 UTC (permalink / raw)
To: benh; +Cc: Stephen Rothwell, THEMANN, linuxppc-dev, RAISCH, Paul Mackerras
> On Wed, 2007-12-12 at 20:37 +1100, Stephen Rothwell wrote:
> > On Wed, 12 Dec 2007 19:06:54 +1100 Benjamin Herrenschmidt <benh@kernel.cras
hing.org> wrote:
> > >
> > > Time to introduce a merged misc.S ? :-)
> >
> > We already have one ...
>
> Hah ! I should have looked :-)
Me too! :-)
Sorry Kumar, I'll fix.
Mikey
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 5:45 Michael Neuling
2007-12-12 7:59 ` Kumar Gala
@ 2007-12-12 22:56 ` Michael Ellerman
2007-12-12 23:40 ` Michael Neuling
1 sibling, 1 reply; 35+ messages in thread
From: Michael Ellerman @ 2007-12-12 22:56 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
[-- Attachment #1: Type: text/plain, Size: 3401 bytes --]
On Wed, 2007-12-12 at 16:45 +1100, Michael Neuling wrote:
> This makes the setjmp/longjmp code used by xmon, generically available
> to other code. It also removes the requirement for debugger hooks to
> be only called on 0x300 (data storage) exception.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
>
> arch/powerpc/kernel/misc_64.S | 124 ++++++++++++++++++++++++++++++++++++++
> arch/powerpc/mm/fault.c | 6 -
> arch/powerpc/xmon/Makefile | 2
> arch/powerpc/xmon/setjmp.S | 135 ------------------------------------------
> arch/powerpc/xmon/xmon.c | 10 ---
> include/asm-powerpc/setjmp.h | 12 +++
> 6 files changed, 142 insertions(+), 147 deletions(-)
>
> Index: linux-2.6-ozlabs/arch/powerpc/kernel/misc_64.S
> ===================================================================
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/misc_64.S
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/misc_64.S
> @@ -518,6 +518,130 @@ _GLOBAL(giveup_altivec)
>
> #endif /* CONFIG_ALTIVEC */
>
> +_GLOBAL(setjmp)
> + mflr r0
> + PPC_STL r0,0(r3)
> + PPC_STL r1,SZL(r3)
> + PPC_STL r2,2*SZL(r3)
> + mfcr r0
> + PPC_STL r0,3*SZL(r3)
> + PPC_STL r13,4*SZL(r3)
> + PPC_STL r14,5*SZL(r3)
> + PPC_STL r15,6*SZL(r3)
> + PPC_STL r16,7*SZL(r3)
> + PPC_STL r17,8*SZL(r3)
> + PPC_STL r18,9*SZL(r3)
> + PPC_STL r19,10*SZL(r3)
> + PPC_STL r20,11*SZL(r3)
> + PPC_STL r21,12*SZL(r3)
> + PPC_STL r22,13*SZL(r3)
> + PPC_STL r23,14*SZL(r3)
> + PPC_STL r24,15*SZL(r3)
> + PPC_STL r25,16*SZL(r3)
> + PPC_STL r26,17*SZL(r3)
> + PPC_STL r27,18*SZL(r3)
> + PPC_STL r28,19*SZL(r3)
> + PPC_STL r29,20*SZL(r3)
> + PPC_STL r30,21*SZL(r3)
> + PPC_STL r31,22*SZL(r3)
> + li r3,0
> + blr
> +
> +_GLOBAL(longjmp)
> + PPC_LCMPI r4,0
> + bne 1f
> + li r4,1
> +1: PPC_LL r13,4*SZL(r3)
> + PPC_LL r14,5*SZL(r3)
> + PPC_LL r15,6*SZL(r3)
> + PPC_LL r16,7*SZL(r3)
> + PPC_LL r17,8*SZL(r3)
> + PPC_LL r18,9*SZL(r3)
> + PPC_LL r19,10*SZL(r3)
> + PPC_LL r20,11*SZL(r3)
> + PPC_LL r21,12*SZL(r3)
> + PPC_LL r22,13*SZL(r3)
> + PPC_LL r23,14*SZL(r3)
> + PPC_LL r24,15*SZL(r3)
> + PPC_LL r25,16*SZL(r3)
> + PPC_LL r26,17*SZL(r3)
> + PPC_LL r27,18*SZL(r3)
> + PPC_LL r28,19*SZL(r3)
> + PPC_LL r29,20*SZL(r3)
> + PPC_LL r30,21*SZL(r3)
> + PPC_LL r31,22*SZL(r3)
> + PPC_LL r0,3*SZL(r3)
> + mtcrf 0x38,r0
> + PPC_LL r0,0(r3)
> + PPC_LL r1,SZL(r3)
> + PPC_LL r2,2*SZL(r3)
> + mtlr r0
> + mr r3,r4
> + blr
> +
> +#ifdef CONFIG_XMON
> +/*
> + * Grab the register values as they are now.
> + * This won't do a particularily good job because we really
> + * want our caller's caller's registers, and our caller has
> + * already executed its prologue.
> + * ToDo: We could reach back into the caller's save area to do
> + * a better job of representing the caller's state (note that
> + * that will be different for 32-bit and 64-bit, because of the
> + * different ABIs, though).
> + */
> +_GLOBAL(xmon_save_regs)
> + PPC_STL r0,0*SZL(r3)
> + PPC_STL r2,2*SZL(r3)
> + PPC_STL r3,3*SZL(r3)
> + PPC_STL r4,4*SZL(r3)
Does xmon_save_regs belong here?
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-12 5:45 [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-12 7:01 ` Olof Johansson
@ 2007-12-12 23:07 ` Michael Ellerman
2007-12-13 0:04 ` Michael Neuling
2007-12-13 3:16 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2 siblings, 1 reply; 35+ messages in thread
From: Michael Ellerman @ 2007-12-12 23:07 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
[-- Attachment #1: Type: text/plain, Size: 4958 bytes --]
On Wed, 2007-12-12 at 16:45 +1100, Michael Neuling wrote:
> This adds hooks into the default_machine_crash_shutdown so drivers can
> register a function to be run in the first kernel before we hand off
> to the second kernel. This should only be used in exceptional
> circumstances, like where the device can't be reset in the second
> kernel alone (as is the case with eHEA). To emphasize this, the
> number of handles allowed to be registered is currently #def to 1.
>
> This uses the setjmp/longjmp code to call out to the registered hooks,
> so any bogus exceptions we encounter will hopefully be recoverable.
>
> I've tested with bogus data and instruction exceptions.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
>
> arch/powerpc/kernel/crash.c | 90 +++++++++++++++++++++++++++++++++++++++++---
> include/asm-powerpc/kexec.h | 3 +
> 2 files changed, 88 insertions(+), 5 deletions(-)
>
> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> ===================================================================
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_SHUTDOWN_HANDLES_NUM 1
CRASH_HANDLER_MAX ?
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NUM+1];
> +static DEFINE_SPINLOCK(crash_handles_lock);
> +
> #ifdef CONFIG_SMP
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++) {
> + if (!crash_shutdown_handles[i]) {
> + /* Insert handle at end */
> + crash_shutdown_handles[i] = handler;
> + rc = 0;
> + break;
> + }
> + }
>
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + rc = 1;
> + }
> +
> + spin_unlock(&crash_handles_lock);
Perhaps?
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + spin_unlock(&crash_handles_lock);
> + return 1;
> + }
> +
> + /* Shift handles down */
> + while(crash_shutdown_handles[i]) {
> + crash_shutdown_handles[i] = crash_shutdown_handles[i+1];
> + i++;
> + }
> + spin_unlock(&crash_handles_lock);
> + return 0;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static long crash_shutdown_buf[SETJMP_BUF_LEN];
unsigned long?
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
>
> /*
> * This function is only called after the system
> @@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /* Call registered shutdown routines */
> + __debugger_fault_handler = handle_fault;
> + i = 0;
> + while(crash_shutdown_handles[i]){
> + if (setjmp(crash_shutdown_buf) == 0) {
> + asm volatile("sync; isync");
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(200);
> + }
> + i++;
> }
You should probably reset __debugger_fault_handler, just to be safe.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-12 22:56 ` Michael Ellerman
@ 2007-12-12 23:40 ` Michael Neuling
0 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-12 23:40 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
> > arch/powerpc/xmon/setjmp.S | 135 ------------------------------------------
<snip>
> > +#ifdef CONFIG_XMON
> > +/*
> > + * Grab the register values as they are now.
> > + * This won't do a particularily good job because we really
> > + * want our caller's caller's registers, and our caller has
> > + * already executed its prologue.
> > + * ToDo: We could reach back into the caller's save area to do
> > + * a better job of representing the caller's state (note that
> > + * that will be different for 32-bit and 64-bit, because of the
> > + * different ABIs, though).
> > + */
> > +_GLOBAL(xmon_save_regs)
> > + PPC_STL r0,0*SZL(r3)
> > + PPC_STL r2,2*SZL(r3)
> > + PPC_STL r3,3*SZL(r3)
> > + PPC_STL r4,4*SZL(r3)
>
> Does xmon_save_regs belong here?
This was the only function left in xmon/setjmp.S. So rather than rename
the whole file to reflect it no longer has anything to do with setjmp, I
moved it out to misc.S
I'm not fussed what we end up doing.
Mikey
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-12 23:07 ` Michael Ellerman
@ 2007-12-13 0:04 ` Michael Neuling
0 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 0:04 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In message <1197500839.7695.19.camel@concordia> you wrote:
>
> --=-Kza0KCx0MG8nsjfq7kOz
> Content-Type: text/plain
> Content-Transfer-Encoding: quoted-printable
>
> On Wed, 2007-12-12 at 16:45 +1100, Michael Neuling wrote:
> > This adds hooks into the default_machine_crash_shutdown so drivers can
> > register a function to be run in the first kernel before we hand off
> > to the second kernel. This should only be used in exceptional
> > circumstances, like where the device can't be reset in the second
> > kernel alone (as is the case with eHEA). To emphasize this, the
> > number of handles allowed to be registered is currently #def to 1.
> >=20
> > This uses the setjmp/longjmp code to call out to the registered hooks,
> > so any bogus exceptions we encounter will hopefully be recoverable. =20
> >=20
> > I've tested with bogus data and instruction exceptions.
> >=20
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > ---
> >=20
> > arch/powerpc/kernel/crash.c | 90 +++++++++++++++++++++++++++++++++++++=
> ++++---
> > include/asm-powerpc/kexec.h | 3 +
> > 2 files changed, 88 insertions(+), 5 deletions(-)
> >=20
> > Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> > +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> > @@ -32,6 +32,8 @@
> > #include <asm/lmb.h>
> > #include <asm/firmware.h>
> > #include <asm/smp.h>
> > +#include <asm/system.h>
> > +#include <asm/setjmp.h>
> > =20
> > #ifdef DEBUG
> > #include <asm/udbg.h>
> > @@ -45,6 +47,11 @@ int crashing_cpu =3D -1;
> > static cpumask_t cpus_in_crash =3D CPU_MASK_NONE;
> > cpumask_t cpus_in_sr =3D CPU_MASK_NONE;
> > =20
> > +#define CRASH_SHUTDOWN_HANDLES_NUM 1
>
> CRASH_HANDLER_MAX ?
yep, MAX is probably a more representative name
>
> > +/* NULL terminated list of shutdown handles */
> > +static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NU=
> M+1];
> > +static DEFINE_SPINLOCK(crash_handles_lock);
> > +
> > #ifdef CONFIG_SMP
> > static atomic_t enter_on_soft_reset =3D ATOMIC_INIT(0);
> > =20
> > @@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
> > }
> > #endif /* CONFIG_SPU_BASE */
> > =20
> > +/*=20
> > + * Register a function to be called on shutdown. Only use this if you
> > + * can't reset your device in the second kernel.
> > + */
> > +int crash_shutdown_register(crash_shutdown_t handler)
> > +{
> > + unsigned int i, rc;
> > +
> > + spin_lock(&crash_handles_lock);
>
> > + for(i =3D 0 ; i <=3D CRASH_SHUTDOWN_HANDLES_NUM; i++) {
> > + if (!crash_shutdown_handles[i]) {
> > + /* Insert handle at end */
> > + crash_shutdown_handles[i] =3D handler;
> > + rc =3D 0;
> > + break;
> > + }
> > + }
> >=20
> > + if (i =3D=3D CRASH_SHUTDOWN_HANDLES_NUM){
> > + printk(KERN_ERR "Crash shutdown handles full, "
> > + "not registered.\n");
> > + rc =3D 1;
> > + }
> > +
> > + spin_unlock(&crash_handles_lock);
>
> Perhaps?
Yep, looks nicer. I'll fix the one below too.
>
> > + return rc;
> > +}
> > +EXPORT_SYMBOL(crash_shutdown_register);
> > +
> > +int crash_shutdown_unregister(crash_shutdown_t handler)
> > +{
> > + unsigned int i;
> > +
> > + spin_lock(&crash_handles_lock);
> > + for(i =3D 0 ; i <=3D CRASH_SHUTDOWN_HANDLES_NUM; i++)
> > + if (crash_shutdown_handles[i] =3D=3D handler)
> > + break;
> > +
> > + if (i =3D=3D CRASH_SHUTDOWN_HANDLES_NUM){
> > + printk(KERN_ERR "Crash shutdown handle not found\n");
> > + spin_unlock(&crash_handles_lock);
> > + return 1;
> > + }
> > +
> > + /* Shift handles down */
> > + while(crash_shutdown_handles[i]) {
> > + crash_shutdown_handles[i] =3D crash_shutdown_handles[i+1];
> > + i++;
> > + }
> > + spin_unlock(&crash_handles_lock);
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(crash_shutdown_unregister);
> > +
> > +static long crash_shutdown_buf[SETJMP_BUF_LEN];
>
> unsigned long?
yep
>
> > +
> > +static int handle_fault(struct pt_regs *regs)
> > +{
> > + longjmp(crash_shutdown_buf, 1);
> > + return 0;
> > +}
> > +
> > void default_machine_crash_shutdown(struct pt_regs *regs)
> > {
> > - unsigned int irq;
> > + unsigned int i;
> > =20
> > /*
> > * This function is only called after the system
> > @@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
> > */
> > hard_irq_disable();
> > =20
> > - for_each_irq(irq) {
> > - struct irq_desc *desc =3D irq_desc + irq;
> > + for_each_irq(i) {
> > + struct irq_desc *desc =3D irq_desc + i;
> > =20
> > if (desc->status & IRQ_INPROGRESS)
> > - desc->chip->eoi(irq);
> > + desc->chip->eoi(i);
> > =20
> > if (!(desc->status & IRQ_DISABLED))
> > - desc->chip->disable(irq);
> > + desc->chip->disable(i);
> > + }
> > +
> > + /* Call registered shutdown routines */
> > + __debugger_fault_handler =3D handle_fault;
> > + i =3D 0;
> > + while(crash_shutdown_handles[i]){
> > + if (setjmp(crash_shutdown_buf) =3D=3D 0) {
> > + asm volatile("sync; isync");
> > + crash_shutdown_handles[i]();
> > + asm volatile("sync; isync");
> > + __delay(200);
> > + }
> > + i++;
> > }
>
> You should probably reset __debugger_fault_handler, just to be safe.
Agreed.
Mikey
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-12 7:01 ` Olof Johansson
@ 2007-12-13 0:53 ` Michael Neuling
0 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 0:53 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
>
> > + if (setjmp(crash_shutdown_buf) == 0) {
> > + asm volatile("sync; isync");
> > + crash_shutdown_handles[i]();
> > + asm volatile("sync; isync");
> > + __delay(200);
>
> This looks a bit random. Why the handcoded barriers, and why the delay?
> I don't see a need for the barriers at all here?
I was following the bouncing ball here from the xmon code. We don't
want the hardware executing any of potentially dangerous hooks before
we've setup the setjmp save buffer. Similar, any code past the
dangerous hooks shouldn't be executed before we take a machine check.
It's definitely not a fast path so.... :-)
> At least comment why the delay is needed (and why just 200 is
> sufficient).
xmon.c says:
/* wait a little while to see if we get a machine check */
I'll update the "200" with a #define SETJMP_MACHINE_CHECK_DELAY and push
the same change into the xmon code. This delay in the machine check is
apparently required on 601 machines.
All you other comments I agree with.
Mikey
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/2] Add crashdump shutdown hooks
2007-12-12 5:45 [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-12 7:01 ` Olof Johansson
2007-12-12 23:07 ` Michael Ellerman
@ 2007-12-13 3:16 ` Michael Neuling
2007-12-13 3:16 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-13 3:16 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2 siblings, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This is an updated series following comments from the first post.
Adds some documentation, better code flow, fixes 32 bit compiles and
other updates based on feedback
Again these are based on paulus' for 2.6.25 tree.
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-13 3:16 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2007-12-13 3:16 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
@ 2007-12-13 3:16 ` Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception and adds some
documentation.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 128 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 -
arch/powerpc/xmon/Makefile | 2
arch/powerpc/xmon/setjmp.S | 135 -------------------------------------------
arch/powerpc/xmon/xmon.c | 38 ++++--------
include/asm-powerpc/setjmp.h | 19 ++++++
6 files changed, 164 insertions(+), 164 deletions(-)
Index: clone3/arch/powerpc/kernel/misc.S
===================================================================
--- clone3.orig/arch/powerpc/kernel/misc.S
+++ clone3/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,127 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
+
+#ifdef CONFIG_XMON
+/*
+ * Grab the register values as they are now.
+ * This won't do a particularily good job because we really
+ * want our caller's caller's registers, and our caller has
+ * already executed its prologue.
+ * ToDo: We could reach back into the caller's save area to do
+ * a better job of representing the caller's state (note that
+ * that will be different for 32-bit and 64-bit, because of the
+ * different ABIs, though).
+ */
+_GLOBAL(xmon_save_regs)
+ PPC_STL r0,0*SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ PPC_STL r3,3*SZL(r3)
+ PPC_STL r4,4*SZL(r3)
+ PPC_STL r5,5*SZL(r3)
+ PPC_STL r6,6*SZL(r3)
+ PPC_STL r7,7*SZL(r3)
+ PPC_STL r8,8*SZL(r3)
+ PPC_STL r9,9*SZL(r3)
+ PPC_STL r10,10*SZL(r3)
+ PPC_STL r11,11*SZL(r3)
+ PPC_STL r12,12*SZL(r3)
+ PPC_STL r13,13*SZL(r3)
+ PPC_STL r14,14*SZL(r3)
+ PPC_STL r15,15*SZL(r3)
+ PPC_STL r16,16*SZL(r3)
+ PPC_STL r17,17*SZL(r3)
+ PPC_STL r18,18*SZL(r3)
+ PPC_STL r19,19*SZL(r3)
+ PPC_STL r20,20*SZL(r3)
+ PPC_STL r21,21*SZL(r3)
+ PPC_STL r22,22*SZL(r3)
+ PPC_STL r23,23*SZL(r3)
+ PPC_STL r24,24*SZL(r3)
+ PPC_STL r25,25*SZL(r3)
+ PPC_STL r26,26*SZL(r3)
+ PPC_STL r27,27*SZL(r3)
+ PPC_STL r28,28*SZL(r3)
+ PPC_STL r29,29*SZL(r3)
+ PPC_STL r30,30*SZL(r3)
+ PPC_STL r31,31*SZL(r3)
+ /* go up one stack frame for SP */
+ PPC_LL r4,0(r1)
+ PPC_STL r4,1*SZL(r3)
+ /* get caller's LR */
+ PPC_LL r0,LRSAVE(r4)
+ PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
+ PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
+ mfmsr r0
+ PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
+ mfctr r0
+ PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
+ mfxer r0
+ PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
+ mfcr r0
+ PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
+ li r0,0
+ PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
+ blr
+#endif
Index: clone3/arch/powerpc/mm/fault.c
===================================================================
--- clone3.orig/arch/powerpc/mm/fault.c
+++ clone3/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: clone3/arch/powerpc/xmon/Makefile
===================================================================
--- clone3.orig/arch/powerpc/xmon/Makefile
+++ clone3/arch/powerpc/xmon/Makefile
@@ -4,7 +4,7 @@ ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y += xmon.o setjmp.o start.o nonstdio.o
+obj-y += xmon.o start.o nonstdio.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
Index: clone3/arch/powerpc/xmon/setjmp.S
===================================================================
--- clone3.orig/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
Index: clone3/arch/powerpc/xmon/xmon.c
===================================================================
--- clone3.orig/arch/powerpc/xmon/xmon.c
+++ clone3/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
-static long bus_error_jmp[JMP_BUF_LEN];
+static long bus_error_jmp[SETJMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
@@ -338,7 +334,7 @@ static int xmon_core(struct pt_regs *reg
{
int cmd = 0;
struct bpt *bp;
- long recurse_jmp[JMP_BUF_LEN];
+ long recurse_jmp[SETJMP_BUF_LEN];
unsigned long offset;
unsigned long flags;
#ifdef CONFIG_SMP
@@ -1428,7 +1424,7 @@ void prregs(struct pt_regs *fp)
sync();
regs = *(struct pt_regs *)base;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error reading registers from "REG"\n",
@@ -1497,8 +1493,7 @@ void cacheflush(void)
cinval((void *) adrs);
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
}
@@ -1533,8 +1528,7 @@ read_spr(int n)
ret = code();
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
@@ -1569,8 +1563,7 @@ write_spr(int n, unsigned long val)
code(val);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
}
@@ -1676,8 +1669,7 @@ mread(unsigned long adrs, void *buf, int
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
catch_memory_errors = 0;
@@ -1713,8 +1705,7 @@ mwrite(unsigned long adrs, void *buf, in
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
} else {
printf("*** Error writing address %x\n", adrs + n);
@@ -2521,8 +2512,7 @@ static void xmon_print_symbol(unsigned l
name = kallsyms_lookup(address, &size, &offset, &modname,
tmpstr);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
@@ -2777,7 +2767,7 @@ static void stop_spus(void)
spu_mfc_sr1_set(spu, tmp);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
spu_info[i].stopped_ok = 1;
@@ -2817,7 +2807,7 @@ static void restart_spus(void)
spu_info[i].saved_spu_runcntl_RW);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
printf("Restarted spu %.2d\n", i);
} else {
@@ -2837,7 +2827,7 @@ do { \
printf(" %-*s = "format"\n", DUMP_WIDTH, \
#field, value); \
sync(); \
- __delay(200); \
+ __delay(SETJMP_MACHINE_CHECK_DELAY); \
} else { \
catch_memory_errors = 0; \
printf(" %-*s = *** Error reading field.\n", \
@@ -2899,7 +2889,7 @@ static void dump_spu_ls(unsigned long nu
sync();
ls_addr = (unsigned long)spu_info[num].spu->local_store;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error: accessing spu info for spu %d\n", num);
Index: clone3/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ clone3/include/asm-powerpc/setjmp.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define SETJMP_BUF_LEN 23
+#define SETJMP_MACHINE_CHECK_DELAY 200
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/2] kdump shutdown hook support
2007-12-13 3:16 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
@ 2007-12-13 3:16 ` Michael Neuling
2007-12-13 5:12 ` Olof Johansson
2007-12-13 3:16 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
1 sibling, 1 reply; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 102 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 100 insertions(+), 5 deletions(-)
Index: clone3/arch/powerpc/kernel/crash.c
===================================================================
--- clone3.orig/arch/powerpc/kernel/crash.c
+++ clone3/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: clone3/include/asm-powerpc/kexec.h
===================================================================
--- clone3.orig/include/asm-powerpc/kexec.h
+++ clone3/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-13 3:16 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
@ 2007-12-13 5:12 ` Olof Johansson
2007-12-13 5:13 ` Olof Johansson
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
0 siblings, 2 replies; 35+ messages in thread
From: Olof Johansson @ 2007-12-13 5:12 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
Hi,
On Thu, Dec 13, 2007 at 02:16:18PM +1100, Michael Neuling wrote:
> Index: clone3/arch/powerpc/kernel/crash.c
> ===================================================================
> --- clone3.orig/arch/powerpc/kernel/crash.c
> +++ clone3/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_HANDLER_MAX 1
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
> +static DEFINE_SPINLOCK(crash_handers_lock);
How about just using 'handlers' instead of 'handers' and 'handles'? :)
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (!crash_shutdown_handles[i]) {
> + /* Insert handle at first empty entry */
> + crash_shutdown_handles[i] = handler;
> + rc = 0;
> + break;
> + }
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + rc = 1;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + rc = 1;
> + } else {
> + /* Shift handles down */
> + for (; crash_shutdown_handles[i]; i++)
> + crash_shutdown_handles[i] =
> + crash_shutdown_handles[i+1];
> + rc = 0;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
> + int (*old_handler)(struct pt_regs *regs);
> +
>
> /*
> * This function is only called after the system
> @@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /*
> + * Call registered shutdown routines savely. Swap out
> + * __debugger_fault_handler, and replace on exit.
> + */
> + old_handler = __debugger_fault_handler;
> + __debugger_fault_handler = handle_fault;
> + for (i = 0; crash_shutdown_handles[i]; i++) {
> + if (setjmp(crash_shutdown_buf) == 0) {
> + /*
> + * Insert syncs and delay to ensure
> + * instructions in the dangerous region don't
> + * leak away from this protected region.
> + */
> + asm volatile("sync; isync");
> + /* dangerous region */
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(SETJMP_MACHINE_CHECK_DELAY);
Where is this defined?
> + }
> }
> + __debugger_fault_handler = old_handler;
>
> /*
> * Make a note of crashing cpu. Will be used in machine_kexec
> Index: clone3/include/asm-powerpc/kexec.h
> ===================================================================
> --- clone3.orig/include/asm-powerpc/kexec.h
> +++ clone3/include/asm-powerpc/kexec.h
> @@ -123,6 +123,9 @@ struct pt_regs;
> extern void default_machine_kexec(struct kimage *image);
> extern int default_machine_kexec_prepare(struct kimage *image);
> extern void default_machine_crash_shutdown(struct pt_regs *regs);
> +typedef void (*crash_shutdown_t)(void);
> +extern int crash_shutdown_register(crash_shutdown_t handler);
> +extern int crash_shutdown_unregister(crash_shutdown_t handler);
>
> extern void machine_kexec_simple(struct kimage *image);
> extern void crash_kexec_secondary(struct pt_regs *regs);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/2] kdump shutdown hook support
2007-12-13 5:12 ` Olof Johansson
@ 2007-12-13 5:13 ` Olof Johansson
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Olof Johansson @ 2007-12-13 5:13 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
On Wed, Dec 12, 2007 at 11:12:24PM -0600, Olof Johansson wrote:
> Hi,
> > + __delay(SETJMP_MACHINE_CHECK_DELAY);
>
> Where is this defined?
Oops, nevermind. In 1/2, of course. :-)
-Olof
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/2] Add crashdump shutdown hooks
2007-12-13 5:12 ` Olof Johansson
2007-12-13 5:13 ` Olof Johansson
@ 2007-12-13 9:59 ` Michael Neuling
2007-12-13 9:59 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
` (2 more replies)
1 sibling, 3 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 9:59 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Fixes stupid variable name noticed by Olof.
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/2] Make setjmp/longjmp code generic
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
@ 2007-12-13 9:59 ` Michael Neuling
2007-12-13 9:59 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2008-01-17 4:45 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 9:59 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception and adds some
documentation.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 128 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 -
arch/powerpc/xmon/Makefile | 2
arch/powerpc/xmon/setjmp.S | 135 -------------------------------------------
arch/powerpc/xmon/xmon.c | 38 ++++--------
include/asm-powerpc/setjmp.h | 19 ++++++
6 files changed, 164 insertions(+), 164 deletions(-)
Index: clone3/arch/powerpc/kernel/misc.S
===================================================================
--- clone3.orig/arch/powerpc/kernel/misc.S
+++ clone3/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,127 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
+
+#ifdef CONFIG_XMON
+/*
+ * Grab the register values as they are now.
+ * This won't do a particularily good job because we really
+ * want our caller's caller's registers, and our caller has
+ * already executed its prologue.
+ * ToDo: We could reach back into the caller's save area to do
+ * a better job of representing the caller's state (note that
+ * that will be different for 32-bit and 64-bit, because of the
+ * different ABIs, though).
+ */
+_GLOBAL(xmon_save_regs)
+ PPC_STL r0,0*SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ PPC_STL r3,3*SZL(r3)
+ PPC_STL r4,4*SZL(r3)
+ PPC_STL r5,5*SZL(r3)
+ PPC_STL r6,6*SZL(r3)
+ PPC_STL r7,7*SZL(r3)
+ PPC_STL r8,8*SZL(r3)
+ PPC_STL r9,9*SZL(r3)
+ PPC_STL r10,10*SZL(r3)
+ PPC_STL r11,11*SZL(r3)
+ PPC_STL r12,12*SZL(r3)
+ PPC_STL r13,13*SZL(r3)
+ PPC_STL r14,14*SZL(r3)
+ PPC_STL r15,15*SZL(r3)
+ PPC_STL r16,16*SZL(r3)
+ PPC_STL r17,17*SZL(r3)
+ PPC_STL r18,18*SZL(r3)
+ PPC_STL r19,19*SZL(r3)
+ PPC_STL r20,20*SZL(r3)
+ PPC_STL r21,21*SZL(r3)
+ PPC_STL r22,22*SZL(r3)
+ PPC_STL r23,23*SZL(r3)
+ PPC_STL r24,24*SZL(r3)
+ PPC_STL r25,25*SZL(r3)
+ PPC_STL r26,26*SZL(r3)
+ PPC_STL r27,27*SZL(r3)
+ PPC_STL r28,28*SZL(r3)
+ PPC_STL r29,29*SZL(r3)
+ PPC_STL r30,30*SZL(r3)
+ PPC_STL r31,31*SZL(r3)
+ /* go up one stack frame for SP */
+ PPC_LL r4,0(r1)
+ PPC_STL r4,1*SZL(r3)
+ /* get caller's LR */
+ PPC_LL r0,LRSAVE(r4)
+ PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
+ PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
+ mfmsr r0
+ PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
+ mfctr r0
+ PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
+ mfxer r0
+ PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
+ mfcr r0
+ PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
+ li r0,0
+ PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
+ blr
+#endif
Index: clone3/arch/powerpc/mm/fault.c
===================================================================
--- clone3.orig/arch/powerpc/mm/fault.c
+++ clone3/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: clone3/arch/powerpc/xmon/Makefile
===================================================================
--- clone3.orig/arch/powerpc/xmon/Makefile
+++ clone3/arch/powerpc/xmon/Makefile
@@ -4,7 +4,7 @@ ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y += xmon.o setjmp.o start.o nonstdio.o
+obj-y += xmon.o start.o nonstdio.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
Index: clone3/arch/powerpc/xmon/setjmp.S
===================================================================
--- clone3.orig/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
Index: clone3/arch/powerpc/xmon/xmon.c
===================================================================
--- clone3.orig/arch/powerpc/xmon/xmon.c
+++ clone3/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
-static long bus_error_jmp[JMP_BUF_LEN];
+static long bus_error_jmp[SETJMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
@@ -338,7 +334,7 @@ static int xmon_core(struct pt_regs *reg
{
int cmd = 0;
struct bpt *bp;
- long recurse_jmp[JMP_BUF_LEN];
+ long recurse_jmp[SETJMP_BUF_LEN];
unsigned long offset;
unsigned long flags;
#ifdef CONFIG_SMP
@@ -1428,7 +1424,7 @@ void prregs(struct pt_regs *fp)
sync();
regs = *(struct pt_regs *)base;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error reading registers from "REG"\n",
@@ -1497,8 +1493,7 @@ void cacheflush(void)
cinval((void *) adrs);
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
}
@@ -1533,8 +1528,7 @@ read_spr(int n)
ret = code();
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
@@ -1569,8 +1563,7 @@ write_spr(int n, unsigned long val)
code(val);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
}
@@ -1676,8 +1669,7 @@ mread(unsigned long adrs, void *buf, int
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
catch_memory_errors = 0;
@@ -1713,8 +1705,7 @@ mwrite(unsigned long adrs, void *buf, in
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
} else {
printf("*** Error writing address %x\n", adrs + n);
@@ -2521,8 +2512,7 @@ static void xmon_print_symbol(unsigned l
name = kallsyms_lookup(address, &size, &offset, &modname,
tmpstr);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
@@ -2777,7 +2767,7 @@ static void stop_spus(void)
spu_mfc_sr1_set(spu, tmp);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
spu_info[i].stopped_ok = 1;
@@ -2817,7 +2807,7 @@ static void restart_spus(void)
spu_info[i].saved_spu_runcntl_RW);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
printf("Restarted spu %.2d\n", i);
} else {
@@ -2837,7 +2827,7 @@ do { \
printf(" %-*s = "format"\n", DUMP_WIDTH, \
#field, value); \
sync(); \
- __delay(200); \
+ __delay(SETJMP_MACHINE_CHECK_DELAY); \
} else { \
catch_memory_errors = 0; \
printf(" %-*s = *** Error reading field.\n", \
@@ -2899,7 +2889,7 @@ static void dump_spu_ls(unsigned long nu
sync();
ls_addr = (unsigned long)spu_info[num].spu->local_store;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error: accessing spu info for spu %d\n", num);
Index: clone3/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ clone3/include/asm-powerpc/setjmp.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define SETJMP_BUF_LEN 23
+#define SETJMP_MACHINE_CHECK_DELAY 200
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/2] kdump shutdown hook support
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2007-12-13 9:59 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
@ 2007-12-13 9:59 ` Michael Neuling
2008-01-17 4:45 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2 siblings, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2007-12-13 9:59 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 102 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 100 insertions(+), 5 deletions(-)
Index: clone3/arch/powerpc/kernel/crash.c
===================================================================
--- clone3.orig/arch/powerpc/kernel/crash.c
+++ clone3/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handlers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: clone3/include/asm-powerpc/kexec.h
===================================================================
--- clone3.orig/include/asm-powerpc/kexec.h
+++ clone3/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/2] Add crashdump shutdown hooks
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2007-12-13 9:59 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2007-12-13 9:59 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
@ 2008-01-17 4:45 ` Michael Neuling
2008-01-17 4:45 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2008-01-17 4:45 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2 siblings, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 4:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Updated for suggests made by Paulus
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 4:45 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
@ 2008-01-17 4:45 ` Michael Neuling
2008-01-17 5:38 ` Olof Johansson
2008-01-17 6:39 ` [PATCH 1/2] Make setjmp/longjmp code generic Stephen Rothwell
2008-01-17 4:45 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
1 sibling, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 4:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 65 +++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 +--
arch/powerpc/xmon/setjmp.S | 61 ----------------------------------------
arch/powerpc/xmon/xmon.c | 6 ---
include/asm-powerpc/setjmp.h | 18 +++++++++++
5 files changed, 86 insertions(+), 70 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/misc.S
+++ linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,64 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
Index: linux-2.6-ozlabs/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/setjmp.S
+++ linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
@@ -12,67 +12,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
/*
* Grab the register values as they are now.
* This won't do a particularily good job because we really
Index: linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/xmon.c
+++ linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
static long bus_error_jmp[JMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define JMP_BUF_LEN 23
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/2] kdump shutdown hook support
2008-01-17 4:45 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2008-01-17 4:45 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
@ 2008-01-17 4:45 ` Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 4:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, THEMANN
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 106 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 104 insertions(+), 5 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handlers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[JMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,41 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ /*
+ * wait a little while to see if we get a
+ * machine check
+ */
+ __delay(200);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: linux-2.6-ozlabs/include/asm-powerpc/kexec.h
===================================================================
--- linux-2.6-ozlabs.orig/include/asm-powerpc/kexec.h
+++ linux-2.6-ozlabs/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 5:38 ` Olof Johansson
@ 2008-01-17 5:36 ` Michael Neuling
2008-01-17 6:36 ` Stephen Rothwell
` (2 more replies)
0 siblings, 3 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 5:36 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In message <20080117053857.GA29035@lixom.net> you wrote:
> Hi,
>
> On Thu, Jan 17, 2008 at 03:45:42PM +1100, Michael Neuling wrote:
>
> > Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > ===================================================================
> > --- /dev/null
> > +++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > @@ -0,0 +1,18 @@
> > +/*
> > + * Copyright (C) 2007 Michael Neuling
^^^^^^
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version
> > + * 2 of the License, or (at your option) any later version.
> > + *
> > + */
> > +#ifndef _ASM_POWERPC_SETJMP_H
> > +#define _ASM_POWERPC_SETJMP_H
> > +
> > +#define JMP_BUF_LEN 23
> > +
> > +extern long setjmp(long *);
> > +extern void longjmp(long *, long);
> > +
> > +#endif /* _ASM_POWERPC_SETJMP_H */
>
> Should the above be inside #ifdef __KERNEL__?
Yep... _and_ it's 2008 now!
I'll update.
Mikey
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 4:45 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
@ 2008-01-17 5:38 ` Olof Johansson
2008-01-17 5:36 ` Michael Neuling
2008-01-17 6:39 ` [PATCH 1/2] Make setjmp/longjmp code generic Stephen Rothwell
1 sibling, 1 reply; 35+ messages in thread
From: Olof Johansson @ 2008-01-17 5:38 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
Hi,
On Thu, Jan 17, 2008 at 03:45:42PM +1100, Michael Neuling wrote:
> Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2007 Michael Neuling
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + */
> +#ifndef _ASM_POWERPC_SETJMP_H
> +#define _ASM_POWERPC_SETJMP_H
> +
> +#define JMP_BUF_LEN 23
> +
> +extern long setjmp(long *);
> +extern void longjmp(long *, long);
> +
> +#endif /* _ASM_POWERPC_SETJMP_H */
Should the above be inside #ifdef __KERNEL__?
-Olof
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 5:36 ` Michael Neuling
@ 2008-01-17 6:36 ` Stephen Rothwell
2008-01-17 12:45 ` Josh Boyer
2008-01-17 22:16 ` [PATCH] Add crashdump shutdown hooks Michael Neuling
2 siblings, 0 replies; 35+ messages in thread
From: Stephen Rothwell @ 2008-01-17 6:36 UTC (permalink / raw)
To: Michael Neuling
Cc: Olof Johansson, linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
[-- Attachment #1: Type: text/plain, Size: 459 bytes --]
On Thu, 17 Jan 2008 16:36:49 +1100 Michael Neuling <mikey@neuling.org> wrote:
>
> >
> > Should the above be inside #ifdef __KERNEL__?
>
> Yep... _and_ it's 2008 now!
I think that if you don't list the file for exporting to user mode (in
the Kbuild file), then you shouldn't need the __KERNEL__ protectors.
But it is, indeed, 2008. :-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 4:45 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2008-01-17 5:38 ` Olof Johansson
@ 2008-01-17 6:39 ` Stephen Rothwell
1 sibling, 0 replies; 35+ messages in thread
From: Stephen Rothwell @ 2008-01-17 6:39 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
[-- Attachment #1: Type: text/plain, Size: 527 bytes --]
On Thu, 17 Jan 2008 15:45:42 +1100 Michael Neuling <mikey@neuling.org> wrote:
>
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
> @@ -8,6 +8,8 @@
> * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
> * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
> *
> + * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
^^^^^^^^^^^^^^
This doesn't exist here.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 5:36 ` Michael Neuling
2008-01-17 6:36 ` Stephen Rothwell
@ 2008-01-17 12:45 ` Josh Boyer
2008-01-17 21:49 ` Michael Ellerman
2008-01-17 22:16 ` [PATCH] Add crashdump shutdown hooks Michael Neuling
2 siblings, 1 reply; 35+ messages in thread
From: Josh Boyer @ 2008-01-17 12:45 UTC (permalink / raw)
To: Michael Neuling
Cc: Olof Johansson, linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
On Thu, 17 Jan 2008 16:36:49 +1100
Michael Neuling <mikey@neuling.org> wrote:
>
>
> In message <20080117053857.GA29035@lixom.net> you wrote:
> > Hi,
> >
> > On Thu, Jan 17, 2008 at 03:45:42PM +1100, Michael Neuling wrote:
> >
> > > Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > > ===================================================================
> > > --- /dev/null
> > > +++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > > @@ -0,0 +1,18 @@
> > > +/*
> > > + * Copyright (C) 2007 Michael Neuling
> ^^^^^^
>
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > > + * modify it under the terms of the GNU General Public License
> > > + * as published by the Free Software Foundation; either version
> > > + * 2 of the License, or (at your option) any later version.
> > > + *
> > > + */
> > > +#ifndef _ASM_POWERPC_SETJMP_H
> > > +#define _ASM_POWERPC_SETJMP_H
> > > +
> > > +#define JMP_BUF_LEN 23
> > > +
> > > +extern long setjmp(long *);
> > > +extern void longjmp(long *, long);
> > > +
> > > +#endif /* _ASM_POWERPC_SETJMP_H */
> >
> > Should the above be inside #ifdef __KERNEL__?
>
> Yep... _and_ it's 2008 now!
>
> I'll update.
While you're off updating it, remove the (C). It's bogus and shouldn't
be there.
josh
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-17 12:45 ` Josh Boyer
@ 2008-01-17 21:49 ` Michael Ellerman
0 siblings, 0 replies; 35+ messages in thread
From: Michael Ellerman @ 2008-01-17 21:49 UTC (permalink / raw)
To: Josh Boyer
Cc: Michael Neuling, THEMANN, linuxppc-dev, RAISCH, Paul Mackerras,
Olof Johansson
[-- Attachment #1: Type: text/plain, Size: 1837 bytes --]
On Thu, 2008-01-17 at 06:45 -0600, Josh Boyer wrote:
> On Thu, 17 Jan 2008 16:36:49 +1100
> Michael Neuling <mikey@neuling.org> wrote:
> > In message <20080117053857.GA29035@lixom.net> you wrote:
> > > Hi,
> > >
> > > On Thu, Jan 17, 2008 at 03:45:42PM +1100, Michael Neuling wrote:
> > >
> > > > Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > > > ===================================================================
> > > > --- /dev/null
> > > > +++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
> > > > @@ -0,0 +1,18 @@
> > > > +/*
> > > > + * Copyright (C) 2007 Michael Neuling
> > ^^^^^^
> >
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > > + * modify it under the terms of the GNU General Public License
> > > > + * as published by the Free Software Foundation; either version
> > > > + * 2 of the License, or (at your option) any later version.
> > > > + *
> > > > + */
> > > > +#ifndef _ASM_POWERPC_SETJMP_H
> > > > +#define _ASM_POWERPC_SETJMP_H
> > > > +
> > > > +#define JMP_BUF_LEN 23
> > > > +
> > > > +extern long setjmp(long *);
> > > > +extern void longjmp(long *, long);
> > > > +
> > > > +#endif /* _ASM_POWERPC_SETJMP_H */
> > >
> > > Should the above be inside #ifdef __KERNEL__?
> >
> > Yep... _and_ it's 2008 now!
> >
> > I'll update.
>
> While you're off updating it, remove the (C). It's bogus and shouldn't
> be there.
And it should say IBM corp too.
Oh and my car needs a wash when you're free ..
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH] Add crashdump shutdown hooks
2008-01-17 5:36 ` Michael Neuling
2008-01-17 6:36 ` Stephen Rothwell
2008-01-17 12:45 ` Josh Boyer
@ 2008-01-17 22:16 ` Michael Neuling
2008-01-17 22:16 ` [PATCH] Make setjmp/longjmp code generic Michael Neuling
2008-01-18 4:50 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2 siblings, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 22:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, Stephen Rothwell, THEMANN
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Updated some comments in the code, as noticed by sfr, Josh Boyer and a
dirty car owner.
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH] Make setjmp/longjmp code generic
2008-01-17 22:16 ` [PATCH] Add crashdump shutdown hooks Michael Neuling
@ 2008-01-17 22:16 ` Michael Neuling
2008-01-18 4:50 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-17 22:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, RAISCH, Stephen Rothwell, THEMANN
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 6605 bytes --]
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 65 +++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 +--
arch/powerpc/xmon/setjmp.S | 61 ----------------------------------------
arch/powerpc/xmon/xmon.c | 6 ---
include/asm-powerpc/setjmp.h | 18 +++++++++++
5 files changed, 86 insertions(+), 70 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/misc.S
+++ linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,64 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
Index: linux-2.6-ozlabs/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/setjmp.S
+++ linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
@@ -12,67 +12,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
/*
* Grab the register values as they are now.
* This won't do a particularily good job because we really
Index: linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/xmon.c
+++ linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
static long bus_error_jmp[JMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright © 2008 Michael Neuling IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define JMP_BUF_LEN 23
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/2] Add crashdump shutdown hooks
2008-01-17 22:16 ` [PATCH] Add crashdump shutdown hooks Michael Neuling
2008-01-17 22:16 ` [PATCH] Make setjmp/longjmp code generic Michael Neuling
@ 2008-01-18 4:50 ` Michael Neuling
2008-01-18 4:50 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2008-01-18 4:50 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
1 sibling, 2 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-18 4:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Sorry, last update didn't include both patches.
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/2] Make setjmp/longjmp code generic
2008-01-18 4:50 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
@ 2008-01-18 4:50 ` Michael Neuling
2008-01-18 4:50 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-18 4:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 6605 bytes --]
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 65 +++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 +--
arch/powerpc/xmon/setjmp.S | 61 ----------------------------------------
arch/powerpc/xmon/xmon.c | 6 ---
include/asm-powerpc/setjmp.h | 18 +++++++++++
5 files changed, 86 insertions(+), 70 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/misc.S
+++ linux-2.6-ozlabs/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,64 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
Index: linux-2.6-ozlabs/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/setjmp.S
+++ linux-2.6-ozlabs/arch/powerpc/xmon/setjmp.S
@@ -12,67 +12,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
/*
* Grab the register values as they are now.
* This won't do a particularily good job because we really
Index: linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/xmon.c
+++ linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
static long bus_error_jmp[JMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
Index: linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ linux-2.6-ozlabs/include/asm-powerpc/setjmp.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright © 2008 Michael Neuling IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define JMP_BUF_LEN 23
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/2] kdump shutdown hook support
2008-01-18 4:50 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2008-01-18 4:50 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
@ 2008-01-18 4:50 ` Michael Neuling
1 sibling, 0 replies; 35+ messages in thread
From: Michael Neuling @ 2008-01-18 4:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 106 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 104 insertions(+), 5 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handlers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handlers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handlers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[JMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,41 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ /*
+ * wait a little while to see if we get a
+ * machine check
+ */
+ __delay(200);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: linux-2.6-ozlabs/include/asm-powerpc/kexec.h
===================================================================
--- linux-2.6-ozlabs.orig/include/asm-powerpc/kexec.h
+++ linux-2.6-ozlabs/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2008-01-18 4:50 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-12 5:45 [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-12 7:01 ` Olof Johansson
2007-12-13 0:53 ` Michael Neuling
2007-12-12 23:07 ` Michael Ellerman
2007-12-13 0:04 ` Michael Neuling
2007-12-13 3:16 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2007-12-13 3:16 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-13 5:12 ` Olof Johansson
2007-12-13 5:13 ` Olof Johansson
2007-12-13 9:59 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2007-12-13 9:59 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2007-12-13 9:59 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2008-01-17 4:45 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2008-01-17 4:45 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2008-01-17 5:38 ` Olof Johansson
2008-01-17 5:36 ` Michael Neuling
2008-01-17 6:36 ` Stephen Rothwell
2008-01-17 12:45 ` Josh Boyer
2008-01-17 21:49 ` Michael Ellerman
2008-01-17 22:16 ` [PATCH] Add crashdump shutdown hooks Michael Neuling
2008-01-17 22:16 ` [PATCH] Make setjmp/longjmp code generic Michael Neuling
2008-01-18 4:50 ` [PATCH 0/2] Add crashdump shutdown hooks Michael Neuling
2008-01-18 4:50 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
2008-01-18 4:50 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2008-01-17 6:39 ` [PATCH 1/2] Make setjmp/longjmp code generic Stephen Rothwell
2008-01-17 4:45 ` [PATCH 2/2] kdump shutdown hook support Michael Neuling
2007-12-13 3:16 ` [PATCH 1/2] Make setjmp/longjmp code generic Michael Neuling
-- strict thread matches above, loose matches on Subject: below --
2007-12-12 5:45 Michael Neuling
2007-12-12 7:59 ` Kumar Gala
2007-12-12 8:06 ` Benjamin Herrenschmidt
2007-12-12 9:37 ` Stephen Rothwell
2007-12-12 9:44 ` Benjamin Herrenschmidt
2007-12-12 11:09 ` Michael Neuling
2007-12-12 22:56 ` Michael Ellerman
2007-12-12 23:40 ` Michael Neuling
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).