[OpenBIOS] sparc32 trap recovery

Bob Breuer breuerr at mc.net
Tue Jun 25 17:40:19 CEST 2013


On 6/19/2013 9:44 AM, Bob Breuer wrote:
> So how about if I setup an interrupt handler that skips over the
> faulting instruction when a global flag is set, otherwise continues as
> is today.  Then cpeek can become:
>  - set skip_datafault flag
>  - clear SFSR
>  - chain to c@
>  - clear skip_datafault flag
>  - check SFSR
>  - if fault, fixup stack and return false, else return true
> 
> Now, I might be able to code up this cpeek version in forth, or just
> leave it in C?


Here's what I've got.  If it looks ok, I will finish it off by also catching 
trap 0x29, modify wpeek/lpeek to also use the wrapper, and make a similar change 
for the poke commands.


Index: forth/device/other.fs
===================================================================
--- forth/device/other.fs	(revision 1160)
+++ forth/device/other.fs	(working copy)
@@ -20,8 +20,12 @@
 
 \ 5.3.7.1 Peek/poke 
 
+defer (peek-wrapper)
+: (peek-default) execute true ;
+['] (peek-default) to (peek-wrapper)
+
 : cpeek    ( addr -- false | byte true )
-  c@ true
+  ['] c@ (peek-wrapper)
   ;
 
 : wpeek    ( waddr -- false | w true )
Index: arch/sparc32/vectors.S
===================================================================
--- arch/sparc32/vectors.S	(revision 1160)
+++ arch/sparc32/vectors.S	(working copy)
@@ -41,6 +41,9 @@
 #define WINDOW_FILL \
         rd %psr, %l0; rd %wim, %l3; b fill_window_entry; nop;
 
+#define TRAP_DFAULT(lvl) \
+        rd %psr, %l0; rd %wim, %l3; b do_dfault; mov lvl, %l7;
+
 #define BTRAP(lvl) ba bug; mov lvl, %g1; nop; nop;
 #define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
 #define TRAP_ENTRY_INTERRUPT(int_level) \
@@ -54,7 +57,11 @@
 t_wovf:         WINDOW_SPILL                        /* Window Overflow               */
 t_wunf:         WINDOW_FILL                         /* Window Underflow              */
                 BTRAP(0x7)
-                BTRAPS(0x8)
+                BTRAP(0x8)
+                TRAP_DFAULT(0x9)
+                BTRAP(0xa) BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
+
+
 #if 0
                 BAD_TRAP(0x10)
 t_irq1:         TRAP_ENTRY_INTERRUPT(1)             /* IRQ Software/SBUS Level 1     */
@@ -206,6 +213,26 @@
 #include "wof.S"
 #include "wuf.S"
 
+/* data fault handler */
+	.data
+	.align	4
+	.global allow_dfault
+allow_dfault:
+	.word	0
+
+	.text
+	.align	4
+do_dfault:
+	/* if allow_dfault is 0, do old behavior */
+	set	allow_dfault, %l4
+	ld	[ %l4 ], %l4
+	tst	%l4
+	bz,a	bug
+	 mov	%l7, %g1
+	/* skip the faulting instruction */
+	jmp	%l2
+	rett	%l2+4
+
         .section .rodata
 _BUG_message_0:
         .string "Unhandled Exception 0x"
Index: arch/sparc32/lib.c
===================================================================
--- arch/sparc32/lib.c	(revision 1160)
+++ arch/sparc32/lib.c	(working copy)
@@ -302,6 +302,45 @@
     DPRINTF("obp_dumb_memfree 0x%p (size %d)\n", va, sz);
 }
 
+#include "asm/crs.h"
+
+extern unsigned int allow_dfault;
+
+static unsigned int get_sfsr(void)
+{
+	unsigned int sfsr;
+	__asm__ __volatile__(
+	"lda	[%1] %2, %0"
+	: "=r" (sfsr)
+	: "r" (AC_M_SFSR), "i" (ASI_M_MMUREGS));
+
+	return sfsr;
+}
+
+static void sparc_peek(void)
+{
+	unsigned int sfsr;
+
+	get_sfsr(); /* clear any stale fault status */
+	allow_dfault = 1;
+
+	fword("execute");
+
+	allow_dfault = 0;
+	sfsr = get_sfsr();
+
+	if (sfsr == 0)
+	{
+		PUSH(-1); /* true */
+	}
+	else
+	{
+		/* drop failed read, return false */
+		POP();
+		PUSH(0);
+	}
+}
+
 void
 ob_init_mmu(void)
 {
@@ -360,6 +399,9 @@
     bind_func("pgmap@", pgmap_fetch);
     bind_func("pgmap!", pgmap_store);
     bind_func("map-pages", ob_map_pages);
+
+    PUSH_xt( bind_noname_func(sparc_peek) );
+    feval("to (peek-wrapper)");
 }
 
 /*




More information about the OpenBIOS mailing list