[PATCH] (2.6) os-term call upon kernel panic
Mike Strosaker
strosake at austin.ibm.com
Fri Feb 27 11:02:55 EST 2004
This patch will cause the os-term RTAS call to be invoked after a
kernel panic. The call notifies the platform that the OS is terminating
normal operation, which causes the service processor (on systems so
equipped) to perform some pre-defined actions (like a call home). The
os-term routine is given the lowest priority on panic_notifier_list so
that it will be the last routine invoked, since it may not return.
Comments welcome.
Thanks,
Mike
diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c
--- a/arch/ppc64/kernel/chrp_setup.c Thu Feb 26 16:54:18 2004
+++ b/arch/ppc64/kernel/chrp_setup.c Thu Feb 26 16:54:18 2004
@@ -268,6 +268,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;
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c Thu Feb 26 16:54:18 2004
+++ b/arch/ppc64/kernel/iSeries_setup.c Thu Feb 26 16:54:18 2004
@@ -323,6 +323,7 @@
ppc_md.restart = iSeries_restart;
ppc_md.power_off = iSeries_power_off;
ppc_md.halt = iSeries_halt;
+ ppc_md.panic = iSeries_panic;
ppc_md.get_boot_time = iSeries_get_boot_time;
ppc_md.set_rtc_time = iSeries_set_rtc_time;
@@ -790,6 +791,14 @@
void iSeries_halt(void)
{
mf_powerOff();
+}
+
+/*
+ * Document me.
+ */
+void iSeries_panic(void)
+{
+ mf_reboot();
}
/* JDH Hack */
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c Thu Feb 26 16:54:18 2004
+++ b/arch/ppc64/kernel/rtas.c Thu Feb 26 16:54:18 2004
@@ -420,6 +420,17 @@
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)
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c Thu Feb 26 16:54:18 2004
+++ b/arch/ppc64/kernel/setup.c Thu Feb 26 16:54:18 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,12 @@
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.
@@ -316,6 +323,13 @@
EXPORT_SYMBOL(machine_halt);
+static int ppc64_panic_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ ppc_md.panic(); /* May not return */
+ return NOTIFY_DONE;
+}
+
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
@@ -610,8 +624,9 @@
dcache_bsize = systemcfg->dCacheL1LineSize;
icache_bsize = systemcfg->iCacheL1LineSize;
- /* reboot on panic */
- panic_timeout = 180;
+ /* do not reboot on panic */
+ panic_timeout = 0;
+ notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h Thu Feb 26 16:54:18 2004
+++ b/include/asm-ppc64/machdep.h Thu Feb 26 16:54:18 2004
@@ -82,6 +82,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 *);
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h Thu Feb 26 16:54:18 2004
+++ b/include/asm-ppc64/rtas.h Thu Feb 26 16:54:18 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);
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list