diff options
Diffstat (limited to 'arch/frv/kernel/break.S')
-rw-r--r-- | arch/frv/kernel/break.S | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S new file mode 100644 index 000000000000..33233dc23e29 --- /dev/null +++ b/arch/frv/kernel/break.S | |||
@@ -0,0 +1,720 @@ | |||
1 | /* break.S: Break interrupt handling (kept separate from entry.S) | ||
2 | * | ||
3 | * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
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. | ||
10 | */ | ||
11 | |||
12 | #include <linux/sys.h> | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/linkage.h> | ||
15 | #include <asm/setup.h> | ||
16 | #include <asm/segment.h> | ||
17 | #include <asm/ptrace.h> | ||
18 | #include <asm/spr-regs.h> | ||
19 | |||
20 | #include <asm/errno.h> | ||
21 | |||
22 | # | ||
23 | # the break handler has its own stack | ||
24 | # | ||
25 | .section .bss.stack | ||
26 | .globl __break_user_context | ||
27 | .balign 8192 | ||
28 | __break_stack: | ||
29 | .space (8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7 | ||
30 | __break_stack_tos: | ||
31 | .space REG__DEBUG_XTRA | ||
32 | __break_user_context: | ||
33 | .space USER_CONTEXT_SIZE | ||
34 | |||
35 | # | ||
36 | # miscellaneous variables | ||
37 | # | ||
38 | .section .bss | ||
39 | #ifdef CONFIG_MMU | ||
40 | .globl __break_tlb_miss_real_return_info | ||
41 | __break_tlb_miss_real_return_info: | ||
42 | .balign 8 | ||
43 | .space 2*4 /* saved PCSR, PSR for TLB-miss handler fixup */ | ||
44 | #endif | ||
45 | |||
46 | __break_trace_through_exceptions: | ||
47 | .space 4 | ||
48 | |||
49 | #define CS2_ECS1 0xe1200000 | ||
50 | #define CS2_USERLED 0x4 | ||
51 | |||
52 | .macro LEDS val,reg | ||
53 | # sethi.p %hi(CS2_ECS1+CS2_USERLED),gr30 | ||
54 | # setlo %lo(CS2_ECS1+CS2_USERLED),gr30 | ||
55 | # setlos #~\val,\reg | ||
56 | # st \reg,@(gr30,gr0) | ||
57 | # setlos #0x5555,\reg | ||
58 | # sethi.p %hi(0xffc00100),gr30 | ||
59 | # setlo %lo(0xffc00100),gr30 | ||
60 | # sth \reg,@(gr30,gr0) | ||
61 | # membar | ||
62 | .endm | ||
63 | |||
64 | ############################################################################### | ||
65 | # | ||
66 | # entry point for Break Exceptions/Interrupts | ||
67 | # | ||
68 | ############################################################################### | ||
69 | .text | ||
70 | .balign 4 | ||
71 | .globl __entry_break | ||
72 | __entry_break: | ||
73 | #ifdef CONFIG_MMU | ||
74 | movgs gr31,scr3 | ||
75 | #endif | ||
76 | LEDS 0x1001,gr31 | ||
77 | |||
78 | sethi.p %hi(__break_user_context),gr31 | ||
79 | setlo %lo(__break_user_context),gr31 | ||
80 | |||
81 | stdi gr2,@(gr31,#REG_GR(2)) | ||
82 | movsg ccr,gr3 | ||
83 | sti gr3,@(gr31,#REG_CCR) | ||
84 | |||
85 | # catch the return from a TLB-miss handler that had single-step disabled | ||
86 | # traps will be enabled, so we have to do this now | ||
87 | #ifdef CONFIG_MMU | ||
88 | movsg bpcsr,gr3 | ||
89 | sethi.p %hi(__break_tlb_miss_return_breaks_here),gr2 | ||
90 | setlo %lo(__break_tlb_miss_return_breaks_here),gr2 | ||
91 | subcc gr2,gr3,gr0,icc0 | ||
92 | beq icc0,#2,__break_return_singlestep_tlbmiss | ||
93 | #endif | ||
94 | |||
95 | # determine whether we have stepped through into an exception | ||
96 | # - we need to take special action to suspend h/w single stepping if we've done | ||
97 | # that, so that the gdbstub doesn't get bogged down endlessly stepping through | ||
98 | # external interrupt handling | ||
99 | movsg bpsr,gr3 | ||
100 | andicc gr3,#BPSR_BET,gr0,icc0 | ||
101 | bne icc0,#2,__break_maybe_userspace /* jump if PSR.ET was 1 */ | ||
102 | |||
103 | LEDS 0x1003,gr2 | ||
104 | |||
105 | movsg brr,gr3 | ||
106 | andicc gr3,#BRR_ST,gr0,icc0 | ||
107 | andicc.p gr3,#BRR_SB,gr0,icc1 | ||
108 | bne icc0,#2,__break_step /* jump if single-step caused break */ | ||
109 | beq icc1,#2,__break_continue /* jump if BREAK didn't cause break */ | ||
110 | |||
111 | LEDS 0x1007,gr2 | ||
112 | |||
113 | # handle special breaks | ||
114 | movsg bpcsr,gr3 | ||
115 | |||
116 | sethi.p %hi(__entry_return_singlestep_breaks_here),gr2 | ||
117 | setlo %lo(__entry_return_singlestep_breaks_here),gr2 | ||
118 | subcc gr2,gr3,gr0,icc0 | ||
119 | beq icc0,#2,__break_return_singlestep | ||
120 | |||
121 | bra __break_continue | ||
122 | |||
123 | |||
124 | ############################################################################### | ||
125 | # | ||
126 | # handle BREAK instruction in kernel-mode exception epilogue | ||
127 | # | ||
128 | ############################################################################### | ||
129 | __break_return_singlestep: | ||
130 | LEDS 0x100f,gr2 | ||
131 | |||
132 | # special break insn requests single-stepping to be turned back on | ||
133 | # HERE RETT | ||
134 | # PSR.ET 0 0 | ||
135 | # PSR.PS old PSR.S ? | ||
136 | # PSR.S 1 1 | ||
137 | # BPSR.ET 0 1 (can't have caused orig excep otherwise) | ||
138 | # BPSR.BS 1 old PSR.S | ||
139 | movsg dcr,gr2 | ||
140 | sethi.p %hi(DCR_SE),gr3 | ||
141 | setlo %lo(DCR_SE),gr3 | ||
142 | or gr2,gr3,gr2 | ||
143 | movgs gr2,dcr | ||
144 | |||
145 | movsg psr,gr2 | ||
146 | andi gr2,#PSR_PS,gr2 | ||
147 | slli gr2,#11,gr2 /* PSR.PS -> BPSR.BS */ | ||
148 | ori gr2,#BPSR_BET,gr2 /* 1 -> BPSR.BET */ | ||
149 | movgs gr2,bpsr | ||
150 | |||
151 | # return to the invoker of the original kernel exception | ||
152 | movsg pcsr,gr2 | ||
153 | movgs gr2,bpcsr | ||
154 | |||
155 | LEDS 0x101f,gr2 | ||
156 | |||
157 | ldi @(gr31,#REG_CCR),gr3 | ||
158 | movgs gr3,ccr | ||
159 | lddi.p @(gr31,#REG_GR(2)),gr2 | ||
160 | xor gr31,gr31,gr31 | ||
161 | movgs gr0,brr | ||
162 | #ifdef CONFIG_MMU | ||
163 | movsg scr3,gr31 | ||
164 | #endif | ||
165 | rett #1 | ||
166 | |||
167 | ############################################################################### | ||
168 | # | ||
169 | # handle BREAK instruction in TLB-miss handler return path | ||
170 | # | ||
171 | ############################################################################### | ||
172 | #ifdef CONFIG_MMU | ||
173 | __break_return_singlestep_tlbmiss: | ||
174 | LEDS 0x1100,gr2 | ||
175 | |||
176 | sethi.p %hi(__break_tlb_miss_real_return_info),gr3 | ||
177 | setlo %lo(__break_tlb_miss_real_return_info),gr3 | ||
178 | lddi @(gr3,#0),gr2 | ||
179 | movgs gr2,pcsr | ||
180 | movgs gr3,psr | ||
181 | |||
182 | bra __break_return_singlestep | ||
183 | #endif | ||
184 | |||
185 | |||
186 | ############################################################################### | ||
187 | # | ||
188 | # handle single stepping into an exception prologue from kernel mode | ||
189 | # - we try and catch it whilst it is still in the main vector table | ||
190 | # - if we catch it there, we have to jump to the fixup handler | ||
191 | # - there is a fixup table that has a pointer for every 16b slot in the trap | ||
192 | # table | ||
193 | # | ||
194 | ############################################################################### | ||
195 | __break_step: | ||
196 | LEDS 0x2003,gr2 | ||
197 | |||
198 | # external interrupts seem to escape from the trap table before single | ||
199 | # step catches up with them | ||
200 | movsg bpcsr,gr2 | ||
201 | sethi.p %hi(__entry_kernel_external_interrupt),gr3 | ||
202 | setlo %lo(__entry_kernel_external_interrupt),gr3 | ||
203 | subcc gr2,gr3,gr0,icc0 | ||
204 | beq icc0,#2,__break_step_kernel_external_interrupt | ||
205 | sethi.p %hi(__entry_uspace_external_interrupt),gr3 | ||
206 | setlo %lo(__entry_uspace_external_interrupt),gr3 | ||
207 | subcc gr2,gr3,gr0,icc0 | ||
208 | beq icc0,#2,__break_step_uspace_external_interrupt | ||
209 | |||
210 | LEDS 0x2007,gr2 | ||
211 | |||
212 | # the two main vector tables are adjacent on one 8Kb slab | ||
213 | movsg bpcsr,gr2 | ||
214 | setlos #0xffffe000,gr3 | ||
215 | and gr2,gr3,gr2 | ||
216 | sethi.p %hi(__trap_tables),gr3 | ||
217 | setlo %lo(__trap_tables),gr3 | ||
218 | subcc gr2,gr3,gr0,icc0 | ||
219 | bne icc0,#2,__break_continue | ||
220 | |||
221 | LEDS 0x200f,gr2 | ||
222 | |||
223 | # skip workaround if so requested by GDB | ||
224 | sethi.p %hi(__break_trace_through_exceptions),gr3 | ||
225 | setlo %lo(__break_trace_through_exceptions),gr3 | ||
226 | ld @(gr3,gr0),gr3 | ||
227 | subcc gr3,gr0,gr0,icc0 | ||
228 | bne icc0,#0,__break_continue | ||
229 | |||
230 | LEDS 0x201f,gr2 | ||
231 | |||
232 | # access the fixup table - there's a 1:1 mapping between the slots in the trap tables and | ||
233 | # the slots in the trap fixup tables allowing us to simply divide the offset into the | ||
234 | # former by 4 to access the latter | ||
235 | sethi.p %hi(__trap_tables),gr3 | ||
236 | setlo %lo(__trap_tables),gr3 | ||
237 | movsg bpcsr,gr2 | ||
238 | sub gr2,gr3,gr2 | ||
239 | srli.p gr2,#2,gr2 | ||
240 | |||
241 | sethi %hi(__trap_fixup_tables),gr3 | ||
242 | setlo.p %lo(__trap_fixup_tables),gr3 | ||
243 | andi gr2,#~3,gr2 | ||
244 | ld @(gr2,gr3),gr2 | ||
245 | jmpil @(gr2,#0) | ||
246 | |||
247 | # step through an internal exception from kernel mode | ||
248 | .globl __break_step_kernel_softprog_interrupt | ||
249 | __break_step_kernel_softprog_interrupt: | ||
250 | sethi.p %hi(__entry_kernel_softprog_interrupt_reentry),gr3 | ||
251 | setlo %lo(__entry_kernel_softprog_interrupt_reentry),gr3 | ||
252 | bra __break_return_as_kernel_prologue | ||
253 | |||
254 | # step through an external interrupt from kernel mode | ||
255 | .globl __break_step_kernel_external_interrupt | ||
256 | __break_step_kernel_external_interrupt: | ||
257 | sethi.p %hi(__entry_kernel_external_interrupt_reentry),gr3 | ||
258 | setlo %lo(__entry_kernel_external_interrupt_reentry),gr3 | ||
259 | |||
260 | __break_return_as_kernel_prologue: | ||
261 | LEDS 0x203f,gr2 | ||
262 | |||
263 | movgs gr3,bpcsr | ||
264 | |||
265 | # do the bit we had to skip | ||
266 | #ifdef CONFIG_MMU | ||
267 | movsg ear0,gr2 /* EAR0 can get clobbered by gdb-stub (ICI/ICEI) */ | ||
268 | movgs gr2,scr2 | ||
269 | #endif | ||
270 | |||
271 | or.p sp,gr0,gr2 /* set up the stack pointer */ | ||
272 | subi sp,#REG__END,sp | ||
273 | sti.p gr2,@(sp,#REG_SP) | ||
274 | |||
275 | setlos #REG__STATUS_STEP,gr2 | ||
276 | sti gr2,@(sp,#REG__STATUS) /* record single step status */ | ||
277 | |||
278 | # cancel single-stepping mode | ||
279 | movsg dcr,gr2 | ||
280 | sethi.p %hi(~DCR_SE),gr3 | ||
281 | setlo %lo(~DCR_SE),gr3 | ||
282 | and gr2,gr3,gr2 | ||
283 | movgs gr2,dcr | ||
284 | |||
285 | LEDS 0x207f,gr2 | ||
286 | |||
287 | ldi @(gr31,#REG_CCR),gr3 | ||
288 | movgs gr3,ccr | ||
289 | lddi.p @(gr31,#REG_GR(2)),gr2 | ||
290 | xor gr31,gr31,gr31 | ||
291 | movgs gr0,brr | ||
292 | #ifdef CONFIG_MMU | ||
293 | movsg scr3,gr31 | ||
294 | #endif | ||
295 | rett #1 | ||
296 | |||
297 | # step through an internal exception from uspace mode | ||
298 | .globl __break_step_uspace_softprog_interrupt | ||
299 | __break_step_uspace_softprog_interrupt: | ||
300 | sethi.p %hi(__entry_uspace_softprog_interrupt_reentry),gr3 | ||
301 | setlo %lo(__entry_uspace_softprog_interrupt_reentry),gr3 | ||
302 | bra __break_return_as_uspace_prologue | ||
303 | |||
304 | # step through an external interrupt from kernel mode | ||
305 | .globl __break_step_uspace_external_interrupt | ||
306 | __break_step_uspace_external_interrupt: | ||
307 | sethi.p %hi(__entry_uspace_external_interrupt_reentry),gr3 | ||
308 | setlo %lo(__entry_uspace_external_interrupt_reentry),gr3 | ||
309 | |||
310 | __break_return_as_uspace_prologue: | ||
311 | LEDS 0x20ff,gr2 | ||
312 | |||
313 | movgs gr3,bpcsr | ||
314 | |||
315 | # do the bit we had to skip | ||
316 | sethi.p %hi(__kernel_frame0_ptr),gr28 | ||
317 | setlo %lo(__kernel_frame0_ptr),gr28 | ||
318 | ldi.p @(gr28,#0),gr28 | ||
319 | |||
320 | setlos #REG__STATUS_STEP,gr2 | ||
321 | sti gr2,@(gr28,#REG__STATUS) /* record single step status */ | ||
322 | |||
323 | # cancel single-stepping mode | ||
324 | movsg dcr,gr2 | ||
325 | sethi.p %hi(~DCR_SE),gr3 | ||
326 | setlo %lo(~DCR_SE),gr3 | ||
327 | and gr2,gr3,gr2 | ||
328 | movgs gr2,dcr | ||
329 | |||
330 | LEDS 0x20fe,gr2 | ||
331 | |||
332 | ldi @(gr31,#REG_CCR),gr3 | ||
333 | movgs gr3,ccr | ||
334 | lddi.p @(gr31,#REG_GR(2)),gr2 | ||
335 | xor gr31,gr31,gr31 | ||
336 | movgs gr0,brr | ||
337 | #ifdef CONFIG_MMU | ||
338 | movsg scr3,gr31 | ||
339 | #endif | ||
340 | rett #1 | ||
341 | |||
342 | #ifdef CONFIG_MMU | ||
343 | # step through an ITLB-miss handler from user mode | ||
344 | .globl __break_user_insn_tlb_miss | ||
345 | __break_user_insn_tlb_miss: | ||
346 | # we'll want to try the trap stub again | ||
347 | sethi.p %hi(__trap_user_insn_tlb_miss),gr2 | ||
348 | setlo %lo(__trap_user_insn_tlb_miss),gr2 | ||
349 | movgs gr2,bpcsr | ||
350 | |||
351 | __break_tlb_miss_common: | ||
352 | LEDS 0x2101,gr2 | ||
353 | |||
354 | # cancel single-stepping mode | ||
355 | movsg dcr,gr2 | ||
356 | sethi.p %hi(~DCR_SE),gr3 | ||
357 | setlo %lo(~DCR_SE),gr3 | ||
358 | and gr2,gr3,gr2 | ||
359 | movgs gr2,dcr | ||
360 | |||
361 | # we'll swap the real return address for one with a BREAK insn so that we can re-enable | ||
362 | # single stepping on return | ||
363 | movsg pcsr,gr2 | ||
364 | sethi.p %hi(__break_tlb_miss_real_return_info),gr3 | ||
365 | setlo %lo(__break_tlb_miss_real_return_info),gr3 | ||
366 | sti gr2,@(gr3,#0) | ||
367 | |||
368 | sethi.p %hi(__break_tlb_miss_return_break),gr2 | ||
369 | setlo %lo(__break_tlb_miss_return_break),gr2 | ||
370 | movgs gr2,pcsr | ||
371 | |||
372 | # we also have to fudge PSR because the return BREAK is in kernel space and we want | ||
373 | # to get a BREAK fault not an access violation should the return be to userspace | ||
374 | movsg psr,gr2 | ||
375 | sti.p gr2,@(gr3,#4) | ||
376 | ori gr2,#PSR_PS,gr2 | ||
377 | movgs gr2,psr | ||
378 | |||
379 | LEDS 0x2102,gr2 | ||
380 | |||
381 | ldi @(gr31,#REG_CCR),gr3 | ||
382 | movgs gr3,ccr | ||
383 | lddi @(gr31,#REG_GR(2)),gr2 | ||
384 | movsg scr3,gr31 | ||
385 | movgs gr0,brr | ||
386 | rett #1 | ||
387 | |||
388 | # step through a DTLB-miss handler from user mode | ||
389 | .globl __break_user_data_tlb_miss | ||
390 | __break_user_data_tlb_miss: | ||
391 | # we'll want to try the trap stub again | ||
392 | sethi.p %hi(__trap_user_data_tlb_miss),gr2 | ||
393 | setlo %lo(__trap_user_data_tlb_miss),gr2 | ||
394 | movgs gr2,bpcsr | ||
395 | bra __break_tlb_miss_common | ||
396 | |||
397 | # step through an ITLB-miss handler from kernel mode | ||
398 | .globl __break_kernel_insn_tlb_miss | ||
399 | __break_kernel_insn_tlb_miss: | ||
400 | # we'll want to try the trap stub again | ||
401 | sethi.p %hi(__trap_kernel_insn_tlb_miss),gr2 | ||
402 | setlo %lo(__trap_kernel_insn_tlb_miss),gr2 | ||
403 | movgs gr2,bpcsr | ||
404 | bra __break_tlb_miss_common | ||
405 | |||
406 | # step through a DTLB-miss handler from kernel mode | ||
407 | .globl __break_kernel_data_tlb_miss | ||
408 | __break_kernel_data_tlb_miss: | ||
409 | # we'll want to try the trap stub again | ||
410 | sethi.p %hi(__trap_kernel_data_tlb_miss),gr2 | ||
411 | setlo %lo(__trap_kernel_data_tlb_miss),gr2 | ||
412 | movgs gr2,bpcsr | ||
413 | bra __break_tlb_miss_common | ||
414 | #endif | ||
415 | |||
416 | ############################################################################### | ||
417 | # | ||
418 | # handle debug events originating with userspace | ||
419 | # | ||
420 | ############################################################################### | ||
421 | __break_maybe_userspace: | ||
422 | LEDS 0x3003,gr2 | ||
423 | |||
424 | setlos #BPSR_BS,gr2 | ||
425 | andcc gr3,gr2,gr0,icc0 | ||
426 | bne icc0,#0,__break_continue /* skip if PSR.S was 1 */ | ||
427 | |||
428 | movsg brr,gr2 | ||
429 | andicc gr2,#BRR_ST|BRR_SB,gr0,icc0 | ||
430 | beq icc0,#0,__break_continue /* jump if not BREAK or single-step */ | ||
431 | |||
432 | LEDS 0x3007,gr2 | ||
433 | |||
434 | # do the first part of the exception prologue here | ||
435 | sethi.p %hi(__kernel_frame0_ptr),gr28 | ||
436 | setlo %lo(__kernel_frame0_ptr),gr28 | ||
437 | ldi @(gr28,#0),gr28 | ||
438 | andi gr28,#~7,gr28 | ||
439 | |||
440 | # set up the kernel stack pointer | ||
441 | sti sp ,@(gr28,#REG_SP) | ||
442 | ori gr28,0,sp | ||
443 | sti gr0 ,@(gr28,#REG_GR(28)) | ||
444 | |||
445 | stdi gr20,@(gr28,#REG_GR(20)) | ||
446 | stdi gr22,@(gr28,#REG_GR(22)) | ||
447 | |||
448 | movsg tbr,gr20 | ||
449 | movsg bpcsr,gr21 | ||
450 | movsg psr,gr22 | ||
451 | |||
452 | # determine the exception type and cancel single-stepping mode | ||
453 | or gr0,gr0,gr23 | ||
454 | |||
455 | movsg dcr,gr2 | ||
456 | sethi.p %hi(DCR_SE),gr3 | ||
457 | setlo %lo(DCR_SE),gr3 | ||
458 | andcc gr2,gr3,gr0,icc0 | ||
459 | beq icc0,#0,__break_no_user_sstep /* must have been a BREAK insn */ | ||
460 | |||
461 | not gr3,gr3 | ||
462 | and gr2,gr3,gr2 | ||
463 | movgs gr2,dcr | ||
464 | ori gr23,#REG__STATUS_STEP,gr23 | ||
465 | |||
466 | __break_no_user_sstep: | ||
467 | LEDS 0x300f,gr2 | ||
468 | |||
469 | movsg brr,gr2 | ||
470 | andi gr2,#BRR_ST|BRR_SB,gr2 | ||
471 | slli gr2,#1,gr2 | ||
472 | or gr23,gr2,gr23 | ||
473 | sti.p gr23,@(gr28,#REG__STATUS) /* record single step status */ | ||
474 | |||
475 | # adjust the value acquired from TBR - this indicates the exception | ||
476 | setlos #~TBR_TT,gr2 | ||
477 | and.p gr20,gr2,gr20 | ||
478 | setlos #TBR_TT_BREAK,gr2 | ||
479 | or.p gr20,gr2,gr20 | ||
480 | |||
481 | # fudge PSR.PS and BPSR.BS to return to kernel mode through the trap | ||
482 | # table as trap 126 | ||
483 | andi gr22,#~PSR_PS,gr22 /* PSR.PS should be 0 */ | ||
484 | movgs gr22,psr | ||
485 | |||
486 | setlos #BPSR_BS,gr2 /* BPSR.BS should be 1 and BPSR.BET 0 */ | ||
487 | movgs gr2,bpsr | ||
488 | |||
489 | # return through remainder of the exception prologue | ||
490 | # - need to load gr23 with return handler address | ||
491 | sethi.p %hi(__entry_return_from_user_exception),gr23 | ||
492 | setlo %lo(__entry_return_from_user_exception),gr23 | ||
493 | sethi.p %hi(__entry_common),gr3 | ||
494 | setlo %lo(__entry_common),gr3 | ||
495 | movgs gr3,bpcsr | ||
496 | |||
497 | LEDS 0x301f,gr2 | ||
498 | |||
499 | ldi @(gr31,#REG_CCR),gr3 | ||
500 | movgs gr3,ccr | ||
501 | lddi.p @(gr31,#REG_GR(2)),gr2 | ||
502 | xor gr31,gr31,gr31 | ||
503 | movgs gr0,brr | ||
504 | #ifdef CONFIG_MMU | ||
505 | movsg scr3,gr31 | ||
506 | #endif | ||
507 | rett #1 | ||
508 | |||
509 | ############################################################################### | ||
510 | # | ||
511 | # resume normal debug-mode entry | ||
512 | # | ||
513 | ############################################################################### | ||
514 | __break_continue: | ||
515 | LEDS 0x4003,gr2 | ||
516 | |||
517 | # set up the kernel stack pointer | ||
518 | sti sp,@(gr31,#REG_SP) | ||
519 | |||
520 | sethi.p %hi(__break_stack_tos),sp | ||
521 | setlo %lo(__break_stack_tos),sp | ||
522 | |||
523 | # finish building the exception frame | ||
524 | stdi gr4 ,@(gr31,#REG_GR(4)) | ||
525 | stdi gr6 ,@(gr31,#REG_GR(6)) | ||
526 | stdi gr8 ,@(gr31,#REG_GR(8)) | ||
527 | stdi gr10,@(gr31,#REG_GR(10)) | ||
528 | stdi gr12,@(gr31,#REG_GR(12)) | ||
529 | stdi gr14,@(gr31,#REG_GR(14)) | ||
530 | stdi gr16,@(gr31,#REG_GR(16)) | ||
531 | stdi gr18,@(gr31,#REG_GR(18)) | ||
532 | stdi gr20,@(gr31,#REG_GR(20)) | ||
533 | stdi gr22,@(gr31,#REG_GR(22)) | ||
534 | stdi gr24,@(gr31,#REG_GR(24)) | ||
535 | stdi gr26,@(gr31,#REG_GR(26)) | ||
536 | sti gr0 ,@(gr31,#REG_GR(28)) /* NULL frame pointer */ | ||
537 | sti gr29,@(gr31,#REG_GR(29)) | ||
538 | sti gr30,@(gr31,#REG_GR(30)) | ||
539 | sti gr8 ,@(gr31,#REG_ORIG_GR8) | ||
540 | |||
541 | #ifdef CONFIG_MMU | ||
542 | movsg scr3,gr19 | ||
543 | sti gr19,@(gr31,#REG_GR(31)) | ||
544 | #endif | ||
545 | |||
546 | movsg bpsr ,gr19 | ||
547 | movsg tbr ,gr20 | ||
548 | movsg bpcsr,gr21 | ||
549 | movsg psr ,gr22 | ||
550 | movsg isr ,gr23 | ||
551 | movsg cccr ,gr25 | ||
552 | movsg lr ,gr26 | ||
553 | movsg lcr ,gr27 | ||
554 | |||
555 | andi.p gr22,#~(PSR_S|PSR_ET),gr5 /* rebuild PSR */ | ||
556 | andi gr19,#PSR_ET,gr4 | ||
557 | or.p gr4,gr5,gr5 | ||
558 | srli gr19,#10,gr4 | ||
559 | andi gr4,#PSR_S,gr4 | ||
560 | or.p gr4,gr5,gr5 | ||
561 | |||
562 | setlos #-1,gr6 | ||
563 | sti gr20,@(gr31,#REG_TBR) | ||
564 | sti gr21,@(gr31,#REG_PC) | ||
565 | sti gr5 ,@(gr31,#REG_PSR) | ||
566 | sti gr23,@(gr31,#REG_ISR) | ||
567 | sti gr25,@(gr31,#REG_CCCR) | ||
568 | stdi gr26,@(gr31,#REG_LR) | ||
569 | sti gr6 ,@(gr31,#REG_SYSCALLNO) | ||
570 | |||
571 | # store CPU-specific regs | ||
572 | movsg iacc0h,gr4 | ||
573 | movsg iacc0l,gr5 | ||
574 | stdi gr4,@(gr31,#REG_IACC0) | ||
575 | |||
576 | movsg gner0,gr4 | ||
577 | movsg gner1,gr5 | ||
578 | stdi gr4,@(gr31,#REG_GNER0) | ||
579 | |||
580 | # build the debug register frame | ||
581 | movsg brr,gr4 | ||
582 | movgs gr0,brr | ||
583 | movsg nmar,gr5 | ||
584 | movsg dcr,gr6 | ||
585 | |||
586 | stdi gr4 ,@(gr31,#REG_BRR) | ||
587 | sti gr19,@(gr31,#REG_BPSR) | ||
588 | sti.p gr6 ,@(gr31,#REG_DCR) | ||
589 | |||
590 | # trap exceptions during break handling and disable h/w breakpoints/watchpoints | ||
591 | sethi %hi(DCR_EBE),gr5 | ||
592 | setlo.p %lo(DCR_EBE),gr5 | ||
593 | sethi %hi(__entry_breaktrap_table),gr4 | ||
594 | setlo %lo(__entry_breaktrap_table),gr4 | ||
595 | movgs gr5,dcr | ||
596 | movgs gr4,tbr | ||
597 | |||
598 | # set up kernel global registers | ||
599 | sethi.p %hi(__kernel_current_task),gr5 | ||
600 | setlo %lo(__kernel_current_task),gr5 | ||
601 | ld @(gr5,gr0),gr29 | ||
602 | ldi.p @(gr29,#4),gr15 ; __current_thread_info = current->thread_info | ||
603 | |||
604 | sethi %hi(_gp),gr16 | ||
605 | setlo.p %lo(_gp),gr16 | ||
606 | |||
607 | # make sure we (the kernel) get div-zero and misalignment exceptions | ||
608 | setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5 | ||
609 | movgs gr5,isr | ||
610 | |||
611 | # enter the GDB stub | ||
612 | LEDS 0x4007,gr2 | ||
613 | |||
614 | or.p gr0,gr0,fp | ||
615 | call debug_stub | ||
616 | |||
617 | LEDS 0x403f,gr2 | ||
618 | |||
619 | # return from break | ||
620 | lddi @(gr31,#REG_IACC0),gr4 | ||
621 | movgs gr4,iacc0h | ||
622 | movgs gr5,iacc0l | ||
623 | |||
624 | lddi @(gr31,#REG_GNER0),gr4 | ||
625 | movgs gr4,gner0 | ||
626 | movgs gr5,gner1 | ||
627 | |||
628 | lddi @(gr31,#REG_LR) ,gr26 | ||
629 | lddi @(gr31,#REG_CCR) ,gr24 | ||
630 | lddi @(gr31,#REG_PSR) ,gr22 | ||
631 | ldi @(gr31,#REG_PC) ,gr21 | ||
632 | ldi @(gr31,#REG_TBR) ,gr20 | ||
633 | ldi.p @(gr31,#REG_DCR) ,gr6 | ||
634 | |||
635 | andi gr22,#PSR_S,gr19 /* rebuild BPSR */ | ||
636 | andi.p gr22,#PSR_ET,gr5 | ||
637 | slli gr19,#10,gr19 | ||
638 | or gr5,gr19,gr19 | ||
639 | |||
640 | movgs gr6 ,dcr | ||
641 | movgs gr19,bpsr | ||
642 | movgs gr20,tbr | ||
643 | movgs gr21,bpcsr | ||
644 | movgs gr23,isr | ||
645 | movgs gr24,ccr | ||
646 | movgs gr25,cccr | ||
647 | movgs gr26,lr | ||
648 | movgs gr27,lcr | ||
649 | |||
650 | LEDS 0x407f,gr2 | ||
651 | |||
652 | #ifdef CONFIG_MMU | ||
653 | ldi @(gr31,#REG_GR(31)),gr2 | ||
654 | movgs gr2,scr3 | ||
655 | #endif | ||
656 | |||
657 | ldi @(gr31,#REG_GR(30)),gr30 | ||
658 | ldi @(gr31,#REG_GR(29)),gr29 | ||
659 | lddi @(gr31,#REG_GR(26)),gr26 | ||
660 | lddi @(gr31,#REG_GR(24)),gr24 | ||
661 | lddi @(gr31,#REG_GR(22)),gr22 | ||
662 | lddi @(gr31,#REG_GR(20)),gr20 | ||
663 | lddi @(gr31,#REG_GR(18)),gr18 | ||
664 | lddi @(gr31,#REG_GR(16)),gr16 | ||
665 | lddi @(gr31,#REG_GR(14)),gr14 | ||
666 | lddi @(gr31,#REG_GR(12)),gr12 | ||
667 | lddi @(gr31,#REG_GR(10)),gr10 | ||
668 | lddi @(gr31,#REG_GR(8)) ,gr8 | ||
669 | lddi @(gr31,#REG_GR(6)) ,gr6 | ||
670 | lddi @(gr31,#REG_GR(4)) ,gr4 | ||
671 | lddi @(gr31,#REG_GR(2)) ,gr2 | ||
672 | ldi.p @(gr31,#REG_SP) ,sp | ||
673 | |||
674 | xor gr31,gr31,gr31 | ||
675 | movgs gr0,brr | ||
676 | #ifdef CONFIG_MMU | ||
677 | movsg scr3,gr31 | ||
678 | #endif | ||
679 | rett #1 | ||
680 | |||
681 | ################################################################################################### | ||
682 | # | ||
683 | # GDB stub "system calls" | ||
684 | # | ||
685 | ################################################################################################### | ||
686 | |||
687 | #ifdef CONFIG_GDBSTUB | ||
688 | # void gdbstub_console_write(struct console *con, const char *p, unsigned n) | ||
689 | .globl gdbstub_console_write | ||
690 | gdbstub_console_write: | ||
691 | break | ||
692 | bralr | ||
693 | #endif | ||
694 | |||
695 | # GDB stub BUG() trap | ||
696 | # GR8 is the proposed signal number | ||
697 | .globl __debug_bug_trap | ||
698 | __debug_bug_trap: | ||
699 | break | ||
700 | bralr | ||
701 | |||
702 | # transfer kernel exeception to GDB for handling | ||
703 | .globl __break_hijack_kernel_event | ||
704 | __break_hijack_kernel_event: | ||
705 | break | ||
706 | .globl __break_hijack_kernel_event_breaks_here | ||
707 | __break_hijack_kernel_event_breaks_here: | ||
708 | nop | ||
709 | |||
710 | #ifdef CONFIG_MMU | ||
711 | # handle a return from TLB-miss that requires single-step reactivation | ||
712 | .globl __break_tlb_miss_return_break | ||
713 | __break_tlb_miss_return_break: | ||
714 | break | ||
715 | __break_tlb_miss_return_breaks_here: | ||
716 | nop | ||
717 | #endif | ||
718 | |||
719 | # guard the first .text label in the next file from confusion | ||
720 | nop | ||