From: Stefan Ring Date: Sat, 7 Aug 2010 20:23:45 +0000 (+0200) Subject: * src/vm/jit/trap.cpp: Finally switched s390 to the new trap decoding method. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=aed95b0ea70495483786dde13566ea05c3869dee * src/vm/jit/trap.cpp: Finally switched s390 to the new trap decoding method. * src/vm/jit/s390/md.c: Simplified signal handlers, (md_executionstate_read, md_executionstate_write, md_trap_decode): Implemented. * src/vm/jit/s390/md-trap.h: Added MD_TRAP_COMPILER_FIXUP. Should fix icedtea/PR515 (s390 not building). --- diff --git a/src/vm/jit/s390/md-trap.h b/src/vm/jit/s390/md-trap.h index a5e05a071..3d3e4afe8 100644 --- a/src/vm/jit/s390/md-trap.h +++ b/src/vm/jit/s390/md-trap.h @@ -1,6 +1,6 @@ /* src/vm/jit/s390/md-trap.h - s390 hardware traps - Copyright (C) 2008 + Copyright (C) 2008, 2010 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -50,6 +50,18 @@ enum { TRAP_COUNTDOWN = 8 }; + +/** + * Macro to fixup a compiler stub. The XPC is the RA minus 2, + * because the RA points to the instruction after the call. + */ +#define MD_TRAP_COMPILER_FIXUP(xpc, ra, sp, pv) \ + do { \ + (pv) = (xpc); \ + (xpc) = (void*) (((uintptr_t) (ra)) - 2); \ + } while(0) + + #endif /* _MD_TRAP_H */ diff --git a/src/vm/jit/s390/md.c b/src/vm/jit/s390/md.c index bee38bb7d..95eb600ed 100644 --- a/src/vm/jit/s390/md.c +++ b/src/vm/jit/s390/md.c @@ -1,6 +1,6 @@ /* src/vm/jit/s390/md.c - machine dependent s390 Linux functions - Copyright (C) 2006, 2007, 2008 + Copyright (C) 2006, 2007, 2008, 2010 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -39,7 +39,6 @@ #include "vm/exceptions.hpp" #include "vm/signallocal.hpp" -#include "vm/jit/asmpart.h" #include "vm/jit/abi.h" #include "vm/jit/executionstate.h" #include "vm/jit/methodheader.h" @@ -49,7 +48,6 @@ #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) #include "vm/options.h" /* XXX debug */ -#include "vm/jit/disass.h" /* XXX debug */ #endif #include "vm/jit/codegen-common.hpp" @@ -129,152 +127,32 @@ void md_dump_context(u1 *pc, mcontext_t *mc) { stacktrace_print_current(); } -/* md_signal_handler_sigsegv *************************************************** - - NullPointerException signal handler for hardware null pointer - check. - -*******************************************************************************/ - +/** + * NullPointerException signal handler for hardware null pointer check. + */ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - int type; - intptr_t val; - void *p; - s4 base; - s4 is_null; + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; - - xpc = (u1 *)_mc->psw.addr; + void* xpc = (u1 *) _mc->psw.addr; - /* Check opcodes and verify it is a null pointer exception */ - - switch (N_RX_GET_OPC(xpc)) { - case OPC_L: - case OPC_ST: - case OPC_CL: /* array size check on NULL array */ - base = N_RX_GET_BASE(xpc); - if (base == 0) { - is_null = 1; - } else if (_mc->gregs[base] == 0) { - is_null = 1; - } else { - is_null = 0; - } - break; - default: - is_null = 0; - break; - } - - 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] - N_PV_OFFSET; - sp = (u1 *)_mc->gregs[REG_SP]; - ra = xpc; - type = TRAP_NullPointerException; - val = 0; - - /* Handle the trap. */ - - p = trap_handle(type, val, pv, sp, ra, xpc, _p); - - if (p != NULL) { - _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p; - _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc; - _mc->psw.addr = (uintptr_t) asm_handle_exception; - } - else { - _mc->psw.addr = (uintptr_t) xpc; - } + // Handle the trap. + trap_handle(TRAP_SIGSEGV, xpc, _p); } +/** + * Illegal Instruction signal handler for hardware exception checks. + */ 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; - int type; - intptr_t val; - void *p; - 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) && (N_RR_GET_OPC(xpc) == OPC_ILL)) { - - /* bits 7-4 contain a register holding a value */ - reg = N_ILL_GET_REG(xpc); - - /* bits 3-0 designate the exception type */ - type = N_ILL_GET_TYPE(xpc); - - pv = (u1 *)_mc->gregs[REG_PV] - N_PV_OFFSET; - sp = (u1 *)_mc->gregs[REG_SP]; - val = (ptrint)_mc->gregs[reg]; - - if (TRAP_COMPILER == type) { - /* The PV from the compiler stub is equal to the XPC. */ - - pv = xpc; - - /* The return address in is REG_RA */ + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - ra = (u1 *)_mc->gregs[REG_RA]; + void* xpc = siginfo->si_addr; - xpc = ra - 2; - } - - /* Handle the trap. */ - - p = trap_handle(type, val, pv, sp, ra, xpc, _p); - - if (TRAP_COMPILER == type) { - if (NULL == p) { - _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) builtin_retrieve_exception(); - _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) ra - 2; - _mc->gregs[REG_PV] = (uintptr_t) md_codegen_get_pv_from_pc(ra); - _mc->psw.addr = (uintptr_t) asm_handle_exception; - } else { - _mc->gregs[REG_PV] = (uintptr_t) p; - _mc->psw.addr = (uintptr_t) p; - } - } else { - if (p != NULL) { - _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p; - _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc; - _mc->psw.addr = (uintptr_t) asm_handle_exception; - } - else { - _mc->psw.addr = (uintptr_t) xpc; - } - } - } else { -#if !defined(NDEBUG) - md_dump_context(xpc, _mc); -#endif - vm_abort("%s: illegal instruction at %p, aborting.", __FUNCTION__, xpc); - } + // Handle the trap. + trap_handle(TRAP_SIGILL, xpc, _p); } /* md_signal_handler_sigfpe **************************************************** @@ -286,30 +164,15 @@ void md_signal_handler_sigill(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 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - u1 *pc; - int r1, r2; - int type; - intptr_t val; - void *p; - - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - /* Instruction that raised signal */ - xpc = siginfo->si_addr; - - /* Check opcodes */ + void* xpc = siginfo->si_addr; if (N_RR_GET_OPC(xpc) == OPC_DR) { /* DR */ - r1 = N_RR_GET_REG1(xpc); - r2 = N_RR_GET_REG2(xpc); + int r1 = N_RR_GET_REG1(xpc); + int r2 = N_RR_GET_REG2(xpc); if ( (_mc->gregs[r1] == 0xFFFFFFFF) && @@ -318,44 +181,20 @@ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p) ) { /* handle special case 0x80000000 / 0xFFFFFFFF that fails on hardware */ /* next instruction */ - pc = (u1 *)_mc->psw.addr; - /* reminder */ + u1 *pc = (u1 *)_mc->psw.addr; + /* remainder */ _mc->gregs[r1] = 0; /* quotient */ _mc->gregs[r1 + 1] = 0x80000000; /* continue at next instruction */ _mc->psw.addr = (ptrint) pc; - return; - } - else if (_mc->gregs[r2] == 0) { - /* division by 0 */ - - pv = (u1 *)_mc->gregs[REG_PV] - N_PV_OFFSET; - sp = (u1 *)_mc->gregs[REG_SP]; - ra = xpc; - - type = TRAP_ArithmeticException; - val = 0; - - /* Handle the trap. */ - - p = trap_handle(type, val, pv, sp, ra, xpc, _p); - - _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p; - _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc; - _mc->psw.addr = (uintptr_t) 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); + // Handle the trap. + trap_handle(TRAP_SIGFPE, xpc, _p); } @@ -396,7 +235,29 @@ void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p) */ void md_executionstate_read(executionstate_t* es, void* context) { - vm_abort("md_executionstate_read: IMPLEMENT ME!"); + ucontext_t *_uc; + mcontext_t *_mc; + int i; + + _uc = (ucontext_t *) context; + _mc = &_uc->uc_mcontext; + + /* read special registers */ + es->pc = (u1 *) _mc->psw.addr; + es->sp = (u1 *) _mc->gregs[REG_SP]; + es->pv = (u1 *) _mc->gregs[REG_PV] - N_PV_OFFSET; + es->ra = (u1 *) _mc->gregs[REG_RA]; + + /* read integer registers */ + for (i = 0; i < INT_REG_CNT; i++) + es->intregs[i] = _mc->gregs[i]; + + /* read float registers */ + /* Do not use the assignment operator '=', as the type of + * the _mc->sc_fpregs[i] can cause invalid conversions. */ + + assert(sizeof(_mc->fpregs.fprs) == sizeof(es->fltregs)); + os_memcpy(&es->fltregs, &_mc->fpregs.fprs, sizeof(_mc->fpregs.fprs)); } @@ -408,7 +269,29 @@ void md_executionstate_read(executionstate_t* es, void* context) */ void md_executionstate_write(executionstate_t* es, void* context) { - vm_abort("md_executionstate_write: IMPLEMENT ME!"); + ucontext_t *_uc; + mcontext_t *_mc; + int i; + + _uc = (ucontext_t *) context; + _mc = &_uc->uc_mcontext; + + /* write integer registers */ + for (i = 0; i < INT_REG_CNT; i++) + _mc->gregs[i] = es->intregs[i]; + + /* write float registers */ + /* Do not use the assignment operator '=', as the type of + * the _mc->sc_fpregs[i] can cause invalid conversions. */ + + assert(sizeof(_mc->fpregs.fprs) == sizeof(es->fltregs)); + os_memcpy(&_mc->fpregs.fprs, &es->fltregs, sizeof(_mc->fpregs.fprs)); + + /* write special registers */ + _mc->psw.addr = (ptrint) es->pc; + _mc->gregs[REG_SP] = (ptrint) es->sp; + _mc->gregs[REG_PV] = (ptrint) es->pv + N_PV_OFFSET; + _mc->gregs[REG_RA] = (ptrint) es->ra; } @@ -509,6 +392,80 @@ void *md_jit_method_patch_address(void* pv, void *ra, void *mptr) } +/** + * Decode the trap instruction at the given PC. + * + * @param trp information about trap to be filled + * @param sig signal number + * @param xpc exception PC + * @param es execution state of the machine + * @return true if trap was decoded successfully, false otherwise. + */ +bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es) +{ + switch (sig) { + case TRAP_SIGILL: + if (N_RR_GET_OPC(xpc) == OPC_ILL) { + int32_t reg = N_ILL_GET_REG(xpc); + trp->type = N_ILL_GET_TYPE(xpc); + trp->value = es->intregs[reg]; + return true; + } + return false; + + case TRAP_SIGSEGV: + { + int is_null; + int32_t base; + switch (N_RX_GET_OPC(xpc)) { + case OPC_L: + case OPC_ST: + case OPC_CL: /* array size check on NULL array */ + base = N_RX_GET_BASE(xpc); + if (base == 0) { + is_null = 1; + } else if (es->intregs[base] == 0) { + is_null = 1; + } else { + is_null = 0; + } + break; + default: + is_null = 0; + break; + } + + // Check for implicit NullPointerException. + if (is_null) { + trp->type = TRAP_NullPointerException; + trp->value = 0; + return true; + } + + return false; + } + + case TRAP_SIGFPE: + { + if (N_RR_GET_OPC(xpc) == OPC_DR) { + int r2 = N_RR_GET_REG2(xpc); + if (es->intregs[r2] == 0) { + trp->type = TRAP_ArithmeticException; + trp->value = 0; + return true; + } + } + + return false; + } + + default: + return false; + } +} + + + /* md_patch_replacement_point ************************************************** Patch the given replacement point. @@ -539,8 +496,8 @@ void md_handle_exception(int32_t *regs, int64_t *fregs, int32_t *out) { /* get registers */ - xptr = *(uint8_t **)(regs + REG_ITMP3_XPTR); - xpc = *(uint8_t **)(regs + REG_ITMP1_XPC); + xptr = *(uint8_t **)(regs + REG_ITMP1_XPTR); + xpc = *(uint8_t **)(regs + REG_ITMP2_XPC); sp = *(uint8_t **)(regs + REG_SP); @@ -615,8 +572,8 @@ void md_handle_exception(int32_t *regs, int64_t *fregs, int32_t *out) { /* write new values for registers */ - *(uint8_t **)(regs + REG_ITMP3_XPTR) = xptr; - *(uint8_t **)(regs + REG_ITMP1_XPC) = xpc; + *(uint8_t **)(regs + REG_ITMP1_XPTR) = xptr; + *(uint8_t **)(regs + REG_ITMP2_XPC) = xpc; *(uint8_t **)(regs + REG_SP) = sp; *(uint8_t **)(regs + REG_PV) = pv - 0XFFC; diff --git a/src/vm/jit/trap.cpp b/src/vm/jit/trap.cpp index e15a77a18..d3781e33f 100644 --- a/src/vm/jit/trap.cpp +++ b/src/vm/jit/trap.cpp @@ -1,6 +1,6 @@ /* src/vm/jit/trap.cpp - hardware traps - Copyright (C) 2008, 2009 + Copyright (C) 2008, 2009, 2010 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2009 Theobroma Systems Ltd. @@ -55,6 +55,12 @@ #include "vm/jit/stacktrace.hpp" #include "vm/jit/trap.hpp" +#if defined(__S390__) +#include "vm/jit/s390/codegen.h" +#else +#define N_PV_OFFSET 0 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -109,7 +115,7 @@ void trap_handle(int sig, void *xpc, void *context) vm_abort("trap_handle: The program counter is NULL!"); #endif -#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) # if !defined(NDEBUG) /* Perform a sanity check on our execution state functions. */ @@ -297,7 +303,7 @@ void trap_handle(int sig, void *xpc, void *context) stacktrace_stackframeinfo_remove(&sfi); -#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) /* Update execution state and set registers. */ /* AFTER: removing stackframeinfo */ @@ -308,7 +314,9 @@ void trap_handle(int sig, void *xpc, void *context) if (entry != NULL) { es.pc = (uint8_t *) (uintptr_t) entry; - es.pv = (uint8_t *) (uintptr_t) entry; + // The s390 executionstate offsets pv, so we need to + // compensate here. + es.pv = (uint8_t *) (uintptr_t) entry - N_PV_OFFSET; break; } @@ -324,7 +332,7 @@ void trap_handle(int sig, void *xpc, void *context) // Get and set the PV from the parent Java method. - es.pv = (uint8_t*) md_codegen_get_pv_from_pc(ra); + es.pv = (uint8_t*) md_codegen_get_pv_from_pc(ra) - N_PV_OFFSET; // Now fall-through to default exception handling.