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.
19 #include "interrupt.h"
22 #include "interrupt.h"
24 #include "breakpoint.h"
27 #if defined(LISP_FEATURE_GENCGC)
28 #include "gencgc-alloc-region.h"
31 #ifdef LISP_FEATURE_SB_THREAD
32 #include "pseudo-atomic.h"
35 /* The header files may not define PT_DAR/PT_DSISR. This definition
36 is correct for all versions of ppc linux >= 2.0.30
38 As of DR2.1u4, MkLinux doesn't pass these registers to signal
39 handlers correctly; a patch is necessary in order to (partially)
42 Even with the patch, the DSISR may not have its 'write' bit set
43 correctly (it tends not to be set if the fault was caused by
44 something other than a protection violation.)
48 #if defined (LISP_FEATURE_DARWIN) || defined(LISP_FEATURE_LINUX)
58 /* Magic encoding for the instruction used for traps. */
59 #define TRAP_INSTRUCTION(trap) ((3<<26) | (6 << 21) | (trap))
65 arch_get_bad_addr(int sig
, siginfo_t
*code
, os_context_t
*context
)
69 #if defined(LISP_FEATURE_NETBSD) || defined(LISP_FEATURE_OPENBSD)
70 addr
= (os_vm_address_t
) (code
->si_addr
);
72 addr
= (os_vm_address_t
) (*os_context_register_addr(context
,PT_DAR
));
79 arch_skip_instruction(os_context_t
*context
)
82 pcptr
= (char**) os_context_pc_addr(context
);
87 arch_internal_error_arguments(os_context_t
*context
)
89 return (unsigned char *)(*os_context_pc_addr(context
)+4);
94 arch_pseudo_atomic_atomic(os_context_t
*context
)
96 #ifdef LISP_FEATURE_SB_THREAD
97 struct thread
*thread
= arch_os_get_current_thread();
99 if (foreign_function_call_active_p(thread
)) {
100 return get_pseudo_atomic_atomic(thread
);
103 /* FIXME: this foreign_function_call_active test is dubious at
104 * best. If a foreign call is made in a pseudo atomic section
105 * (?) or more likely a pseudo atomic section is in a foreign
106 * call then an interrupt is executed immediately. Maybe it
107 * has to do with C code not maintaining pseudo atomic
108 * properly. MG - 2005-08-10
110 * The foreign_function_call_active used to live at each call-site
111 * to arch_pseudo_atomic_atomic, but this seems clearer.
113 return (!foreign_function_call_active_p(arch_os_get_current_thread())) &&
115 ((*os_context_register_addr(context
,reg_ALLOC
)) & flag_PseudoAtomic
);
119 arch_set_pseudo_atomic_interrupted(os_context_t
*context
)
121 #ifdef LISP_FEATURE_SB_THREAD
122 struct thread
*thread
= arch_os_get_current_thread();
124 if (foreign_function_call_active_p(thread
)) {
125 set_pseudo_atomic_interrupted(thread
);
128 *os_context_register_addr(context
,reg_ALLOC
)
129 |= flag_PseudoAtomicInterrupted
;
133 arch_clear_pseudo_atomic_interrupted(os_context_t
*context
)
135 #ifdef LISP_FEATURE_SB_THREAD
136 struct thread
*thread
= arch_os_get_current_thread();
138 if (foreign_function_call_active_p(thread
)) {
139 clear_pseudo_atomic_interrupted(thread
);
142 *os_context_register_addr(context
,reg_ALLOC
)
143 &= ~flag_PseudoAtomicInterrupted
;
147 arch_install_breakpoint(void *pc
)
149 unsigned int *ptr
= (unsigned int *)pc
;
150 unsigned int result
= *ptr
;
151 *ptr
= TRAP_INSTRUCTION(trap_Breakpoint
);
152 os_flush_icache((os_vm_address_t
) pc
, sizeof(unsigned int));
157 arch_remove_breakpoint(void *pc
, unsigned int orig_inst
)
159 *(unsigned int *)pc
= orig_inst
;
160 os_flush_icache((os_vm_address_t
) pc
, sizeof(unsigned int));
164 * Perform the instruction that we overwrote with a breakpoint. As we
165 * don't have a single-step facility, this means we have to:
166 * - put the instruction back
167 * - put a second breakpoint at the following instruction,
168 * set after_breakpoint and continue execution.
170 * When the second breakpoint is hit (very shortly thereafter, we hope)
171 * sigtrap_handler gets called again, but follows the AfterBreakpoint
173 * - puts a bpt back in the first breakpoint place (running across a
174 * breakpoint shouldn't cause it to be uninstalled)
175 * - replaces the second bpt with the instruction it was meant to be
180 static unsigned int *skipped_break_addr
, displaced_after_inst
;
181 static sigset_t orig_sigmask
;
184 should_branch(os_context_t
*context
, unsigned int orig_inst
)
186 /* orig_inst is a conditional branch instruction. We need to
187 * know if the branch will be taken if executed in context. */
188 int ctr
= *os_context_ctr_addr(context
);
189 int cr
= *os_context_cr_addr(context
);
190 int bo_field
= (orig_inst
>> 21) & 0x1f;
191 int bi_field
= (orig_inst
>> 16) & 0x1f;
194 if (!(bo_field
& 4)) ctr
--; /* Decrement CTR if necessary. */
196 ctr_ok
= (bo_field
& 4) || ((ctr
== 0) == ((bo_field
& 2) == 2));
197 return ctr_ok
&& ((bo_field
& 0x10) ||
198 !(((cr
>> (31-bi_field
)) ^ (bo_field
>> 3)) & 1));
202 arch_do_displaced_inst(os_context_t
*context
, unsigned int orig_inst
)
204 /* not sure how we ensure that we get the breakpoint reinstalled
205 * after doing this -dan */
206 unsigned int *pc
= (unsigned int *)(*os_context_pc_addr(context
));
207 unsigned int *next_pc
;
208 int op
= orig_inst
>> 26;
209 int sub_op
= (orig_inst
& 0x7fe) >> 1; /* XL-form sub-opcode */
211 orig_sigmask
= *os_context_sigmask_addr(context
);
212 sigaddset_blockable(os_context_sigmask_addr(context
));
215 os_flush_icache((os_vm_address_t
) pc
, sizeof(unsigned int));
216 skipped_break_addr
= pc
;
218 /* Figure out where we will end up after running the displaced
219 * instruction by defaulting to the next instruction in the stream
220 * and then checking for branch instructions. FIXME: This will
221 * probably screw up if it attempts to step a trap instruction. */
226 unsigned int displacement
= orig_inst
& 0x03fffffc;
228 if (displacement
& 0x02000000) {
229 displacement
|= 0xc0000000;
231 if (orig_inst
& 2) { /* Absolute Address */
232 next_pc
= (unsigned int *)displacement
;
234 next_pc
= (unsigned int *)(((unsigned int)pc
) + displacement
);
236 } else if ((op
== 16)
237 && should_branch(context
, orig_inst
)) {
238 /* Branch Conditional B-form */
239 unsigned int displacement
= orig_inst
& 0x0000fffc;
241 if (displacement
& 0x00008000) {
242 displacement
|= 0xffff0000;
244 if (orig_inst
& 2) { /* Absolute Address */
245 next_pc
= (unsigned int *)displacement
;
247 next_pc
= (unsigned int *)(((unsigned int)pc
) + displacement
);
249 } else if ((op
== 19) && (sub_op
== 16)
250 && should_branch(context
, orig_inst
)) {
251 /* Branch Conditional to Link Register XL-form */
252 next_pc
= (unsigned int *)
253 ((*os_context_lr_addr(context
)) & ~3);
254 } else if ((op
== 19) && (sub_op
== 528)
255 && should_branch(context
, orig_inst
)) {
256 /* Branch Conditional to Count Register XL-form */
257 next_pc
= (unsigned int *)
258 ((*os_context_ctr_addr(context
)) & ~3);
261 /* Set the "after" breakpoint. */
262 displaced_after_inst
= *next_pc
;
263 *next_pc
= TRAP_INSTRUCTION(trap_AfterBreakpoint
);
264 os_flush_icache((os_vm_address_t
)next_pc
, sizeof(unsigned int));
267 #ifdef LISP_FEATURE_GENCGC
269 * Return non-zero if the current instruction is an allocation trap
272 allocation_trap_p(os_context_t
* context
)
278 unsigned __attribute__((unused
)) dst
;
281 * First, the instruction has to be a TWLGE temp, NL3, which has the
283 * | 6| 5| 5 | 5 | 10|1| width
284 * |31|5 |dst|src| 4|0| field
286 pc
= (unsigned int *) (*os_context_pc_addr(context
));
290 fprintf(stderr
, "allocation_trap_p at %p: inst = 0x%08x\n", pc
, inst
);
294 src
= (inst
>> 11) & 0x1f;
295 dst
= (inst
>> 16) & 0x1f;
296 if ((opcode
== 31) && (src
== reg_NL3
) && (5 == ((inst
>> 21) & 0x1f))
297 && (4 == ((inst
>> 1) & 0x3ff))) {
299 * We got the instruction. Now, look back to make sure it was
300 * proceeded by what we expected. The previous instruction
301 * should be an ADD or ADDI instruction.
303 unsigned int add_inst
;
307 fprintf(stderr
, " add inst at %p: inst = 0x%08x\n",
310 opcode
= add_inst
>> 26;
311 if ((opcode
== 31) && (266 == ((add_inst
>> 1) & 0x1ff))) {
313 } else if ((opcode
== 14)) {
317 "Whoa! Got allocation trap but could not find ADD or ADDI instruction: 0x%08x in the proper place\n",
324 extern struct alloc_region boxed_region
;
327 handle_allocation_trap(os_context_t
* context
)
332 unsigned int __attribute__((unused
)) target_ptr
, end_addr
;
335 boolean were_in_lisp
;
342 fprintf(stderr
, "In handle_allocation_trap\n");
345 /* I don't think it's possible for us NOT to be in lisp when we get
346 * here. Remove this later? */
347 were_in_lisp
= !foreign_function_call_active_p(arch_os_get_current_thread());
350 fake_foreign_function_call(context
);
352 fprintf(stderr
, "**** Whoa! allocation trap and we weren't in lisp!\n");
356 * Look at current instruction: TWNE temp, NL3. We're here because
357 * temp > NL3 and temp is the end of the allocation, and NL3 is
358 * current-region-end-addr.
360 * We need to adjust temp and alloc-tn.
363 pc
= (unsigned int *) (*os_context_pc_addr(context
));
365 end_addr
= (inst
>> 11) & 0x1f;
366 target
= (inst
>> 16) & 0x1f;
368 target_ptr
= *os_context_register_addr(context
, target
);
371 fprintf(stderr
, "handle_allocation_trap at %p:\n", pc
);
372 fprintf(stderr
, "boxed_region.free_pointer: %p\n", boxed_region
.free_pointer
);
373 fprintf(stderr
, "boxed_region.end_addr: %p\n", boxed_region
.end_addr
);
374 fprintf(stderr
, "target reg: %d, end_addr reg: %d\n", target
, end_addr
);
375 fprintf(stderr
, "target: %x\n", *os_context_register_addr(context
, target
));
376 fprintf(stderr
, "end_addr: %x\n", *os_context_register_addr(context
, end_addr
));
380 fprintf(stderr
, "handle_allocation_trap at %p:\n", pc
);
381 fprintf(stderr
, " trap inst = 0x%08x\n", inst
);
382 fprintf(stderr
, " target reg = %s\n", lisp_register_names
[target
]);
386 * Go back and look at the add/addi instruction. The second src arg
387 * is the size of the allocation. Get it and call alloc to allocate
393 fprintf(stderr
, " add inst = 0x%08x, opcode = %d\n", inst
, opcode
);
397 * ADDI temp-tn, alloc-tn, size
401 size
= (inst
& 0xffff);
402 } else if (opcode
== 31) {
404 * ADD temp-tn, alloc-tn, size-tn
410 reg
= (inst
>> 11) & 0x1f;
412 fprintf(stderr
, " add, reg = %s\n", lisp_register_names
[reg
]);
414 size
= *os_context_register_addr(context
, reg
);
419 fprintf(stderr
, "Alloc %d to %s\n", size
, lisp_register_names
[target
]);
422 #if INLINE_ALLOC_DEBUG
423 if ((((unsigned long)boxed_region
.end_addr
+ size
) / PAGE_SIZE
) ==
424 (((unsigned long)boxed_region
.end_addr
) / PAGE_SIZE
)) {
425 fprintf(stderr
,"*** possibly bogus trap allocation of %d bytes at %p\n",
427 fprintf(stderr
, " dynamic_space_free_pointer: %p, boxed_region.end_addr %p\n",
428 dynamic_space_free_pointer
, boxed_region
.end_addr
);
433 fprintf(stderr
, "Ready to alloc\n");
434 fprintf(stderr
, "free_pointer = 0x%08x\n",
435 dynamic_space_free_pointer
);
439 * alloc-tn was incremented by size. Need to decrement it by size
440 * to restore its original value. This is not true on GENCGC
441 * anymore. d_s_f_p and reg_alloc get out of sync, but the p_a
442 * bits stay intact and we set it to the proper value when it
443 * needs to be. Keep this comment here for the moment in case
444 * somebody tries to figure out what happened here.
446 /* dynamic_space_free_pointer =
447 (lispobj *) ((long) dynamic_space_free_pointer - size);
450 fprintf(stderr
, "free_pointer = 0x%08x new\n",
451 dynamic_space_free_pointer
);
455 struct interrupt_data
*data
=
456 arch_os_get_current_thread()->interrupt_data
;
457 data
->allocation_trap_context
= context
;
458 memory
= (char *) alloc(size
);
459 data
->allocation_trap_context
= 0;
463 fprintf(stderr
, "alloc returned %p\n", memory
);
464 fprintf(stderr
, "free_pointer = 0x%08x\n",
465 dynamic_space_free_pointer
);
469 * The allocation macro wants the result to point to the end of the
475 fprintf(stderr
, "object end at %p\n", memory
);
478 *os_context_register_addr(context
, target
) = (unsigned long) memory
;
479 #ifndef LISP_FEATURE_SB_THREAD
480 /* This is handled by the fake_foreign_function_call machinery on
481 * threaded targets. */
482 *os_context_register_addr(context
, reg_ALLOC
) =
483 (unsigned long) dynamic_space_free_pointer
484 | (*os_context_register_addr(context
, reg_ALLOC
)
489 undo_fake_foreign_function_call(context
);
492 /* Skip the allocation trap and the write of the updated free
493 * pointer back to the allocation region. This is two
494 * instructions when threading is enabled and four instructions
496 #ifdef LISP_FEATURE_SB_THREAD
497 (*os_context_pc_addr(context
)) = (unsigned int)(pc
+ 2);
499 (*os_context_pc_addr(context
)) = (unsigned int)(pc
+ 4);
506 arch_handle_breakpoint(os_context_t
*context
)
508 handle_breakpoint(context
);
512 arch_handle_fun_end_breakpoint(os_context_t
*context
)
514 *os_context_pc_addr(context
)
515 =(int)handle_fun_end_breakpoint(context
);
519 arch_handle_after_breakpoint(os_context_t
*context
)
521 *skipped_break_addr
= TRAP_INSTRUCTION(trap_Breakpoint
);
522 os_flush_icache((os_vm_address_t
) skipped_break_addr
,
523 sizeof(unsigned int));
524 skipped_break_addr
= NULL
;
525 *(unsigned int *)*os_context_pc_addr(context
)
526 = displaced_after_inst
;
527 *os_context_sigmask_addr(context
)= orig_sigmask
;
528 os_flush_icache((os_vm_address_t
) *os_context_pc_addr(context
),
529 sizeof(unsigned int));
533 arch_handle_single_step_trap(os_context_t
*context
, int trap
)
535 unsigned int code
= *((u32
*)(*os_context_pc_addr(context
)));
536 int register_offset
= code
>> 5 & 0x1f;
537 handle_single_step_trap(context
, trap
, register_offset
);
538 arch_skip_instruction(context
);
542 sigtrap_handler(int signal
, siginfo_t
*siginfo
, os_context_t
*context
)
546 code
=*((u32
*)(*os_context_pc_addr(context
)));
547 if (code
== ((3 << 26) | (0x18 << 21) | (reg_NL3
<< 16))||
548 /* trap instruction from do_pending_interrupt */
549 code
== 0x7fe00008) {
550 arch_clear_pseudo_atomic_interrupted(context
);
551 arch_skip_instruction(context
);
552 /* interrupt or GC was requested in PA; now we're done with the
553 PA section we may as well get around to it */
554 interrupt_handle_pending(context
);
558 #ifdef LISP_FEATURE_GENCGC
559 /* Is this an allocation trap? */
560 if (allocation_trap_p(context
)) {
561 handle_allocation_trap(context
);
566 if ((code
>> 16) == ((3 << 10) | (6 << 5))) {
567 /* twllei reg_ZERO,N will always trap if reg_ZERO = 0 */
568 int trap
= code
& 0x1f;
569 handle_trap(context
,trap
);
572 /* twi :ne ... or twi ... nargs */
573 if (((code
>> 26) == 3) && (((code
>> 21) & 31) == 24
574 #ifdef LISP_FEATURE_PRECISE_ARG_COUNT_ERROR
575 || ((code
>> 16) & 31) == reg_NARGS
578 interrupt_internal_error(context
, 0);
582 interrupt_handle_now(signal
, (siginfo_t
*)code
, context
);
586 void arch_install_interrupt_handlers()
588 undoably_install_low_level_interrupt_handler(SIGILL
, sigtrap_handler
);
589 undoably_install_low_level_interrupt_handler(SIGTRAP
, sigtrap_handler
);
593 ppc_flush_icache(os_vm_address_t address
, os_vm_size_t length
)
595 os_vm_address_t end
= (os_vm_address_t
) ((int)(address
+length
+(32-1)) &~(32-1));
596 extern void ppc_flush_cache_line(os_vm_address_t
);
598 while (address
< end
) {
599 ppc_flush_cache_line(address
);
604 #ifdef LISP_FEATURE_LINKAGE_TABLE
606 /* Linkage tables for PowerPC
608 * Linkage entry size is 16, because we need at least 4 instructions to
613 * Define the registers to use in the linkage jump table. Can be the
614 * same. Some care must be exercised when choosing these. It has to be
615 * a register that is not otherwise being used. reg_NFP is a good
616 * choice. call_into_c trashes reg_NFP without preserving it, so we can
617 * trash it in the linkage jump table.
619 #define LINKAGE_TEMP_REG reg_NFP
620 #define LINKAGE_ADDR_REG reg_NFP
623 * Insert the necessary jump instructions at the given address.
626 arch_write_linkage_table_jmp(char *reloc_addr
, void *target_addr
)
629 * Make JMP to function entry.
631 * The instruction sequence is:
633 * addis 13, 0, (hi part of addr)
634 * ori 13, 13, (low part of addr)
640 unsigned long hi
; /* Top 16 bits of address */
641 unsigned long lo
; /* Low 16 bits of address */
644 inst_ptr
= (int*) reloc_addr
;
647 * Split the target address into hi and lo parts for the sethi
648 * instruction. hi is the top 22 bits. lo is the low 10 bits.
650 hi
= (unsigned long) target_addr
;
655 * addis 13, 0, (hi part)
658 inst
= (15 << 26) | (LINKAGE_TEMP_REG
<< 21) | (0 << 16) | hi
;
662 * ori 13, 13, (lo part)
665 inst
= (24 << 26) | (LINKAGE_TEMP_REG
<< 21) | (LINKAGE_TEMP_REG
<< 16) | lo
;
672 inst
= (31 << 26) | (LINKAGE_TEMP_REG
<< 21) | (9 << 16) | (467 << 1);
679 inst
= (19 << 26) | (20 << 21) | (528 << 1);
682 os_flush_icache((os_vm_address_t
) reloc_addr
, (char*) inst_ptr
- reloc_addr
);
686 arch_write_linkage_table_ref(void * reloc_addr
, void *target_addr
)
688 *(unsigned long *)reloc_addr
= (unsigned long)target_addr
;