X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpowerpc%2Flinux%2Fmd-os.c;h=edfc86d203085a4752ccbbdf3b399a56b9d04795;hb=167cdb4568b39860841183e6886bfc2bb0c28887;hp=0ab4b858e68030d52c7d2adb07e1172cb4d793f7;hpb=d5bcfae0db70fac13bf01b10556bf85a94bdc33f;p=cacao.git diff --git a/src/vm/jit/powerpc/linux/md-os.c b/src/vm/jit/powerpc/linux/md-os.c index 0ab4b858e..edfc86d20 100644 --- a/src/vm/jit/powerpc/linux/md-os.c +++ b/src/vm/jit/powerpc/linux/md-os.c @@ -1,9 +1,8 @@ /* src/vm/jit/powerpc/linux/md-os.c - machine dependent PowerPC Linux functions - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2008 Theobroma Systems Ltd. This file is part of CACAO. @@ -19,73 +18,418 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at +*/ - Authors: Christian Thalinger - Changes: +#include "config.h" - $Id: md-os.c 2997 2005-07-12 08:39:17Z twisti $ +#include +#include +#include -*/ +#include "vm/types.h" +#include "vm/jit/powerpc/codegen.h" +#include "vm/jit/powerpc/md.h" +#include "vm/jit/powerpc/linux/md-abi.h" -#include +#include "threads/thread.hpp" -#include "vm/jit/powerpc/types.h" -#include "vm/jit/powerpc/linux/md-abi.h" +#include "vm/jit/builtin.hpp" +#include "vm/signallocal.h" +#include "vm/os.hpp" -#include "vm/exceptions.h" -#include "vm/stringlocal.h" #include "vm/jit/asmpart.h" -#include "vm/jit/stacktrace.h" +#include "vm/jit/disass.h" +#include "vm/jit/executionstate.h" + +#if defined(ENABLE_PROFILING) +# include "vm/jit/optimizing/profile.h" +#endif + +#include "vm/jit/patcher-common.hpp" +#include "vm/jit/trap.h" + + +/* md_signal_handler_sigsegv *************************************************** + + Signal handler for hardware-exceptions. + +*******************************************************************************/ + +void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) +{ + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + u1 *pv; + u1 *sp; + u1 *ra; + u1 *xpc; + u4 mcode; + int s1; + int16_t disp; + int d; + intptr_t addr; + intptr_t val; + int type; + void *p; + + _uc = (ucontext_t *) _p; + +#if defined(__UCLIBC__) + _mc = &(_uc->uc_mcontext); + _gregs = _mc->regs->gpr; +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + pv = (u1 *) _gregs[REG_PV]; + sp = (u1 *) _gregs[REG_SP]; + ra = (u1 *) _gregs[PT_LNK]; /* this is correct for leafs */ + xpc = (u1 *) _gregs[PT_NIP]; + + /* get exception-throwing instruction */ + + mcode = *((u4 *) xpc); + + s1 = M_INSTR_OP2_IMM_A(mcode); + disp = M_INSTR_OP2_IMM_I(mcode); + d = M_INSTR_OP2_IMM_D(mcode); + + val = _gregs[d]; + + /* check for special-load */ + + if (s1 == REG_ZERO) { + /* we use the exception type as load displacement */ + + type = disp; + + if (type == TRAP_COMPILER) { + /* The XPC is the RA minus 4, because the RA points to the + instruction after the call. */ + + xpc = ra - 4; + } + } + else { + /* This is a normal NPE: addr must be NULL and the NPE-type + define is 0. */ + + addr = _gregs[s1]; + type = addr; + } + + /* Handle the trap. */ + + p = trap_handle(type, val, pv, sp, ra, xpc, _p); + + /* Set registers. */ + + switch (type) { + case TRAP_COMPILER: + if (p != NULL) { + _gregs[REG_PV] = (uintptr_t) p; + _gregs[PT_NIP] = (uintptr_t) p; + break; + } + + /* Get and set the PV from the parent Java method. */ + + pv = md_codegen_get_pv_from_pc(ra); + + _gregs[REG_PV] = (uintptr_t) pv; + + /* Get the exception object. */ + + p = builtin_retrieve_exception(); + + assert(p != NULL); + + /* fall-through */ + + default: + _gregs[REG_ITMP1_XPTR] = (uintptr_t) p; + _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc; + _gregs[PT_NIP] = (uintptr_t) asm_handle_exception; + } +} + + +/** + * Signal handler for patcher calls. + */ +void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p) +{ + ucontext_t* _uc = (ucontext_t*) _p; + mcontext_t* _mc; + unsigned long* _gregs; + +#if defined(__UCLIBC__) + _mc = &(_uc->uc_mcontext); + _gregs = _mc->regs->gpr; +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + /* get register values */ + + void* pv = (void*) _gregs[REG_PV]; + void* sp = (void*) _gregs[REG_SP]; + void* ra = (void*) _gregs[PT_LNK]; // The RA is correct for leag methods. + void* xpc =(void*) _gregs[PT_NIP]; + + // Get the illegal-instruction. + uint32_t mcode = *((uint32_t*) xpc); + + // Check if the trap instruction is valid. + // TODO Move this into patcher_handler. + if (patcher_is_valid_trap_instruction_at(xpc) == false) { + // Check if the PC has been patched during our way to this + // signal handler (see PR85). + if (patcher_is_patched_at(xpc) == true) + return; + + // We have a problem... + log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%lx", mcode, xpc); +#if defined(ENABLE_DISASSEMBLER) + (void) disassinstr(xpc); +#endif + vm_abort("Aborting..."); + } + + // This signal is always a patcher. + int type = TRAP_PATCHER; + intptr_t val = 0; + + // Handle the trap. + void* p = trap_handle(type, val, pv, sp, ra, xpc, _p); + + // Set registers if we have an exception, continue execution + // otherwise. + if (p != NULL) { + _gregs[REG_ITMP1_XPTR] = (uintptr_t) p; + _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc; + _gregs[PT_NIP] = (uintptr_t) asm_handle_exception; + } +} + + +/* md_signal_handler_sigtrap *************************************************** + + Signal handler for hardware-traps. +*******************************************************************************/ + +void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p) +{ + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + u1 *pv; + u1 *sp; + u1 *ra; + u1 *xpc; + u4 mcode; + int s1; + intptr_t val; + int type; + void *p; + + _uc = (ucontext_t *) _p; + +#if defined(__UCLIBC__) + _mc = &(_uc->uc_mcontext); + _gregs = _mc->regs->gpr; +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + pv = (u1 *) _gregs[REG_PV]; + sp = (u1 *) _gregs[REG_SP]; + ra = (u1 *) _gregs[PT_LNK]; /* this is correct for leafs */ + xpc = (u1 *) _gregs[PT_NIP]; + + /* get exception-throwing instruction */ + + mcode = *((u4 *) xpc); + + s1 = M_OP3_GET_A(mcode); + + /* For now we only handle ArrayIndexOutOfBoundsException. */ + + type = TRAP_ArrayIndexOutOfBoundsException; + val = _gregs[s1]; + + /* Handle the trap. */ + + p = trap_handle(type, val, pv, sp, ra, xpc, _p); + + /* Set registers. */ + + _gregs[REG_ITMP1_XPTR] = (uintptr_t) p; + _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc; + _gregs[PT_NIP] = (uintptr_t) asm_handle_exception; +} -/* signal_handle_sigsegv ******************************************************* - NullPointerException signal handler for hardware null pointer check. +/* md_signal_handler_sigusr1 *************************************************** + + Signal handler for suspending threads. *******************************************************************************/ -void signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) +#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) +void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u4 instr; - s4 reg; - ptrint addr; - u1 *pv; - u1 *sp; - functionptr ra; - functionptr xpc; + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + u1 *pc; + u1 *sp; + + _uc = (ucontext_t *) _p; + +#if defined(__UCLIBC__) + _mc = &(_uc->uc_mcontext); + _gregs = _mc->regs->gpr; +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + /* get the PC and SP for this thread */ + + pc = (u1 *) _gregs[PT_NIP]; + sp = (u1 *) _gregs[REG_SP]; + + /* now suspend the current thread */ + + threads_suspend_ack(pc, sp); +} +#endif + + +/* md_signal_handler_sigusr2 *************************************************** + + Signal handler for profiling sampling. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p) +{ + threadobject *tobj; + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + u1 *pc; + + tobj = THREADOBJECT; _uc = (ucontext_t *) _p; - _mc = _uc->uc_mcontext.uc_regs; - instr = *((u4 *) _mc->gregs[PT_NIP]); - reg = (instr >> 16) & 0x1f; - addr = _mc->gregs[reg]; +#if defined(__UCLIBC__) + _mc = &(_uc->uc_mcontext); + _gregs = _mc->regs->gpr; +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + pc = (u1 *) _gregs[PT_NIP]; + + tobj->pc = pc; +} +#endif + + +/* md_executionstate_read ****************************************************** + + Read the given context into an executionstate. + +*******************************************************************************/ + +void md_executionstate_read(executionstate_t *es, void *context) +{ + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + s4 i; + + _uc = (ucontext_t *) context; + +#if defined(__UCLIBC__) +#error Please port md_executionstate_read to __UCLIBC__ +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif + + /* read special registers */ + es->pc = (u1 *) _gregs[PT_NIP]; + es->sp = (u1 *) _gregs[REG_SP]; + es->pv = (u1 *) _gregs[REG_PV]; + es->ra = (u1 *) _gregs[PT_LNK]; + + /* read integer registers */ + for (i = 0; i < INT_REG_CNT; i++) + es->intregs[i] = _gregs[i]; + + /* read float registers */ + /* Do not use the assignment operator '=', as the type of + * the _mc->fpregs[i] can cause invalid conversions. */ + + assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs)); + os_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs)); +} + + +/* md_executionstate_write ***************************************************** + + Write the given executionstate back to the context. + +*******************************************************************************/ + +void md_executionstate_write(executionstate_t *es, void *context) +{ + ucontext_t *_uc; + mcontext_t *_mc; + unsigned long *_gregs; + s4 i; + + _uc = (ucontext_t *) context; + +#if defined(__UCLIBC__) +#error Please port md_executionstate_write to __UCLIBC__ +#else + _mc = _uc->uc_mcontext.uc_regs; + _gregs = _mc->gregs; +#endif - if (addr == 0) { - pv = (u1 *) _mc->gregs[REG_PV]; - sp = (u1 *) _mc->gregs[REG_SP]; - ra = (functionptr) _mc->gregs[PT_LNK]; /* this is correct for leafs */ - xpc = (functionptr) _mc->gregs[PT_NIP]; + /* write integer registers */ + for (i = 0; i < INT_REG_CNT; i++) + _gregs[i] = es->intregs[i]; - _mc->gregs[REG_ITMP1_XPTR] = - (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc); + /* write float registers */ + /* Do not use the assignment operator '=', as the type of + * the _mc->fpregs[i] can cause invalid conversions. */ - _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc; - _mc->gregs[PT_NIP] = (ptrint) asm_handle_exception; + assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs)); + os_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs)); - } else { - throw_cacao_exception_exit(string_java_lang_InternalError, - "Segmentation fault: 0x%08lx at 0x%08lx", - addr, _mc->gregs[PT_NIP]); - } + /* write special registers */ + _gregs[PT_NIP] = (ptrint) es->pc; + _gregs[REG_SP] = (ptrint) es->sp; + _gregs[REG_PV] = (ptrint) es->pv; + _gregs[PT_LNK] = (ptrint) es->ra; }