linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [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; 27+ 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] 27+ messages in thread

end of thread, other threads:[~2008-01-18  4:50 UTC | newest]

Thread overview: 27+ 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 1/2] Make setjmp/longjmp code generic 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 2/2] kdump shutdown hook support 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

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).