-/* src/vm/jit/arm/linux/md.c - machine dependent arm linux functions
+/* src/vm/jit/arm/linux/md-os.c - machine dependent arm linux functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Michael Starzinger
-
- Changes: Christian Thalinger
-
- $Id: md.c 166 2006-01-22 23:38:44Z twisti $
-
*/
#include "config.h"
+#include <assert.h>
+#include <stdint.h>
+
#include "vm/types.h"
#include "vm/jit/arm/md-abi.h"
#define scontext_t struct sigcontext
-#include "mm/memory.h"
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#endif
+
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.h"
/* md_signal_handler_sigsegv ***************************************************
- NullPointerException signal handler for hardware null pointer
- check.
+ Signal handler for hardware exceptions.
*******************************************************************************/
void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- /*mcontext_t *_mc;*/
- scontext_t *_sc;
- u4 instr;
- ptrint addr;
- ptrint base;
- u1 *pv;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
+ stackframeinfo sfi;
+ ucontext_t *_uc;
+ scontext_t *_sc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ u4 mcode;
+ intptr_t addr;
+ int type;
+ intptr_t val;
+ void *p;
+
+ _uc = (ucontext_t*) _p;
+ _sc = &_uc->uc_mcontext;
+
+ /* ATTENTION: glibc included messed up kernel headers we needed a
+ workaround for the ucontext structure. */
+
+ pv = (u1 *) _sc->arm_ip;
+ sp = (u1 *) _sc->arm_sp;
+ ra = (u1 *) _sc->arm_lr; /* this is correct for leafs */
+ xpc = (u1 *) _sc->arm_pc;
+
+ /* get exception-throwing instruction */
+
+ if (xpc == NULL)
+ vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
+
+ mcode = *((s4 *) xpc);
+
+ /* this is a NullPointerException */
+
+ addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
+ type = EXCEPTION_HARDWARE_NULLPOINTER;
+ val = 0;
+
+ if (addr != 0)
+ vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
+
+ /* create stackframeinfo */
+
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+
+ /* Handle the type. */
+
+ p = signal_handle(xpc, type, val);
+
+ /* remove stackframeinfo */
+
+ stacktrace_remove_stackframeinfo(&sfi);
+
+ /* set registers */
+
+ _sc->arm_r10 = (intptr_t) p;
+ _sc->arm_fp = (intptr_t) xpc;
+ _sc->arm_pc = (intptr_t) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigill ****************************************************
+
+ Illegal Instruction signal handler for hardware exception checks.
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ stackframeinfo sfi;
+ ucontext_t *_uc;
+ scontext_t *_sc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ u4 mcode;
+ int type;
+ intptr_t val;
+ void *p;
_uc = (ucontext_t*) _p;
_sc = &_uc->uc_mcontext;
- /* ATTENTION: glibc included messed up kernel headers */
- /* we needed a workaround for the ucontext structure */
+ /* ATTENTION: glibc included messed up kernel headers we needed a
+ workaround for the ucontext structure. */
+
+ pv = (u1 *) _sc->arm_ip;
+ sp = (u1 *) _sc->arm_sp;
+ ra = (u1 *) _sc->arm_lr; /* this is correct for leafs */
+ xpc = (u1 *) _sc->arm_pc;
+
+ /* get exception-throwing instruction */
- addr = (ptrint) siginfo->si_addr;
- /*xpc = (u1*) _mc->gregs[REG_PC];*/
- xpc = (u1*) _sc->arm_pc;
+ mcode = *((u4 *) xpc);
- instr = *((s4*) xpc);
- base = *((s4*) _sc + OFFSET(scontext_t, arm_r0)/4 + ((instr >> 16) & 0x0f));
+ /* check for undefined instruction we use */
- if (base == 0) {
- pv = (u1*) _sc->arm_ip;
- sp = (u1*) _sc->arm_sp;
- ra = (u1*) _sc->arm_lr; /* this is correct for leafs */
+ if ((mcode & 0x0ff000f0) != 0x07f000f0)
+ vm_abort("md_signal_handler_sigill: unknown illegal instruction");
- _sc->arm_r10 = (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
- _sc->arm_fp = (ptrint) xpc;
- _sc->arm_pc = (ptrint) asm_handle_exception;
- } else {
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "Segmentation fault: %p (pc=%p, instr=%x, base=%p)\n",
- addr, xpc, instr, base);
+ type = (mcode >> 8) & 0x0fff;
+ val = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
+
+ /* create stackframeinfo */
+
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+
+ /* Handle the type. */
+
+ p = signal_handle(xpc, type, val);
+
+ /* remove stackframeinfo */
+
+ stacktrace_remove_stackframeinfo(&sfi);
+
+ /* set registers if we have an exception, return continue execution
+ otherwise (this is needed for patchers to work) */
+
+ if (p != NULL) {
+ _sc->arm_r10 = (intptr_t) p;
+ _sc->arm_fp = (intptr_t) xpc;
+ _sc->arm_pc = (intptr_t) asm_handle_exception;
}
}
-/* thread_restartcriticalsection ***********************************************
+/* md_signal_handler_sigusr1 ***************************************************
+
+ Signal handler for suspending threads.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ scontext_t *_sc;
+ u1 *pc;
+ u1 *sp;
+
+ _uc = (ucontext_t *) _p;
+ _sc = &_uc->uc_mcontext;
+
+ /* get the PC and SP for this thread */
+ pc = (u1 *) _sc->arm_pc;
+ sp = (u1 *) _sc->arm_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 *thread;
+ ucontext_t *_uc;
+ scontext_t *_sc;
+ u1 *pc;
+
+ thread = THREADOBJECT;
+
+ _uc = (ucontext_t*) _p;
+ _sc = &_uc->uc_mcontext;
+
+ pc = (u1 *) _sc->arm_pc;
+
+ thread->pc = pc;
+}
+#endif
+
+
+/* md_critical_section_restart *************************************************
- TODO: document me
+ Search the critical sections tree for a matching section and set
+ the PC to the restart point, if necessary.
*******************************************************************************/
#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *_uc)
+void md_critical_section_restart(ucontext_t *_uc)
{
scontext_t *_sc;
- void *critical;
+ u1 *pc;
+ u1 *npc;
_sc = &_uc->uc_mcontext;
- critical = critical_find_restart_point((void *) _sc->arm_pc);
+ pc = (u1 *) _sc->arm_pc;
+
+ npc = critical_find_restart_point(pc);
- if (critical)
- _sc->arm_pc = (ptrint) critical;
+ if (npc != NULL)
+ _sc->arm_pc = (ptrint) npc;
}
#endif