summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/ofw/rtas.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2013-11-27 21:51:34 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2013-11-27 21:51:34 +0000
commitb9c058e8a0b756bce933dc2413bf8b9e654bccff (patch)
treef97ae917f3a3eee420d8b91e3bb50b60e7083644 /sys/powerpc/ofw/rtas.c
parentffd93c315fc1a63d1d968832713d7b137aa5a22a (diff)
downloadFreeBSD-src-b9c058e8a0b756bce933dc2413bf8b9e654bccff.zip
FreeBSD-src-b9c058e8a0b756bce933dc2413bf8b9e654bccff.tar.gz
Make RTAS calls, which call setfault() to recover from machine checks,
preserve any existing fault buffer. RTAS calls are meant to be safe from interrupt context (and are indeed used there to implement the xics PIC drvier). Without this, calling into RTAS in interrupt context would have the effect of clearing any existing onfault state of the interrupted thread, potentially leading to a panic.
Diffstat (limited to 'sys/powerpc/ofw/rtas.c')
-rw-r--r--sys/powerpc/ofw/rtas.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/sys/powerpc/ofw/rtas.c b/sys/powerpc/ofw/rtas.c
index 34b7acf..3e751b3 100644
--- a/sys/powerpc/ofw/rtas.c
+++ b/sys/powerpc/ofw/rtas.c
@@ -192,7 +192,7 @@ int
rtas_call_method(cell_t token, int nargs, int nreturns, ...)
{
vm_offset_t argsptr;
- faultbuf env;
+ faultbuf env, *oldfaultbuf;
va_list ap;
struct {
cell_t token;
@@ -221,6 +221,7 @@ rtas_call_method(cell_t token, int nargs, int nreturns, ...)
/* Get rid of any stale machine checks that have been waiting. */
__asm __volatile ("sync; isync");
+ oldfaultbuf = curthread->td_pcb->pcb_onfault;
if (!setfault(env)) {
__asm __volatile ("sync");
result = rtascall(argsptr, rtas_private_data);
@@ -228,7 +229,7 @@ rtas_call_method(cell_t token, int nargs, int nreturns, ...)
} else {
result = RTAS_HW_ERROR;
}
- curthread->td_pcb->pcb_onfault = 0;
+ curthread->td_pcb->pcb_onfault = oldfaultbuf;
__asm __volatile ("sync");
rtas_real_unmap(argsptr, &args, sizeof(args));
OpenPOWER on IntegriCloud