From: Olof Johansson RTAS on IBM pSeries runs in real mode, so all pointers being passed in to it need to be in low memory. There's two places in the RAS code that passes in pointers to items on the stack, which might end up being above the limit. Below patch resolves this by creating a buffer in BSS + a lock for serialization. There's no reason to worry about contention on the lock, since rtas_call() also serializes on a single spinlock and this is an infrequent code path in the first place. --- 25-akpm/arch/ppc64/kernel/ras.c | 19 +++++++++++++++++-- 1 files changed, 17 insertions(+), 2 deletions(-) diff -puN arch/ppc64/kernel/ras.c~ppc64-move-epow-log-buffer-to-bss arch/ppc64/kernel/ras.c --- 25/arch/ppc64/kernel/ras.c~ppc64-move-epow-log-buffer-to-bss 2004-04-10 02:44:40.589710928 -0700 +++ 25-akpm/arch/ppc64/kernel/ras.c 2004-04-10 02:44:40.593710320 -0700 @@ -110,6 +110,9 @@ static int __init init_ras_IRQ(void) } __initcall(init_ras_IRQ); +static struct rtas_error_log log_buf; +static spinlock_t log_lock = SPIN_LOCK_UNLOCKED; + /* * Handle power subsystem events (EPOW). * @@ -124,11 +127,17 @@ ras_epow_interrupt(int irq, void *dev_id unsigned int size = sizeof(log_entry); long status = 0xdeadbeef; + spin_lock(&log_lock); + status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, 0x500, irq, RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, 1, /* Time Critical */ - __pa(&log_entry), size); + __pa(&log_buf), size); + + log_entry = log_buf; + + spin_unlock(&log_lock); udbg_printf("EPOW <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); @@ -157,11 +166,17 @@ ras_error_interrupt(int irq, void *dev_i long status = 0xdeadbeef; int fatal; + spin_lock(&log_lock); + status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, 0x500, irq, RTAS_INTERNAL_ERROR, 1, /* Time Critical */ - __pa(&log_entry), size); + __pa(&log_buf), size); + + log_entry = log_buf; + + spin_unlock(&log_lock); if ((status == 0) && (log_entry.severity >= SEVERITY_ERROR_SYNC)) fatal = 1; _