2 * This software is part of the SBCL system. See the README file for
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
21 #include "interrupt.h"
23 #include "breakpoint.h"
25 #if defined(LISP_FEATURE_GENCGC)
26 #include "gencgc-alloc-region.h"
29 /* The header files may not define PT_DAR/PT_DSISR. This definition
30 is correct for all versions of ppc linux >= 2.0.30
32 As of DR2.1u4, MkLinux doesn't pass these registers to signal
33 handlers correctly; a patch is necessary in order to (partially)
36 Even with the patch, the DSISR may not have its 'write' bit set
37 correctly (it tends not to be set if the fault was caused by
38 something other than a protection violation.)
42 #if defined (LISP_FEATURE_DARWIN) || defined(LISP_FEATURE_LINUX)
56 arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context)
60 #if defined(LISP_FEATURE_NETBSD)
61 addr = (os_vm_address_t) (code->si_addr);
63 addr = (os_vm_address_t) (*os_context_register_addr(context,PT_DAR));
70 arch_skip_instruction(os_context_t *context)
73 pcptr = (char**) os_context_pc_addr(context);
78 arch_internal_error_arguments(os_context_t *context)
80 return (unsigned char *)(*os_context_pc_addr(context)+4);
85 arch_pseudo_atomic_atomic(os_context_t *context)
87 /* FIXME: this foreign_function_call_active test is dubious at
88 * best. If a foreign call is made in a pseudo atomic section
89 * (?) or more likely a pseudo atomic section is in a foreign
90 * call then an interrupt is executed immediately. Maybe it
91 * has to do with C code not maintaining pseudo atomic
92 * properly. MG - 2005-08-10
94 * The foreign_function_call_active used to live at each call-site
95 * to arch_pseudo_atomic_atomic, but this seems clearer.
97 return (!foreign_function_call_active)
98 && ((*os_context_register_addr(context,reg_ALLOC)) & 4);
102 arch_set_pseudo_atomic_interrupted(os_context_t *context)
104 *os_context_register_addr(context,reg_ALLOC) |= 1;
108 arch_clear_pseudo_atomic_interrupted(os_context_t *context)
110 *os_context_register_addr(context,reg_ALLOC) &= ~1;
114 arch_install_breakpoint(void *pc)
116 unsigned int *ptr = (unsigned int *)pc;
117 unsigned int result = *ptr;
118 *ptr = (3<<26) | (5 << 21) | trap_Breakpoint;
119 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int));
124 arch_remove_breakpoint(void *pc, unsigned int orig_inst)
126 *(unsigned int *)pc = orig_inst;
127 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int));
131 * Perform the instruction that we overwrote with a breakpoint. As we
132 * don't have a single-step facility, this means we have to:
133 * - put the instruction back
134 * - put a second breakpoint at the following instruction,
135 * set after_breakpoint and continue execution.
137 * When the second breakpoint is hit (very shortly thereafter, we hope)
138 * sigtrap_handler gets called again, but follows the AfterBreakpoint
140 * - puts a bpt back in the first breakpoint place (running across a
141 * breakpoint shouldn't cause it to be uninstalled)
142 * - replaces the second bpt with the instruction it was meant to be
147 static unsigned int *skipped_break_addr, displaced_after_inst;
148 static sigset_t orig_sigmask;
151 arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
153 /* not sure how we ensure that we get the breakpoint reinstalled
154 * after doing this -dan */
155 unsigned int *pc = (unsigned int *)(*os_context_pc_addr(context));
157 orig_sigmask = *os_context_sigmask_addr(context);
158 sigaddset_blockable(os_context_sigmask_addr(context));
161 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int));
162 skipped_break_addr = pc;
164 /* FIXME: we should apparently be installing the after-breakpoint
165 * here, but would need to find the next instruction address for
166 * it first. alpha-arch.c shows how to do it. --NS 2007-04-02 */
169 #ifdef LISP_FEATURE_GENCGC
171 * Return non-zero if the current instruction is an allocation trap
174 allocation_trap_p(os_context_t * context)
186 * First, the instruction has to be a TWLGE temp, NL3, which has the
188 * | 6| 5| 5 | 5 | 10|1| width
189 * |31|5 |dst|src| 4|0| field
191 pc = (unsigned int *) (*os_context_pc_addr(context));
195 fprintf(stderr, "allocation_trap_p at %p: inst = 0x%08x\n", pc, inst);
199 src = (inst >> 11) & 0x1f;
200 dst = (inst >> 16) & 0x1f;
201 if ((opcode == 31) && (src == reg_NL3) && (5 == ((inst >> 21) & 0x1f))
202 && (4 == ((inst >> 1) & 0x3ff))) {
204 * We got the instruction. Now, look back to make sure it was
205 * proceeded by what we expected. 2 instructions back should be
206 * an ADD or ADDI instruction.
208 unsigned int add_inst;
212 fprintf(stderr, " add inst at %p: inst = 0x%08x\n",
215 opcode = add_inst >> 26;
216 if ((opcode == 31) && (266 == ((add_inst >> 1) & 0x1ff))) {
218 } else if ((opcode == 14)) {
222 "Whoa! Got allocation trap but could not find ADD or ADDI instruction: 0x%08x in the proper place\n",
229 extern struct alloc_region boxed_region;
232 handle_allocation_trap(os_context_t * context)
236 unsigned int target, target_ptr, end_addr;
239 boolean were_in_lisp;
246 fprintf(stderr, "In handle_allocation_trap\n");
249 /* I don't think it's possible for us NOT to be in lisp when we get
250 * here. Remove this later? */
251 were_in_lisp = !foreign_function_call_active;
254 fake_foreign_function_call(context);
256 fprintf(stderr, "**** Whoa! allocation trap and we weren't in lisp!\n");
260 * Look at current instruction: TWNE temp, NL3. We're here because
261 * temp > NL3 and temp is the end of the allocation, and NL3 is
262 * current-region-end-addr.
264 * We need to adjust temp and alloc-tn.
267 pc = (unsigned int *) (*os_context_pc_addr(context));
269 end_addr = (inst >> 11) & 0x1f;
270 target = (inst >> 16) & 0x1f;
272 target_ptr = *os_context_register_addr(context, target);
275 fprintf(stderr, "handle_allocation_trap at %p:\n", pc);
276 fprintf(stderr, "boxed_region.free_pointer: %p\n", boxed_region.free_pointer);
277 fprintf(stderr, "boxed_region.end_addr: %p\n", boxed_region.end_addr);
278 fprintf(stderr, "target reg: %d, end_addr reg: %d\n", target, end_addr);
279 fprintf(stderr, "target: %x\n", *os_context_register_addr(context, target));
280 fprintf(stderr, "end_addr: %x\n", *os_context_register_addr(context, end_addr));
284 fprintf(stderr, "handle_allocation_trap at %p:\n", pc);
285 fprintf(stderr, " trap inst = 0x%08x\n", inst);
286 fprintf(stderr, " target reg = %s\n", lisp_register_names[target]);
290 * Go back and look at the add/addi instruction. The second src arg
291 * is the size of the allocation. Get it and call alloc to allocate
297 fprintf(stderr, " add inst = 0x%08x, opcode = %d\n", inst, opcode);
301 * ADDI temp-tn, alloc-tn, size
305 size = (inst & 0xffff);
306 } else if (opcode == 31) {
308 * ADD temp-tn, alloc-tn, size-tn
314 reg = (inst >> 11) & 0x1f;
316 fprintf(stderr, " add, reg = %s\n", lisp_register_names[reg]);
318 size = *os_context_register_addr(context, reg);
323 fprintf(stderr, "Alloc %d to %s\n", size, lisp_register_names[target]);
326 #if INLINE_ALLOC_DEBUG
327 if ((((unsigned long)boxed_region.end_addr + size) / PAGE_SIZE) ==
328 (((unsigned long)boxed_region.end_addr) / PAGE_SIZE)) {
329 fprintf(stderr,"*** possibly bogus trap allocation of %d bytes at %p\n",
331 fprintf(stderr, " dynamic_space_free_pointer: %p, boxed_region.end_addr %p\n",
332 dynamic_space_free_pointer, boxed_region.end_addr);
337 fprintf(stderr, "Ready to alloc\n");
338 fprintf(stderr, "free_pointer = 0x%08x\n",
339 dynamic_space_free_pointer);
343 * alloc-tn was incremented by size. Need to decrement it by size
344 * to restore its original value. This is not true on GENCGC
345 * anymore. d_s_f_p and reg_alloc get out of sync, but the p_a
346 * bits stay intact and we set it to the proper value when it
347 * needs to be. Keep this comment here for the moment in case
348 * somebody tries to figure out what happened here.
350 /* dynamic_space_free_pointer =
351 (lispobj *) ((long) dynamic_space_free_pointer - size);
354 fprintf(stderr, "free_pointer = 0x%08x new\n",
355 dynamic_space_free_pointer);
358 memory = (char *) alloc(size);
361 fprintf(stderr, "alloc returned %p\n", memory);
362 fprintf(stderr, "free_pointer = 0x%08x\n",
363 dynamic_space_free_pointer);
367 * The allocation macro wants the result to point to the end of the
373 fprintf(stderr, "object end at %p\n", memory);
376 *os_context_register_addr(context, target) = (unsigned long) memory;
377 *os_context_register_addr(context, reg_ALLOC) =
378 (unsigned long) dynamic_space_free_pointer
379 | (*os_context_register_addr(context, reg_ALLOC)
383 undo_fake_foreign_function_call(context);
391 arch_handle_breakpoint(os_context_t *context)
393 handle_breakpoint(context);
397 arch_handle_fun_end_breakpoint(os_context_t *context)
399 *os_context_pc_addr(context)
400 =(int)handle_fun_end_breakpoint(context);
404 arch_handle_after_breakpoint(os_context_t *context)
406 *skipped_break_addr = trap_Breakpoint;
407 skipped_break_addr = NULL;
408 *(unsigned int *)*os_context_pc_addr(context)
409 = displaced_after_inst;
410 *os_context_sigmask_addr(context)= orig_sigmask;
411 os_flush_icache((os_vm_address_t) *os_context_pc_addr(context),
412 sizeof(unsigned int));
416 arch_handle_single_step_trap(os_context_t *context, int trap)
418 unsigned int code = *((u32 *)(*os_context_pc_addr(context)));
419 int register_offset = code >> 5 & 0x1f;
420 handle_single_step_trap(context, trap, register_offset);
421 arch_skip_instruction(context);
425 sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
429 #ifdef LISP_FEATURE_LINUX
430 os_restore_fp_control(context);
432 code=*((u32 *)(*os_context_pc_addr(context)));
433 if (code == ((3 << 26) | (0x18 << 21) | (reg_NL3 << 16))) {
434 arch_clear_pseudo_atomic_interrupted(context);
435 arch_skip_instruction(context);
436 /* interrupt or GC was requested in PA; now we're done with the
437 PA section we may as well get around to it */
438 interrupt_handle_pending(context);
442 #ifdef LISP_FEATURE_GENCGC
443 /* Is this an allocation trap? */
444 if (allocation_trap_p(context)) {
445 handle_allocation_trap(context);
446 arch_skip_instruction(context);
447 #ifdef LISP_FEATURE_DARWIN
448 DARWIN_FIX_CONTEXT(context);
454 if ((code >> 16) == ((3 << 10) | (6 << 5))) {
455 /* twllei reg_ZERO,N will always trap if reg_ZERO = 0 */
456 int trap = code & 0x1f;
457 handle_trap(context,trap);
459 #ifdef LISP_FEATURE_DARWIN
460 DARWIN_FIX_CONTEXT(context);
464 if (((code >> 26) == 3) && (((code >> 21) & 31) == 24)) {
465 interrupt_internal_error(context, 0);
466 #ifdef LISP_FEATURE_DARWIN
467 DARWIN_FIX_CONTEXT(context);
472 interrupt_handle_now(signal, code, context);
473 #ifdef LISP_FEATURE_DARWIN
474 /* Work around G5 bug */
475 DARWIN_FIX_CONTEXT(context);
480 void arch_install_interrupt_handlers()
482 undoably_install_low_level_interrupt_handler(SIGILL,sigtrap_handler);
483 undoably_install_low_level_interrupt_handler(SIGTRAP,sigtrap_handler);
487 ppc_flush_icache(os_vm_address_t address, os_vm_size_t length)
489 os_vm_address_t end = (os_vm_address_t) ((int)(address+length+(32-1)) &~(32-1));
490 extern void ppc_flush_cache_line(os_vm_address_t);
492 while (address < end) {
493 ppc_flush_cache_line(address);
498 #ifdef LISP_FEATURE_LINKAGE_TABLE
500 /* Linkage tables for PowerPC
502 * Linkage entry size is 16, because we need at least 4 instructions to
507 * Define the registers to use in the linkage jump table. Can be the
508 * same. Some care must be exercised when choosing these. It has to be
509 * a register that is not otherwise being used. reg_NFP is a good
510 * choice. call_into_c trashes reg_NFP without preserving it, so we can
511 * trash it in the linkage jump table.
513 #define LINKAGE_TEMP_REG reg_NFP
514 #define LINKAGE_ADDR_REG reg_NFP
517 * Insert the necessary jump instructions at the given address.
520 arch_write_linkage_table_jmp(void* reloc_addr, void *target_addr)
523 * Make JMP to function entry.
525 * The instruction sequence is:
527 * addis 13, 0, (hi part of addr)
528 * ori 13, 13, (low part of addr)
534 unsigned long hi; /* Top 16 bits of address */
535 unsigned long lo; /* Low 16 bits of address */
538 inst_ptr = (int*) reloc_addr;
541 * Split the target address into hi and lo parts for the sethi
542 * instruction. hi is the top 22 bits. lo is the low 10 bits.
544 hi = (unsigned long) target_addr;
549 * addis 13, 0, (hi part)
552 inst = (15 << 26) | (LINKAGE_TEMP_REG << 21) | (0 << 16) | hi;
556 * ori 13, 13, (lo part)
559 inst = (24 << 26) | (LINKAGE_TEMP_REG << 21) | (LINKAGE_TEMP_REG << 16) | lo;
566 inst = (31 << 26) | (LINKAGE_TEMP_REG << 21) | (9 << 16) | (467 << 1);
573 inst = (19 << 26) | (20 << 21) | (528 << 1);
579 os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - (char*) reloc_addr);
583 arch_write_linkage_table_ref(void * reloc_addr, void *target_addr)
585 *(unsigned long *)reloc_addr = (unsigned long)target_addr;