summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/ofw/rtas.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/powerpc/ofw/rtas.c b/sys/powerpc/ofw/rtas.c
index 59692c9..66ce12f 100644
--- a/sys/powerpc/ofw/rtas.c
+++ b/sys/powerpc/ofw/rtas.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
@@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/md_var.h>
+#include <machine/pcb.h>
#include <machine/pmap.h>
#include <machine/rtas.h>
#include <machine/stdarg.h>
@@ -60,6 +62,8 @@ int rtascall(vm_offset_t callbuffer, uintptr_t rtas_privdat);
extern uintptr_t rtas_entry;
extern register_t rtasmsr;
+int setfault(faultbuf); /* defined in locore.S */
+
/*
* After the VM is up, allocate RTAS memory and instantiate it
*/
@@ -188,6 +192,7 @@ int
rtas_call_method(cell_t token, int nargs, int nreturns, ...)
{
vm_offset_t argsptr;
+ faultbuf env;
va_list ap;
struct {
cell_t token;
@@ -213,7 +218,19 @@ rtas_call_method(cell_t token, int nargs, int nreturns, ...)
args.args_n_results[n] = va_arg(ap, cell_t);
argsptr = rtas_real_map(&args, sizeof(args));
- result = rtascall(argsptr, rtas_private_data);
+
+ /* Get rid of any stale machine checks that have been waiting. */
+ __asm __volatile ("sync; isync");
+ if (!setfault(env)) {
+ __asm __volatile ("sync");
+ result = rtascall(argsptr, rtas_private_data);
+ __asm __volatile ("sync; isync");
+ } else {
+ result = RTAS_HW_ERROR;
+ }
+ curthread->td_pcb->pcb_onfault = 0;
+ __asm __volatile ("sync");
+
rtas_real_unmap(argsptr, &args, sizeof(args));
mtx_unlock(&rtas_mtx);
OpenPOWER on IntegriCloud