X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fs390%2Fmd.c;h=6129ff20a1db309d808130c084cb6b6cd47a9d6b;hb=bfb7d15b502b8170ec8a9b348c546418c0e44ace;hp=e3d250353b175726564b2aa8bd535bea699f3e68;hpb=2457ad8bcdb80a1026380a158052aa91ad06651d;p=cacao.git diff --git a/src/vm/jit/s390/md.c b/src/vm/jit/s390/md.c index e3d250353..6129ff20a 100644 --- a/src/vm/jit/s390/md.c +++ b/src/vm/jit/s390/md.c @@ -28,22 +28,10 @@ Changes: Edwin Steiner - $Id: md.c 7581 2007-03-26 07:23:16Z pm $ + $Id: md.c 7848 2007-05-01 21:40:26Z pm $ */ -#define REG_RSP 0 -#define REG_RIP 0 -#define REG_RAX 0 -#define REG_R10 0 -#define REG_RIP 0 -#define REG_RSP 0 -#define REG_RIP 0 -#define REG_RAX 0 -#define REG_R10 0 -#define REG_RIP 0 - - #define _GNU_SOURCE #include "config.h" @@ -55,6 +43,7 @@ #include "vm/jit/s390/md-abi.h" #if defined(ENABLE_THREADS) +# include "threads/threads-common.h" # include "threads/native/threads.h" #endif @@ -74,6 +63,12 @@ #include #define OOPS() assert(0); +/* prototypes *****************************************************************/ + +void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p); + +void md_dump_context(u1 *pc, mcontext_t *mc); + /* md_init ********************************************************************* Do some machine dependent initialization. @@ -82,9 +77,58 @@ void md_init(void) { - /* nothing to do */ + struct sigaction act; + + act.sa_sigaction = md_signal_handler_sigill; + act.sa_flags = SA_NODEFER | SA_SIGINFO; + + if (sigaction(SIGILL, &act, NULL) == -1) { + vm_abort("%s: error registering SIGILL signal handler.", __FUNCTION__); + } } +/* md_dump_context ************************************************************ + + Logs the machine context + +*******************************************************************************/ + +void md_dump_context(u1 *pc, mcontext_t *mc) { + int i; + + union { + u8 l; + fpreg_t fr; + } freg; + + log_println("Dumping context."); + + log_println("Program counter: 0x%08X", pc); + +#if defined(ENABLE_DISASSEMBLER) + log_println("Printing instruction at program counter:"); + disassinstr(pc); +#endif + + log_println("General purpose registers:"); + + for (i = 0; i < 16; i++) { + log_println("\tr%d:\t0x%08X\t%d", i, mc->gregs[i], mc->gregs[i]); + } + + log_println("Floating point registers:"); + + for (i = 0; i < 16; i++) { + freg.fr.d = mc->fpregs.fprs[i].d; + log_println("\tf%d\t0x%016llX\t(double)%e\t(float)%f", i, freg.l, freg.fr.d, freg.fr.f); + } + +#if defined(ENABLE_THREADS) + log_println("Dumping the current stacktrace:"); + threads_print_stacktrace(); +#endif + +} /* md_signal_handler_sigsegv *************************************************** @@ -95,35 +139,102 @@ void md_init(void) void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *sp; - u1 *ra; - u1 *xpc; + ucontext_t *_uc; + mcontext_t *_mc; + u1 *pv; + u1 *sp; + u1 *ra; + u1 *xpc; + s4 type; + ptrint val; + java_objectheader *e; + s4 base; + s4 is_null; _uc = (ucontext_t *) _p; _mc = &_uc->uc_mcontext; - /* ATTENTION: Don't use CACAO's internal REG_* defines as they are - different to the ones in . */ - - sp = (u1 *) _mc->gregs[REG_RSP]; - xpc = (u1 *) _mc->gregs[REG_RIP]; - ra = xpc; /* return address is equal to xpc */ - -#if 0 - /* check for StackOverflowException */ + xpc = (u1 *)_mc->psw.addr; + + /* Check opcodes and verify it is a null pointer exception */ + + switch (xpc[0]) { + case 0x58: /* L */ + case 0x50: /* ST */ + base = (xpc[2] >> 4) & 0xF; + if (base == 0) { + is_null = 1; + } else if (_mc->gregs[base] == 0) { + is_null = 1; + } else { + is_null = 0; + } + break; + } - threads_check_stackoverflow(sp); + if (! is_null) { +#if !defined(NDEBUG) + md_dump_context(xpc, _mc); #endif + vm_abort("%s: segmentation fault at %p, aborting.", __FUNCTION__, xpc); + } + + pv = (u1 *)_mc->gregs[REG_PV]; + sp = (u1 *)_mc->gregs[REG_SP]; + ra = xpc; + type = EXCEPTION_HARDWARE_NULLPOINTER; + val = 0; - _mc->gregs[REG_RAX] = - (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc); + e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val); - _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */ - _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception; + _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc; + _mc->gregs[REG_ITMP1_XPTR] = (ptrint) e; + _mc->psw.addr = (ptrint) asm_handle_exception; } +void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p) { + ucontext_t *_uc; + mcontext_t *_mc; + u1 *xpc; + u1 *ra; + u1 *pv; + u1 *sp; + s4 type; + ptrint val; + java_objectheader *e; + s4 reg; + + _uc = (ucontext_t *) _p; + _mc = &_uc->uc_mcontext; + xpc = ra = siginfo->si_addr; + + /* Our trap instruction has the format: { 0x02, one_byte_of_data }. */ + + if ((siginfo->si_code == ILL_ILLOPC) && (xpc[0] == 0x02)) { + + /* bits 7-4 contain a register holding a value */ + reg = (xpc[1] >> 4) & 0xF; + + /* bits 3-0 designate the exception type */ + type = xpc[1] & 0xF; + + pv = (u1 *)_mc->gregs[REG_PV]; + sp = (u1 *)_mc->gregs[REG_SP]; + val = (ptrint)_mc->gregs[reg]; + + e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val); + + _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e; + _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc; + _mc->psw.addr = (ptrint) asm_handle_exception; + + } else { +#if !defined(NDEBUG) + md_dump_context(xpc, _mc); +#endif + vm_abort("%s: illegal instruction at %p, aborting.", __FUNCTION__, xpc); + } +} /* md_signal_handler_sigfpe **************************************************** @@ -134,27 +245,73 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *sp; - u1 *ra; - u1 *xpc; + ucontext_t *_uc; + mcontext_t *_mc; + u1 *pv; + u1 *sp; + u1 *ra; + u1 *xpc; + u1 *pc; + s4 r1, r2; + s4 type; + ptrint val; + java_objectheader *e; _uc = (ucontext_t *) _p; _mc = &_uc->uc_mcontext; - /* ATTENTION: Don't use CACAO's internal REG_* defines as they are - different to the ones in . */ + /* Instruction that raised signal */ + xpc = siginfo->si_addr; + + /* Check opcodes */ + + if (xpc[0] == 0x1D) { /* DR */ + + r1 = (xpc[1] >> 4) & 0xF; + r2 = xpc[1] & 0xF; + + if ( + (_mc->gregs[r1] == 0xFFFFFFFF) && + (_mc->gregs[r1 + 1] == 0x80000000) && + (_mc->gregs[r2] == 0xFFFFFFFF) + ) { + /* handle special case */ + /* next instruction */ + pc = (u1 *)_mc->psw.addr; + /* reminder */ + _mc->gregs[r1] = 0; + /* quotient */ + _mc->gregs[r1 + 1] = 0x80000000; + /* continue at next instruction */ + _mc->psw.addr = (ptrint) pc; - sp = (u1 *) _mc->gregs[REG_RSP]; - xpc = (u1 *) _mc->gregs[REG_RIP]; - ra = xpc; /* return address is equal to xpc */ + return; + } else if (_mc->gregs[r2] == 0) { + /* division by 0 */ - _mc->gregs[REG_RAX] = - (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc); + pv = (u1 *)_mc->gregs[REG_PV]; + sp = (u1 *)_mc->gregs[REG_SP]; + ra = xpc; - _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */ - _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception; + type = EXCEPTION_HARDWARE_ARITHMETIC; + val = 0; + + e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val); + + _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e; + _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc; + _mc->psw.addr = (ptrint) asm_handle_exception; + + return; + } + } + + /* Could not handle signal */ + +#if !defined(NDEBUG) + md_dump_context(xpc, _mc); +#endif + vm_abort("%s: floating point exception at %p, aborting.", __FUNCTION__, xpc); } @@ -180,7 +337,7 @@ void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p) /* ATTENTION: Don't use CACAO's internal REG_* defines as they are different to the ones in . */ - pc = (u1 *) _mc->gregs[REG_RIP]; + pc = (u1 *) _mc->psw.addr; t->pc = pc; } @@ -195,10 +352,10 @@ void thread_restartcriticalsection(ucontext_t *_uc) _mc = &_uc->uc_mcontext; - pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]); + pc = critical_find_restart_point((void *) _mc->psw.addr); if (pc != NULL) - _mc->gregs[REG_RIP] = (ptrint) pc; + _mc->psw.addr = (ptrint) pc; } #endif