(resend) [PATCH] (2.6) os-term call upon kernel panic

olof at austin.ibm.com olof at austin.ibm.com
Fri Feb 27 12:15:23 EST 2004


A couple of comments:

* on iSeries, it'll result in an instant reboot, maybe not desirable
* no support for G5, will result in NULL branch. Panic will panic. :)
* if the RTAS os-term call for some reason fails (can it?), the system
  won't reboot since panic_timeout is 0.

Attached patch resolves those issues by not setting ppc_md.panic on pmac
and iSeries, and only registers the notifier in case it's set. The timeout
is kept at 180 even though it won't be used on a successful panic on
pSeries.

I've tried building it, but I didn't test it much.


-Olof


Olof Johansson                                        Office: 4E002/905
Linux on Power Development                            IBM Systems Group
Email: olof at austin.ibm.com                          Phone: 512-838-9858
All opinions are my own and not those of IBM

-------------- next part --------------
===== arch/ppc64/kernel/chrp_setup.c 1.56 vs edited =====
--- 1.56/arch/ppc64/kernel/chrp_setup.c	Thu Feb 26 04:56:03 2004
+++ edited/arch/ppc64/kernel/chrp_setup.c	Thu Feb 26 18:47:17 2004
@@ -266,6 +266,7 @@
 	ppc_md.restart        = rtas_restart;
 	ppc_md.power_off      = rtas_power_off;
 	ppc_md.halt           = rtas_halt;
+	ppc_md.panic          = rtas_os_term;
 
 	ppc_md.get_boot_time  = pSeries_get_boot_time;
 	ppc_md.get_rtc_time   = pSeries_get_rtc_time;
===== arch/ppc64/kernel/rtas.c 1.24 vs edited =====
--- 1.24/arch/ppc64/kernel/rtas.c	Tue Feb 24 22:28:40 2004
+++ edited/arch/ppc64/kernel/rtas.c	Thu Feb 26 18:48:28 2004
@@ -420,6 +420,18 @@
         rtas_power_off();
 }
 
+void
+rtas_os_term(void)
+{
+	long status;
+	char *str = "OS panic";
+
+	status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, __pa(str));
+	if (status != 0)
+		printk(KERN_EMERG "ibm,os-term call failed %ld\n", status);
+}
+
+
 unsigned long rtas_rmo_buf = 0;
 
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
===== arch/ppc64/kernel/setup.c 1.61 vs edited =====
--- 1.61/arch/ppc64/kernel/setup.c	Tue Feb 24 21:57:17 2004
+++ edited/arch/ppc64/kernel/setup.c	Thu Feb 26 19:02:59 2004
@@ -25,6 +25,7 @@
 #include <linux/version.h>
 #include <linux/tty.h>
 #include <linux/root_dev.h>
+#include <linux/notifier.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -93,6 +94,13 @@
 
 struct machdep_calls ppc_md;
 
+static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
+
+static struct notifier_block ppc64_panic_block = {
+	notifier_call: ppc64_panic_event,
+	priority: INT_MIN /* may not return; must be done last */
+};
+
 /*
  * Perhaps we can put the pmac screen_info[] here
  * on pmac as well so we don't need the ifdef's.
@@ -319,6 +327,14 @@
 unsigned long ppc_proc_freq;
 unsigned long ppc_tb_freq;
 
+static int ppc64_panic_event(struct notifier_block *this,
+                             unsigned long event, void *ptr)
+{
+	ppc_md.panic();         /* May not return */
+	return NOTIFY_DONE;
+}
+
+
 #ifdef CONFIG_SMP
 DEFINE_PER_CPU(unsigned int, pvr);
 #endif
@@ -610,8 +626,11 @@
 	dcache_bsize = systemcfg->dCacheL1LineSize; 
 	icache_bsize = systemcfg->iCacheL1LineSize; 
 
 	/* reboot on panic */
 	panic_timeout = 180;
+
+	if (ppc_md.panic)
+		notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
 
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
===== include/asm-ppc64/machdep.h 1.34 vs edited =====
--- 1.34/include/asm-ppc64/machdep.h	Thu Feb 26 04:56:03 2004
+++ edited/include/asm-ppc64/machdep.h	Thu Feb 26 18:47:18 2004
@@ -81,6 +81,7 @@
 	void		(*restart)(char *cmd);
 	void		(*power_off)(void);
 	void		(*halt)(void);
+	void		(*panic)(void);
 
 	int		(*set_rtc_time)(struct rtc_time *);
 	void		(*get_rtc_time)(struct rtc_time *);
===== include/asm-ppc64/rtas.h 1.17 vs edited =====
--- 1.17/include/asm-ppc64/rtas.h	Mon Jan 19 20:08:24 2004
+++ edited/include/asm-ppc64/rtas.h	Thu Feb 26 18:56:39 2004
@@ -175,6 +175,7 @@
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(void);
 extern void rtas_halt(void);
+extern void rtas_os_term(void);
 extern int rtas_get_sensor(int sensor, int index, int *state);
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_indicator(int indicator, int index, int new_value);


More information about the Linuxppc64-dev mailing list