1 /* break.S: Break interrupt handling (kept separate from entry.S)
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/linkage.h>
13 #include <asm/setup.h>
14 #include <asm/segment.h>
15 #include <asm/ptrace.h>
16 #include <asm/thread_info.h>
17 #include <asm/spr-regs.h>
19 #include <asm/errno.h>
22 # the break handler has its own stack
25 .globl __break_user_context
28 .space THREAD_SIZE - FRV_FRAME0_SIZE
30 .space FRV_FRAME0_SIZE
33 # miscellaneous variables
37 .globl __break_tlb_miss_real_return_info
38 __break_tlb_miss_real_return_info:
40 .space 2*4 /* saved PCSR, PSR for TLB-miss handler fixup */
43 __break_trace_through_exceptions:
46 #define CS2_ECS1 0xe1200000
47 #define CS2_USERLED 0x4
50 # sethi.p %hi(CS2_ECS1+CS2_USERLED),gr30
51 # setlo %lo(CS2_ECS1+CS2_USERLED),gr30
55 # sethi.p %hi(0xffc00100),gr30
56 # setlo %lo(0xffc00100),gr30
57 # sth \reg,@(gr30,gr0)
61 ###############################################################################
63 # entry point for Break Exceptions/Interrupts
65 ###############################################################################
75 sethi.p %hi(__break_frame_0),gr31
76 setlo %lo(__break_frame_0),gr31
78 stdi gr2,@(gr31,#REG_GR(2))
80 sti gr3,@(gr31,#REG_CCR)
82 # catch the return from a TLB-miss handler that had single-step disabled
83 # traps will be enabled, so we have to do this now
86 sethi.p %hi(__break_tlb_miss_return_breaks_here),gr2
87 setlo %lo(__break_tlb_miss_return_breaks_here),gr2
88 subcc gr2,gr3,gr0,icc0
89 beq icc0,#2,__break_return_singlestep_tlbmiss
92 # determine whether we have stepped through into an exception
93 # - we need to take special action to suspend h/w single stepping if we've done
94 # that, so that the gdbstub doesn't get bogged down endlessly stepping through
95 # external interrupt handling
97 andicc gr3,#BPSR_BET,gr0,icc0
98 bne icc0,#2,__break_maybe_userspace /* jump if PSR.ET was 1 */
103 andicc gr3,#BRR_ST,gr0,icc0
104 andicc.p gr3,#BRR_SB,gr0,icc1
105 bne icc0,#2,__break_step /* jump if single-step caused break */
106 beq icc1,#2,__break_continue /* jump if BREAK didn't cause break */
110 # handle special breaks
113 sethi.p %hi(__entry_return_singlestep_breaks_here),gr2
114 setlo %lo(__entry_return_singlestep_breaks_here),gr2
115 subcc gr2,gr3,gr0,icc0
116 beq icc0,#2,__break_return_singlestep
121 ###############################################################################
123 # handle BREAK instruction in kernel-mode exception epilogue
125 ###############################################################################
126 __break_return_singlestep:
129 # special break insn requests single-stepping to be turned back on
134 # BPSR.ET 0 1 (can't have caused orig excep otherwise)
135 # BPSR.BS 1 old PSR.S
137 sethi.p %hi(DCR_SE),gr3
138 setlo %lo(DCR_SE),gr3
144 slli gr2,#11,gr2 /* PSR.PS -> BPSR.BS */
145 ori gr2,#BPSR_BET,gr2 /* 1 -> BPSR.BET */
148 # return to the invoker of the original kernel exception
154 ldi @(gr31,#REG_CCR),gr3
156 lddi.p @(gr31,#REG_GR(2)),gr2
164 ###############################################################################
166 # handle BREAK instruction in TLB-miss handler return path
168 ###############################################################################
170 __break_return_singlestep_tlbmiss:
173 sethi.p %hi(__break_tlb_miss_real_return_info),gr3
174 setlo %lo(__break_tlb_miss_real_return_info),gr3
179 bra __break_return_singlestep
183 ###############################################################################
185 # handle single stepping into an exception prologue from kernel mode
186 # - we try and catch it whilst it is still in the main vector table
187 # - if we catch it there, we have to jump to the fixup handler
188 # - there is a fixup table that has a pointer for every 16b slot in the trap
191 ###############################################################################
195 # external interrupts seem to escape from the trap table before single
196 # step catches up with them
198 sethi.p %hi(__entry_kernel_external_interrupt),gr3
199 setlo %lo(__entry_kernel_external_interrupt),gr3
200 subcc.p gr2,gr3,gr0,icc0
201 sethi %hi(__entry_uspace_external_interrupt),gr3
202 setlo.p %lo(__entry_uspace_external_interrupt),gr3
203 beq icc0,#2,__break_step_kernel_external_interrupt
204 subcc.p gr2,gr3,gr0,icc0
205 sethi %hi(__entry_kernel_external_interrupt_virtually_disabled),gr3
206 setlo.p %lo(__entry_kernel_external_interrupt_virtually_disabled),gr3
207 beq icc0,#2,__break_step_uspace_external_interrupt
208 subcc.p gr2,gr3,gr0,icc0
209 sethi %hi(__entry_kernel_external_interrupt_virtual_reenable),gr3
210 setlo.p %lo(__entry_kernel_external_interrupt_virtual_reenable),gr3
211 beq icc0,#2,__break_step_kernel_external_interrupt_virtually_disabled
212 subcc gr2,gr3,gr0,icc0
213 beq icc0,#2,__break_step_kernel_external_interrupt_virtual_reenable
217 # the two main vector tables are adjacent on one 8Kb slab
219 setlos #0xffffe000,gr3
221 sethi.p %hi(__trap_tables),gr3
222 setlo %lo(__trap_tables),gr3
223 subcc gr2,gr3,gr0,icc0
224 bne icc0,#2,__break_continue
228 # skip workaround if so requested by GDB
229 sethi.p %hi(__break_trace_through_exceptions),gr3
230 setlo %lo(__break_trace_through_exceptions),gr3
232 subcc gr3,gr0,gr0,icc0
233 bne icc0,#0,__break_continue
237 # access the fixup table - there's a 1:1 mapping between the slots in the trap tables and
238 # the slots in the trap fixup tables allowing us to simply divide the offset into the
239 # former by 4 to access the latter
240 sethi.p %hi(__trap_tables),gr3
241 setlo %lo(__trap_tables),gr3
246 sethi %hi(__trap_fixup_tables),gr3
247 setlo.p %lo(__trap_fixup_tables),gr3
252 # step through an internal exception from kernel mode
253 .globl __break_step_kernel_softprog_interrupt
254 __break_step_kernel_softprog_interrupt:
255 sethi.p %hi(__entry_kernel_softprog_interrupt_reentry),gr3
256 setlo %lo(__entry_kernel_softprog_interrupt_reentry),gr3
257 bra __break_return_as_kernel_prologue
259 # step through an external interrupt from kernel mode
260 .globl __break_step_kernel_external_interrupt
261 __break_step_kernel_external_interrupt:
262 # deal with virtual interrupt disablement
263 beq icc2,#0,__break_step_kernel_external_interrupt_virtually_disabled
265 sethi.p %hi(__entry_kernel_external_interrupt_reentry),gr3
266 setlo %lo(__entry_kernel_external_interrupt_reentry),gr3
268 __break_return_as_kernel_prologue:
273 # do the bit we had to skip
275 movsg ear0,gr2 /* EAR0 can get clobbered by gdb-stub (ICI/ICEI) */
279 or.p sp,gr0,gr2 /* set up the stack pointer */
281 sti.p gr2,@(sp,#REG_SP)
283 setlos #REG__STATUS_STEP,gr2
284 sti gr2,@(sp,#REG__STATUS) /* record single step status */
286 # cancel single-stepping mode
288 sethi.p %hi(~DCR_SE),gr3
289 setlo %lo(~DCR_SE),gr3
295 ldi @(gr31,#REG_CCR),gr3
297 lddi.p @(gr31,#REG_GR(2)),gr2
305 # we single-stepped into an interrupt handler whilst interrupts were merely virtually disabled
306 # need to really disable interrupts, set flag, fix up and return
307 __break_step_kernel_external_interrupt_virtually_disabled:
309 andi gr2,#~PSR_PIL,gr2
310 ori gr2,#PSR_PIL_14,gr2 /* debugging interrupts only */
313 ldi @(gr31,#REG_CCR),gr3
315 subcc.p gr0,gr0,gr0,icc2 /* leave Z set, clear C */
317 # exceptions must've been enabled and we must've been in supervisor mode
318 setlos BPSR_BET|BPSR_BS,gr3
321 # return to where the interrupt happened
325 lddi.p @(gr31,#REG_GR(2)),gr2
334 # we stepped through into the virtual interrupt reenablement trap
336 # we also want to single step anyway, but after fixing up so that we get an event on the
337 # instruction after the broken-into exception returns
338 .globl __break_step_kernel_external_interrupt_virtual_reenable
339 __break_step_kernel_external_interrupt_virtual_reenable:
341 andi gr2,#~PSR_PIL,gr2
344 ldi @(gr31,#REG_CCR),gr3
346 subicc gr0,#1,gr0,icc2 /* clear Z, set C */
348 # save the adjusted ICC2
350 sti gr3,@(gr31,#REG_CCR)
352 # exceptions must've been enabled and we must've been in supervisor mode
353 setlos BPSR_BET|BPSR_BS,gr3
356 # return to where the trap happened
360 # and then process the single step
363 # step through an internal exception from uspace mode
364 .globl __break_step_uspace_softprog_interrupt
365 __break_step_uspace_softprog_interrupt:
366 sethi.p %hi(__entry_uspace_softprog_interrupt_reentry),gr3
367 setlo %lo(__entry_uspace_softprog_interrupt_reentry),gr3
368 bra __break_return_as_uspace_prologue
370 # step through an external interrupt from kernel mode
371 .globl __break_step_uspace_external_interrupt
372 __break_step_uspace_external_interrupt:
373 sethi.p %hi(__entry_uspace_external_interrupt_reentry),gr3
374 setlo %lo(__entry_uspace_external_interrupt_reentry),gr3
376 __break_return_as_uspace_prologue:
381 # do the bit we had to skip
382 sethi.p %hi(__kernel_frame0_ptr),gr28
383 setlo %lo(__kernel_frame0_ptr),gr28
384 ldi.p @(gr28,#0),gr28
386 setlos #REG__STATUS_STEP,gr2
387 sti gr2,@(gr28,#REG__STATUS) /* record single step status */
389 # cancel single-stepping mode
391 sethi.p %hi(~DCR_SE),gr3
392 setlo %lo(~DCR_SE),gr3
398 ldi @(gr31,#REG_CCR),gr3
400 lddi.p @(gr31,#REG_GR(2)),gr2
409 # step through an ITLB-miss handler from user mode
410 .globl __break_user_insn_tlb_miss
411 __break_user_insn_tlb_miss:
412 # we'll want to try the trap stub again
413 sethi.p %hi(__trap_user_insn_tlb_miss),gr2
414 setlo %lo(__trap_user_insn_tlb_miss),gr2
417 __break_tlb_miss_common:
420 # cancel single-stepping mode
422 sethi.p %hi(~DCR_SE),gr3
423 setlo %lo(~DCR_SE),gr3
427 # we'll swap the real return address for one with a BREAK insn so that we can re-enable
428 # single stepping on return
430 sethi.p %hi(__break_tlb_miss_real_return_info),gr3
431 setlo %lo(__break_tlb_miss_real_return_info),gr3
434 sethi.p %hi(__break_tlb_miss_return_break),gr2
435 setlo %lo(__break_tlb_miss_return_break),gr2
438 # we also have to fudge PSR because the return BREAK is in kernel space and we want
439 # to get a BREAK fault not an access violation should the return be to userspace
447 ldi @(gr31,#REG_CCR),gr3
449 lddi @(gr31,#REG_GR(2)),gr2
454 # step through a DTLB-miss handler from user mode
455 .globl __break_user_data_tlb_miss
456 __break_user_data_tlb_miss:
457 # we'll want to try the trap stub again
458 sethi.p %hi(__trap_user_data_tlb_miss),gr2
459 setlo %lo(__trap_user_data_tlb_miss),gr2
461 bra __break_tlb_miss_common
463 # step through an ITLB-miss handler from kernel mode
464 .globl __break_kernel_insn_tlb_miss
465 __break_kernel_insn_tlb_miss:
466 # we'll want to try the trap stub again
467 sethi.p %hi(__trap_kernel_insn_tlb_miss),gr2
468 setlo %lo(__trap_kernel_insn_tlb_miss),gr2
470 bra __break_tlb_miss_common
472 # step through a DTLB-miss handler from kernel mode
473 .globl __break_kernel_data_tlb_miss
474 __break_kernel_data_tlb_miss:
475 # we'll want to try the trap stub again
476 sethi.p %hi(__trap_kernel_data_tlb_miss),gr2
477 setlo %lo(__trap_kernel_data_tlb_miss),gr2
479 bra __break_tlb_miss_common
482 ###############################################################################
484 # handle debug events originating with userspace
486 ###############################################################################
487 __break_maybe_userspace:
491 andcc gr3,gr2,gr0,icc0
492 bne icc0,#0,__break_continue /* skip if PSR.S was 1 */
495 andicc gr2,#BRR_ST|BRR_SB,gr0,icc0
496 beq icc0,#0,__break_continue /* jump if not BREAK or single-step */
500 # do the first part of the exception prologue here
501 sethi.p %hi(__kernel_frame0_ptr),gr28
502 setlo %lo(__kernel_frame0_ptr),gr28
506 # set up the kernel stack pointer
507 sti sp ,@(gr28,#REG_SP)
509 sti gr0 ,@(gr28,#REG_GR(28))
511 stdi gr20,@(gr28,#REG_GR(20))
512 stdi gr22,@(gr28,#REG_GR(22))
518 # determine the exception type and cancel single-stepping mode
522 sethi.p %hi(DCR_SE),gr3
523 setlo %lo(DCR_SE),gr3
524 andcc gr2,gr3,gr0,icc0
525 beq icc0,#0,__break_no_user_sstep /* must have been a BREAK insn */
530 ori gr23,#REG__STATUS_STEP,gr23
532 __break_no_user_sstep:
536 andi gr2,#BRR_ST|BRR_SB,gr2
539 sti.p gr23,@(gr28,#REG__STATUS) /* record single step status */
541 # adjust the value acquired from TBR - this indicates the exception
544 setlos #TBR_TT_BREAK,gr2
547 # fudge PSR.PS and BPSR.BS to return to kernel mode through the trap
549 andi gr22,#~PSR_PS,gr22 /* PSR.PS should be 0 */
552 setlos #BPSR_BS,gr2 /* BPSR.BS should be 1 and BPSR.BET 0 */
555 # return through remainder of the exception prologue
556 # - need to load gr23 with return handler address
557 sethi.p %hi(__entry_return_from_user_exception),gr23
558 setlo %lo(__entry_return_from_user_exception),gr23
559 sethi.p %hi(__entry_common),gr3
560 setlo %lo(__entry_common),gr3
565 ldi @(gr31,#REG_CCR),gr3
567 lddi.p @(gr31,#REG_GR(2)),gr2
575 ###############################################################################
577 # resume normal debug-mode entry
579 ###############################################################################
583 # set up the kernel stack pointer
584 sti sp,@(gr31,#REG_SP)
586 sethi.p %hi(__break_frame_0),sp
587 setlo %lo(__break_frame_0),sp
589 # finish building the exception frame
590 stdi gr4 ,@(gr31,#REG_GR(4))
591 stdi gr6 ,@(gr31,#REG_GR(6))
592 stdi gr8 ,@(gr31,#REG_GR(8))
593 stdi gr10,@(gr31,#REG_GR(10))
594 stdi gr12,@(gr31,#REG_GR(12))
595 stdi gr14,@(gr31,#REG_GR(14))
596 stdi gr16,@(gr31,#REG_GR(16))
597 stdi gr18,@(gr31,#REG_GR(18))
598 stdi gr20,@(gr31,#REG_GR(20))
599 stdi gr22,@(gr31,#REG_GR(22))
600 stdi gr24,@(gr31,#REG_GR(24))
601 stdi gr26,@(gr31,#REG_GR(26))
602 sti gr0 ,@(gr31,#REG_GR(28)) /* NULL frame pointer */
603 sti gr29,@(gr31,#REG_GR(29))
604 sti gr30,@(gr31,#REG_GR(30))
605 sti gr8 ,@(gr31,#REG_ORIG_GR8)
609 sti gr19,@(gr31,#REG_GR(31))
621 andi.p gr22,#~(PSR_S|PSR_ET),gr5 /* rebuild PSR */
622 andi gr19,#PSR_ET,gr4
629 sti gr20,@(gr31,#REG_TBR)
630 sti gr21,@(gr31,#REG_PC)
631 sti gr5 ,@(gr31,#REG_PSR)
632 sti gr23,@(gr31,#REG_ISR)
633 sti gr25,@(gr31,#REG_CCCR)
634 stdi gr26,@(gr31,#REG_LR)
635 sti gr6 ,@(gr31,#REG_SYSCALLNO)
637 # store CPU-specific regs
640 stdi gr4,@(gr31,#REG_IACC0)
644 stdi gr4,@(gr31,#REG_GNER0)
646 # build the debug register frame
652 sethi.p %hi(__debug_status),gr7
653 setlo %lo(__debug_status),gr7
655 stdi gr4 ,@(gr7,#DEBUG_BRR)
656 sti gr19,@(gr7,#DEBUG_BPSR)
657 sti.p gr6 ,@(gr7,#DEBUG_DCR)
659 # trap exceptions during break handling and disable h/w breakpoints/watchpoints
660 sethi %hi(DCR_EBE),gr5
661 setlo.p %lo(DCR_EBE),gr5
662 sethi %hi(__entry_breaktrap_table),gr4
663 setlo %lo(__entry_breaktrap_table),gr4
667 # set up kernel global registers
668 sethi.p %hi(__kernel_current_task),gr5
669 setlo %lo(__kernel_current_task),gr5
671 ldi.p @(gr29,#4),gr15 ; __current_thread_info = current->thread_info
674 setlo.p %lo(_gp),gr16
676 # make sure we (the kernel) get div-zero and misalignment exceptions
677 setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
689 lddi @(gr31,#REG_IACC0),gr4
693 lddi @(gr31,#REG_GNER0),gr4
697 lddi @(gr31,#REG_LR) ,gr26
698 lddi @(gr31,#REG_CCR) ,gr24
699 lddi @(gr31,#REG_PSR) ,gr22
700 ldi @(gr31,#REG_PC) ,gr21
701 ldi @(gr31,#REG_TBR) ,gr20
703 sethi.p %hi(__debug_status),gr6
704 setlo %lo(__debug_status),gr6
705 ldi.p @(gr6,#DEBUG_DCR) ,gr6
707 andi gr22,#PSR_S,gr19 /* rebuild BPSR */
708 andi.p gr22,#PSR_ET,gr5
725 ldi @(gr31,#REG_GR(31)),gr2
729 ldi @(gr31,#REG_GR(30)),gr30
730 ldi @(gr31,#REG_GR(29)),gr29
731 lddi @(gr31,#REG_GR(26)),gr26
732 lddi @(gr31,#REG_GR(24)),gr24
733 lddi @(gr31,#REG_GR(22)),gr22
734 lddi @(gr31,#REG_GR(20)),gr20
735 lddi @(gr31,#REG_GR(18)),gr18
736 lddi @(gr31,#REG_GR(16)),gr16
737 lddi @(gr31,#REG_GR(14)),gr14
738 lddi @(gr31,#REG_GR(12)),gr12
739 lddi @(gr31,#REG_GR(10)),gr10
740 lddi @(gr31,#REG_GR(8)) ,gr8
741 lddi @(gr31,#REG_GR(6)) ,gr6
742 lddi @(gr31,#REG_GR(4)) ,gr4
743 lddi @(gr31,#REG_GR(2)) ,gr2
744 ldi.p @(gr31,#REG_SP) ,sp
753 ###################################################################################################
755 # GDB stub "system calls"
757 ###################################################################################################
759 #ifdef CONFIG_GDBSTUB
760 # void gdbstub_console_write(struct console *con, const char *p, unsigned n)
761 .globl gdbstub_console_write
762 gdbstub_console_write:
767 # GDB stub BUG() trap
768 # GR8 is the proposed signal number
769 .globl __debug_bug_trap
774 # transfer kernel exeception to GDB for handling
775 .globl __break_hijack_kernel_event
776 __break_hijack_kernel_event:
778 .globl __break_hijack_kernel_event_breaks_here
779 __break_hijack_kernel_event_breaks_here:
783 # handle a return from TLB-miss that requires single-step reactivation
784 .globl __break_tlb_miss_return_break
785 __break_tlb_miss_return_break:
787 __break_tlb_miss_return_breaks_here:
791 # guard the first .text label in the next file from confusion