Fix mysterious unremovable file part 2 ?
[cacao.git] / src / vm / jit / arm / linux / md-os.c
1 /* src/vm/jit/arm/linux/md-os.c - machine dependent ARM Linux functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29
30 #include "vm/types.h"
31
32 #include "vm/jit/disass.h"
33
34 #include "vm/jit/arm/md-abi.h"
35
36 #define ucontext broken_glibc_ucontext
37 #define ucontext_t broken_glibc_ucontext_t
38 #include <ucontext.h>
39 #undef ucontext
40 #undef ucontext_t
41
42 typedef struct ucontext {
43    unsigned long     uc_flags;
44    struct ucontext  *uc_link;
45    stack_t           uc_stack;
46    struct sigcontext uc_mcontext;
47    sigset_t          uc_sigmask;
48 } ucontext_t;
49
50 #define scontext_t struct sigcontext
51
52 #include "threads/thread.h"
53
54 #include "vm/exceptions.h"
55 #include "vm/signallocal.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/executionstate.h"
61 #include "vm/jit/stacktrace.h"
62 #include "vm/jit/trap.h"
63
64
65 /* md_signal_handler_sigsegv ***************************************************
66
67    Signal handler for hardware exceptions.
68
69 *******************************************************************************/
70
71 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
72 {
73         ucontext_t     *_uc;
74         scontext_t     *_sc;
75         u1             *pv;
76         u1             *sp;
77         u1             *ra;
78         u1             *xpc;
79         u4              mcode;
80         intptr_t        addr;
81         int             type;
82         intptr_t        val;
83         void           *p;
84
85         _uc = (ucontext_t*) _p;
86         _sc = &_uc->uc_mcontext;
87
88         /* ATTENTION: glibc included messed up kernel headers we needed a
89            workaround for the ucontext structure. */
90
91         pv  = (u1 *) _sc->arm_ip;
92         sp  = (u1 *) _sc->arm_sp;
93         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
94         xpc = (u1 *) _sc->arm_pc;
95
96         /* get exception-throwing instruction */
97
98         if (xpc == NULL)
99                 vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
100
101         mcode = *((s4 *) xpc);
102
103         /* This is a NullPointerException. */
104
105         addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
106         type = addr;
107         val  = 0;
108
109         /* Handle the trap. */
110
111         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
112
113         /* set registers */
114
115         _sc->arm_r10 = (uintptr_t) p;
116         _sc->arm_fp  = (uintptr_t) xpc;
117         _sc->arm_pc  = (uintptr_t) asm_handle_exception;
118 }
119
120
121 /* md_signal_handler_sigill ****************************************************
122
123    Illegal Instruction signal handler for hardware exception checks.
124
125 *******************************************************************************/
126
127 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
128 {
129         ucontext_t     *_uc;
130         scontext_t     *_sc;
131         u1             *pv;
132         u1             *sp;
133         u1             *ra;
134         u1             *xpc;
135         u4              mcode;
136         int             type;
137         intptr_t        val;
138         void           *p;
139
140         _uc = (ucontext_t*) _p;
141         _sc = &_uc->uc_mcontext;
142
143         /* ATTENTION: glibc included messed up kernel headers we needed a
144            workaround for the ucontext structure. */
145
146         pv  = (u1 *) _sc->arm_ip;
147         sp  = (u1 *) _sc->arm_sp;
148         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
149         xpc = (u1 *) _sc->arm_pc;
150
151         /* get exception-throwing instruction */
152
153         mcode = *((u4 *) xpc);
154
155         /* check for undefined instruction we use */
156
157         if ((mcode & 0x0ff000f0) != 0x07f000f0) {
158                 log_println("md_signal_handler_sigill: unknown illegal instruction: inst=%x", mcode);
159 #if defined(ENABLE_DISASSEMBLER)
160                 DISASSINSTR(xpc);
161 #endif
162                 vm_abort("Aborting...");
163         }
164
165         type = (mcode >> 8) & 0x0fff;
166         val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
167
168         /* Handle the trap. */
169
170         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
171
172         /* set registers if we have an exception, continue execution
173            otherwise (this is needed for patchers to work) */
174
175         if (p != NULL) {
176                 _sc->arm_r10 = (uintptr_t) p;
177                 _sc->arm_fp  = (uintptr_t) xpc;
178                 _sc->arm_pc  = (uintptr_t) asm_handle_exception;
179         }
180 }
181
182
183 /* md_signal_handler_sigusr1 ***************************************************
184
185    Signal handler for suspending threads.
186
187 *******************************************************************************/
188
189 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
190 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
191 {
192         ucontext_t *_uc;
193         scontext_t *_sc;
194         u1         *pc;
195         u1         *sp;
196
197         _uc = (ucontext_t *) _p;
198         _sc = &_uc->uc_mcontext;
199
200         /* get the PC and SP for this thread */
201         pc = (u1 *) _sc->arm_pc;
202         sp = (u1 *) _sc->arm_sp;
203
204         /* now suspend the current thread */
205         threads_suspend_ack(pc, sp);
206 }
207 #endif
208
209
210 /* md_signal_handler_sigusr2 ***************************************************
211
212    Signal handler for profiling sampling.
213
214 *******************************************************************************/
215
216 #if defined(ENABLE_THREADS)
217 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
218 {
219         threadobject *thread;
220         ucontext_t   *_uc;
221         scontext_t   *_sc;
222         u1           *pc;
223
224         thread = THREADOBJECT;
225
226         _uc = (ucontext_t*) _p;
227         _sc = &_uc->uc_mcontext;
228
229         pc = (u1 *) _sc->arm_pc;
230
231         thread->pc = pc;
232 }
233 #endif
234
235
236 /**
237  * Read the given context into an executionstate.
238  *
239  * @param es      execution state
240  * @param context machine context
241  */
242 void md_executionstate_read(executionstate_t *es, void *context)
243 {
244         vm_abort("md_executionstate_read: IMPLEMENT ME!");
245
246 #if 0
247         ucontext_t *_uc;
248         mcontext_t *_mc;
249         int         i;
250
251         _uc = (ucontext_t *) context;
252         _mc = &_uc->uc_mcontext;
253
254         /* read special registers */
255         es->pc = (u1 *) _mc->sc_pc;
256         es->sp = (u1 *) _mc->sc_regs[REG_SP];
257         es->pv = (u1 *) _mc->sc_regs[REG_PV];
258         es->ra = (u1 *) _mc->sc_regs[REG_RA];
259
260         /* read integer registers */
261         for (i = 0; i < INT_REG_CNT; i++)
262                 es->intregs[i] = _mc->sc_regs[i];
263
264         /* read float registers */
265         /* Do not use the assignment operator '=', as the type of
266          * the _mc->sc_fpregs[i] can cause invalid conversions. */
267
268         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
269         system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
270 #endif
271 }
272
273
274 /**
275  * Write the given executionstate back to the context.
276  *
277  * @param es      execution state
278  * @param context machine context
279  */
280 void md_executionstate_write(executionstate_t *es, void *context)
281 {
282         vm_abort("md_executionstate_write: IMPLEMENT ME!");
283
284 #if 0
285         ucontext_t *_uc;
286         mcontext_t *_mc;
287         int         i;
288
289         _uc = (ucontext_t *) context;
290         _mc = &_uc->uc_mcontext;
291
292         /* write integer registers */
293         for (i = 0; i < INT_REG_CNT; i++)
294                 _mc->sc_regs[i] = es->intregs[i];
295
296         /* write float registers */
297         /* Do not use the assignment operator '=', as the type of
298          * the _mc->sc_fpregs[i] can cause invalid conversions. */
299
300         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
301         system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
302
303         /* write special registers */
304         _mc->sc_pc           = (ptrint) es->pc;
305         _mc->sc_regs[REG_SP] = (ptrint) es->sp;
306         _mc->sc_regs[REG_PV] = (ptrint) es->pv;
307         _mc->sc_regs[REG_RA] = (ptrint) es->ra;
308 #endif
309 }
310
311
312 /* md_critical_section_restart *************************************************
313
314    Search the critical sections tree for a matching section and set
315    the PC to the restart point, if necessary.
316
317 *******************************************************************************/
318
319 #if defined(ENABLE_THREADS)
320 void md_critical_section_restart(ucontext_t *_uc)
321 {
322         scontext_t *_sc;
323         u1         *pc;
324         u1         *npc;
325
326         _sc = &_uc->uc_mcontext;
327
328         pc = (u1 *) _sc->arm_pc;
329
330         npc = critical_find_restart_point(pc);
331
332         if (npc != NULL)
333                 _sc->arm_pc = (ptrint) npc;
334 }
335 #endif
336
337
338 /*
339  * These are local overrides for various environment variables in Emacs.
340  * Please do not remove this and leave it at the end of the file, where
341  * Emacs will automagically detect them.
342  * ---------------------------------------------------------------------
343  * Local variables:
344  * mode: c
345  * indent-tabs-mode: t
346  * c-basic-offset: 4
347  * tab-width: 4
348  * End:
349  */
350