* Merged with default branch at rev 16f3633aaa5a.
[cacao.git] / src / vm / jit / arm / linux / md-os.c
index 1b7ef06f230b299b4c99e0c2c2f7d9995a39ba73..da889e87379581d30ac90c908a4a40b5f8e98eea 100644 (file)
@@ -1,6 +1,6 @@
-/* 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"
@@ -55,81 +50,227 @@ typedef struct ucontext {
 
 #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