--- /dev/null 2013-06-03 22:12:02.175283357 -0500 +++ arch/sparc32/traps.S 2013-06-15 09:32:34.968976086 -0500 @@ -0,0 +1,87 @@ +/* + * Trap handlers to allow recovery + */ + + .data + .align 4 +handler_list: + .word 0 + + .text + .align 4 + +#define STACKFRAME_SZ 0x60 + +#define FLUSH_ALL_WINDOWS \ + save; save; save; save; save; save; save; save; \ + restore; restore; restore; restore; restore; restore; restore; restore; + + .globl push_trap_handler, pop_trap_handler +/* int push_trap_handler(reg_save_t* o0) + * like setjmp(), reg_save_t = 64 bytes, 8 byte aligned + */ +push_trap_handler: + STORE_WINDOW(o0) + /* save globals */ + std %g2, [ %o0 + 0x48 ] + std %g4, [ %o0 + 0x50 ] + std %g6, [ %o0 + 0x58 ] + /* args, sp, ret_address */ + std %o0, [ %o0 + 0x60 ] + std %o2, [ %o0 + 0x68 ] + std %o4, [ %o0 + 0x70 ] + std %o6, [ %o0 + 0x78 ] /* %sp and return address */ + /* add this frame to the list */ + set handler_list, %g1 + ld [ %g1 ], %o1 + st %o0, [ %g1 ] + st %o1, [ %o0 + 0x40 ] /* save previous handler */ + + mov 0, %o0 /* ready */ + retl + nop + +/* int pop_trap_handler(reg_save_t* o0) + */ +pop_trap_handler: + ld [ %o0 + 0x40 ], %o1 + set handler_list, %g1 + st %o1, [ %g1 ] + retl + nop + +/* like longjmp() + * %o0 = trap number + * %o1, %g1 = temporaries (not restored) + */ +do_trap_handler: + FLUSH_ALL_WINDOWS + set handler_list, %g1 + ld [ %g1 ], %o1 + /* restore all registers */ + LOAD_WINDOW(o1) + ldd [ %o1 + 0x48 ], %g2 + ldd [ %o1 + 0x50 ], %g4 + ldd [ %o1 + 0x58 ], %g6 + /* skip %o0, %o1 */ + ldd [ %o1 + 0x68 ], %o2 + ldd [ %o1 + 0x70 ], %o4 + ldd [ %o1 + 0x78 ], %o6 + retl + nop + + +do_trap: + /* if handler is NULL, do old behavior */ + set handler_list, %l4 + ld [ %l4 ], %l4 + tst %l4 + bz,a bug + mov %l7, %g1 + /* just redirect to the handler */ + set do_trap_handler, %l4 + mov %l7, %i0 /* becomes %o0 for handler */ + /* return from trap */ + jmp %l4 + rett %l4+4 + Index: arch/sparc32/vectors.S =================================================================== --- arch/sparc32/vectors.S (revision 1156) +++ arch/sparc32/vectors.S (working copy) @@ -54,7 +54,11 @@ t_wovf: WINDOW_SPILL /* Window Overflow */ t_wunf: WINDOW_FILL /* Window Underflow */ BTRAP(0x7) - BTRAPS(0x8) + BTRAP(0x8) + rd %psr, %l0; rd %wim, %l3; b do_trap; mov 9, %l7 + 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 +210,8 @@ #include "wof.S" #include "wuf.S" +#include "traps.S" + .section .rodata _BUG_message_0: .string "Unhandled Exception 0x" Index: arch/sparc32/lib.c =================================================================== --- arch/sparc32/lib.c (revision 1156) +++ arch/sparc32/lib.c (working copy) @@ -302,6 +302,36 @@ DPRINTF("obp_dumb_memfree 0x%p (size %d)\n", va, sz); } +struct reg_save { + uint64_t regs[16]; +}; +int push_trap_handler(struct reg_save *rs) __attribute__ ((returns_twice)); +void pop_trap_handler(struct reg_save *rs); + +static void try_fault(void) +{ + uint32_t addr; + unsigned char c; + struct reg_save rs; + int trap; + + addr = POP(); + printk("\ntrying address 0x%x\n", addr); + trap = push_trap_handler(&rs); + if (trap == 0) + { + c = *(unsigned char*)addr; + PUSH(c); + PUSH(-1); /* true */ + } + else + { + PUSH(0); /* false */ + } + pop_trap_handler(&rs); + printk("trap = 0x%x\n", trap); +} + void ob_init_mmu(void) { @@ -360,6 +390,7 @@ bind_func("pgmap@", pgmap_fetch); bind_func("pgmap!", pgmap_store); bind_func("map-pages", ob_map_pages); + bind_func("try-fault", try_fault); } /*