irq_domain: correct a minor wrong comment for linear revmap
[deliverable/linux.git] / arch / sh / kernel / cpu / sh5 / entry.S
1 /*
2 * arch/sh/kernel/cpu/sh5/entry.S
3 *
4 * Copyright (C) 2000, 2001 Paolo Alberelli
5 * Copyright (C) 2004 - 2008 Paul Mundt
6 * Copyright (C) 2003, 2004 Richard Curnow
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12 #include <linux/errno.h>
13 #include <linux/init.h>
14 #include <linux/sys.h>
15 #include <cpu/registers.h>
16 #include <asm/processor.h>
17 #include <asm/unistd.h>
18 #include <asm/thread_info.h>
19 #include <asm/asm-offsets.h>
20
21 /*
22 * SR fields.
23 */
24 #define SR_ASID_MASK 0x00ff0000
25 #define SR_FD_MASK 0x00008000
26 #define SR_SS 0x08000000
27 #define SR_BL 0x10000000
28 #define SR_MD 0x40000000
29
30 /*
31 * Event code.
32 */
33 #define EVENT_INTERRUPT 0
34 #define EVENT_FAULT_TLB 1
35 #define EVENT_FAULT_NOT_TLB 2
36 #define EVENT_DEBUG 3
37
38 /* EXPEVT values */
39 #define RESET_CAUSE 0x20
40 #define DEBUGSS_CAUSE 0x980
41
42 /*
43 * Frame layout. Quad index.
44 */
45 #define FRAME_T(x) FRAME_TBASE+(x*8)
46 #define FRAME_R(x) FRAME_RBASE+(x*8)
47 #define FRAME_S(x) FRAME_SBASE+(x*8)
48 #define FSPC 0
49 #define FSSR 1
50 #define FSYSCALL_ID 2
51
52 /* Arrange the save frame to be a multiple of 32 bytes long */
53 #define FRAME_SBASE 0
54 #define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */
55 #define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */
56 #define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */
57 #define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */
58
59 #define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */
60 #define FP_FRAME_BASE 0
61
62 #define SAVED_R2 0*8
63 #define SAVED_R3 1*8
64 #define SAVED_R4 2*8
65 #define SAVED_R5 3*8
66 #define SAVED_R18 4*8
67 #define SAVED_R6 5*8
68 #define SAVED_TR0 6*8
69
70 /* These are the registers saved in the TLB path that aren't saved in the first
71 level of the normal one. */
72 #define TLB_SAVED_R25 7*8
73 #define TLB_SAVED_TR1 8*8
74 #define TLB_SAVED_TR2 9*8
75 #define TLB_SAVED_TR3 10*8
76 #define TLB_SAVED_TR4 11*8
77 /* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing
78 breakage otherwise. */
79 #define TLB_SAVED_R0 12*8
80 #define TLB_SAVED_R1 13*8
81
82 #define CLI() \
83 getcon SR, r6; \
84 ori r6, 0xf0, r6; \
85 putcon r6, SR;
86
87 #define STI() \
88 getcon SR, r6; \
89 andi r6, ~0xf0, r6; \
90 putcon r6, SR;
91
92 #ifdef CONFIG_PREEMPT
93 # define preempt_stop() CLI()
94 #else
95 # define preempt_stop()
96 # define resume_kernel restore_all
97 #endif
98
99 .section .data, "aw"
100
101 #define FAST_TLBMISS_STACK_CACHELINES 4
102 #define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES)
103
104 /* Register back-up area for all exceptions */
105 .balign 32
106 /* Allow for 16 quadwords to be pushed by fast tlbmiss handling
107 * register saves etc. */
108 .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0
109 /* This is 32 byte aligned by construction */
110 /* Register back-up area for all exceptions */
111 reg_save_area:
112 .quad 0
113 .quad 0
114 .quad 0
115 .quad 0
116
117 .quad 0
118 .quad 0
119 .quad 0
120 .quad 0
121
122 .quad 0
123 .quad 0
124 .quad 0
125 .quad 0
126
127 .quad 0
128 .quad 0
129
130 /* Save area for RESVEC exceptions. We cannot use reg_save_area because of
131 * reentrancy. Note this area may be accessed via physical address.
132 * Align so this fits a whole single cache line, for ease of purging.
133 */
134 .balign 32,0,32
135 resvec_save_area:
136 .quad 0
137 .quad 0
138 .quad 0
139 .quad 0
140 .quad 0
141 .balign 32,0,32
142
143 /* Jump table of 3rd level handlers */
144 trap_jtable:
145 .long do_exception_error /* 0x000 */
146 .long do_exception_error /* 0x020 */
147 #ifdef CONFIG_MMU
148 .long tlb_miss_load /* 0x040 */
149 .long tlb_miss_store /* 0x060 */
150 #else
151 .long do_exception_error
152 .long do_exception_error
153 #endif
154 ! ARTIFICIAL pseudo-EXPEVT setting
155 .long do_debug_interrupt /* 0x080 */
156 #ifdef CONFIG_MMU
157 .long tlb_miss_load /* 0x0A0 */
158 .long tlb_miss_store /* 0x0C0 */
159 #else
160 .long do_exception_error
161 .long do_exception_error
162 #endif
163 .long do_address_error_load /* 0x0E0 */
164 .long do_address_error_store /* 0x100 */
165 #ifdef CONFIG_SH_FPU
166 .long do_fpu_error /* 0x120 */
167 #else
168 .long do_exception_error /* 0x120 */
169 #endif
170 .long do_exception_error /* 0x140 */
171 .long system_call /* 0x160 */
172 .long do_reserved_inst /* 0x180 */
173 .long do_illegal_slot_inst /* 0x1A0 */
174 .long do_exception_error /* 0x1C0 - NMI */
175 .long do_exception_error /* 0x1E0 */
176 .rept 15
177 .long do_IRQ /* 0x200 - 0x3C0 */
178 .endr
179 .long do_exception_error /* 0x3E0 */
180 .rept 32
181 .long do_IRQ /* 0x400 - 0x7E0 */
182 .endr
183 .long fpu_error_or_IRQA /* 0x800 */
184 .long fpu_error_or_IRQB /* 0x820 */
185 .long do_IRQ /* 0x840 */
186 .long do_IRQ /* 0x860 */
187 .rept 6
188 .long do_exception_error /* 0x880 - 0x920 */
189 .endr
190 .long breakpoint_trap_handler /* 0x940 */
191 .long do_exception_error /* 0x960 */
192 .long do_single_step /* 0x980 */
193
194 .rept 3
195 .long do_exception_error /* 0x9A0 - 0x9E0 */
196 .endr
197 .long do_IRQ /* 0xA00 */
198 .long do_IRQ /* 0xA20 */
199 #ifdef CONFIG_MMU
200 .long itlb_miss_or_IRQ /* 0xA40 */
201 #else
202 .long do_IRQ
203 #endif
204 .long do_IRQ /* 0xA60 */
205 .long do_IRQ /* 0xA80 */
206 #ifdef CONFIG_MMU
207 .long itlb_miss_or_IRQ /* 0xAA0 */
208 #else
209 .long do_IRQ
210 #endif
211 .long do_exception_error /* 0xAC0 */
212 .long do_address_error_exec /* 0xAE0 */
213 .rept 8
214 .long do_exception_error /* 0xB00 - 0xBE0 */
215 .endr
216 .rept 18
217 .long do_IRQ /* 0xC00 - 0xE20 */
218 .endr
219
220 .section .text64, "ax"
221
222 /*
223 * --- Exception/Interrupt/Event Handling Section
224 */
225
226 /*
227 * VBR and RESVEC blocks.
228 *
229 * First level handler for VBR-based exceptions.
230 *
231 * To avoid waste of space, align to the maximum text block size.
232 * This is assumed to be at most 128 bytes or 32 instructions.
233 * DO NOT EXCEED 32 instructions on the first level handlers !
234 *
235 * Also note that RESVEC is contained within the VBR block
236 * where the room left (1KB - TEXT_SIZE) allows placing
237 * the RESVEC block (at most 512B + TEXT_SIZE).
238 *
239 * So first (and only) level handler for RESVEC-based exceptions.
240 *
241 * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss
242 * and interrupt) we are a lot tight with register space until
243 * saving onto the stack frame, which is done in handle_exception().
244 *
245 */
246
247 #define TEXT_SIZE 128
248 #define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */
249
250 .balign TEXT_SIZE
251 LVBR_block:
252 .space 256, 0 /* Power-on class handler, */
253 /* not required here */
254 not_a_tlb_miss:
255 synco /* TAKum03020 (but probably a good idea anyway.) */
256 /* Save original stack pointer into KCR1 */
257 putcon SP, KCR1
258
259 /* Save other original registers into reg_save_area */
260 movi reg_save_area, SP
261 st.q SP, SAVED_R2, r2
262 st.q SP, SAVED_R3, r3
263 st.q SP, SAVED_R4, r4
264 st.q SP, SAVED_R5, r5
265 st.q SP, SAVED_R6, r6
266 st.q SP, SAVED_R18, r18
267 gettr tr0, r3
268 st.q SP, SAVED_TR0, r3
269
270 /* Set args for Non-debug, Not a TLB miss class handler */
271 getcon EXPEVT, r2
272 movi ret_from_exception, r3
273 ori r3, 1, r3
274 movi EVENT_FAULT_NOT_TLB, r4
275 or SP, ZERO, r5
276 getcon KCR1, SP
277 pta handle_exception, tr0
278 blink tr0, ZERO
279
280 .balign 256
281 ! VBR+0x200
282 nop
283 .balign 256
284 ! VBR+0x300
285 nop
286 .balign 256
287 /*
288 * Instead of the natural .balign 1024 place RESVEC here
289 * respecting the final 1KB alignment.
290 */
291 .balign TEXT_SIZE
292 /*
293 * Instead of '.space 1024-TEXT_SIZE' place the RESVEC
294 * block making sure the final alignment is correct.
295 */
296 #ifdef CONFIG_MMU
297 tlb_miss:
298 synco /* TAKum03020 (but probably a good idea anyway.) */
299 putcon SP, KCR1
300 movi reg_save_area, SP
301 /* SP is guaranteed 32-byte aligned. */
302 st.q SP, TLB_SAVED_R0 , r0
303 st.q SP, TLB_SAVED_R1 , r1
304 st.q SP, SAVED_R2 , r2
305 st.q SP, SAVED_R3 , r3
306 st.q SP, SAVED_R4 , r4
307 st.q SP, SAVED_R5 , r5
308 st.q SP, SAVED_R6 , r6
309 st.q SP, SAVED_R18, r18
310
311 /* Save R25 for safety; as/ld may want to use it to achieve the call to
312 * the code in mm/tlbmiss.c */
313 st.q SP, TLB_SAVED_R25, r25
314 gettr tr0, r2
315 gettr tr1, r3
316 gettr tr2, r4
317 gettr tr3, r5
318 gettr tr4, r18
319 st.q SP, SAVED_TR0 , r2
320 st.q SP, TLB_SAVED_TR1 , r3
321 st.q SP, TLB_SAVED_TR2 , r4
322 st.q SP, TLB_SAVED_TR3 , r5
323 st.q SP, TLB_SAVED_TR4 , r18
324
325 pt do_fast_page_fault, tr0
326 getcon SSR, r2
327 getcon EXPEVT, r3
328 getcon TEA, r4
329 shlri r2, 30, r2
330 andi r2, 1, r2 /* r2 = SSR.MD */
331 blink tr0, LINK
332
333 pt fixup_to_invoke_general_handler, tr1
334
335 /* If the fast path handler fixed the fault, just drop through quickly
336 to the restore code right away to return to the excepting context.
337 */
338 bnei/u r2, 0, tr1
339
340 fast_tlb_miss_restore:
341 ld.q SP, SAVED_TR0, r2
342 ld.q SP, TLB_SAVED_TR1, r3
343 ld.q SP, TLB_SAVED_TR2, r4
344
345 ld.q SP, TLB_SAVED_TR3, r5
346 ld.q SP, TLB_SAVED_TR4, r18
347
348 ptabs r2, tr0
349 ptabs r3, tr1
350 ptabs r4, tr2
351 ptabs r5, tr3
352 ptabs r18, tr4
353
354 ld.q SP, TLB_SAVED_R0, r0
355 ld.q SP, TLB_SAVED_R1, r1
356 ld.q SP, SAVED_R2, r2
357 ld.q SP, SAVED_R3, r3
358 ld.q SP, SAVED_R4, r4
359 ld.q SP, SAVED_R5, r5
360 ld.q SP, SAVED_R6, r6
361 ld.q SP, SAVED_R18, r18
362 ld.q SP, TLB_SAVED_R25, r25
363
364 getcon KCR1, SP
365 rte
366 nop /* for safety, in case the code is run on sh5-101 cut1.x */
367
368 fixup_to_invoke_general_handler:
369
370 /* OK, new method. Restore stuff that's not expected to get saved into
371 the 'first-level' reg save area, then just fall through to setting
372 up the registers and calling the second-level handler. */
373
374 /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore
375 r25,tr1-4 and save r6 to get into the right state. */
376
377 ld.q SP, TLB_SAVED_TR1, r3
378 ld.q SP, TLB_SAVED_TR2, r4
379 ld.q SP, TLB_SAVED_TR3, r5
380 ld.q SP, TLB_SAVED_TR4, r18
381 ld.q SP, TLB_SAVED_R25, r25
382
383 ld.q SP, TLB_SAVED_R0, r0
384 ld.q SP, TLB_SAVED_R1, r1
385
386 ptabs/u r3, tr1
387 ptabs/u r4, tr2
388 ptabs/u r5, tr3
389 ptabs/u r18, tr4
390
391 /* Set args for Non-debug, TLB miss class handler */
392 getcon EXPEVT, r2
393 movi ret_from_exception, r3
394 ori r3, 1, r3
395 movi EVENT_FAULT_TLB, r4
396 or SP, ZERO, r5
397 getcon KCR1, SP
398 pta handle_exception, tr0
399 blink tr0, ZERO
400 #else /* CONFIG_MMU */
401 .balign 256
402 #endif
403
404 /* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE
405 DOES END UP AT VBR+0x600 */
406 nop
407 nop
408 nop
409 nop
410 nop
411 nop
412
413 .balign 256
414 /* VBR + 0x600 */
415
416 interrupt:
417 synco /* TAKum03020 (but probably a good idea anyway.) */
418 /* Save original stack pointer into KCR1 */
419 putcon SP, KCR1
420
421 /* Save other original registers into reg_save_area */
422 movi reg_save_area, SP
423 st.q SP, SAVED_R2, r2
424 st.q SP, SAVED_R3, r3
425 st.q SP, SAVED_R4, r4
426 st.q SP, SAVED_R5, r5
427 st.q SP, SAVED_R6, r6
428 st.q SP, SAVED_R18, r18
429 gettr tr0, r3
430 st.q SP, SAVED_TR0, r3
431
432 /* Set args for interrupt class handler */
433 getcon INTEVT, r2
434 movi ret_from_irq, r3
435 ori r3, 1, r3
436 movi EVENT_INTERRUPT, r4
437 or SP, ZERO, r5
438 getcon KCR1, SP
439 pta handle_exception, tr0
440 blink tr0, ZERO
441 .balign TEXT_SIZE /* let's waste the bare minimum */
442
443 LVBR_block_end: /* Marker. Used for total checking */
444
445 .balign 256
446 LRESVEC_block:
447 /* Panic handler. Called with MMU off. Possible causes/actions:
448 * - Reset: Jump to program start.
449 * - Single Step: Turn off Single Step & return.
450 * - Others: Call panic handler, passing PC as arg.
451 * (this may need to be extended...)
452 */
453 reset_or_panic:
454 synco /* TAKum03020 (but probably a good idea anyway.) */
455 putcon SP, DCR
456 /* First save r0-1 and tr0, as we need to use these */
457 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
458 st.q SP, 0, r0
459 st.q SP, 8, r1
460 gettr tr0, r0
461 st.q SP, 32, r0
462
463 /* Check cause */
464 getcon EXPEVT, r0
465 movi RESET_CAUSE, r1
466 sub r1, r0, r1 /* r1=0 if reset */
467 movi _stext-CONFIG_PAGE_OFFSET, r0
468 ori r0, 1, r0
469 ptabs r0, tr0
470 beqi r1, 0, tr0 /* Jump to start address if reset */
471
472 getcon EXPEVT, r0
473 movi DEBUGSS_CAUSE, r1
474 sub r1, r0, r1 /* r1=0 if single step */
475 pta single_step_panic, tr0
476 beqi r1, 0, tr0 /* jump if single step */
477
478 /* Now jump to where we save the registers. */
479 movi panic_stash_regs-CONFIG_PAGE_OFFSET, r1
480 ptabs r1, tr0
481 blink tr0, r63
482
483 single_step_panic:
484 /* We are in a handler with Single Step set. We need to resume the
485 * handler, by turning on MMU & turning off Single Step. */
486 getcon SSR, r0
487 movi SR_MMU, r1
488 or r0, r1, r0
489 movi ~SR_SS, r1
490 and r0, r1, r0
491 putcon r0, SSR
492 /* Restore EXPEVT, as the rte won't do this */
493 getcon PEXPEVT, r0
494 putcon r0, EXPEVT
495 /* Restore regs */
496 ld.q SP, 32, r0
497 ptabs r0, tr0
498 ld.q SP, 0, r0
499 ld.q SP, 8, r1
500 getcon DCR, SP
501 synco
502 rte
503
504
505 .balign 256
506 debug_exception:
507 synco /* TAKum03020 (but probably a good idea anyway.) */
508 /*
509 * Single step/software_break_point first level handler.
510 * Called with MMU off, so the first thing we do is enable it
511 * by doing an rte with appropriate SSR.
512 */
513 putcon SP, DCR
514 /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */
515 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
516
517 /* With the MMU off, we are bypassing the cache, so purge any
518 * data that will be made stale by the following stores.
519 */
520 ocbp SP, 0
521 synco
522
523 st.q SP, 0, r0
524 st.q SP, 8, r1
525 getcon SPC, r0
526 st.q SP, 16, r0
527 getcon SSR, r0
528 st.q SP, 24, r0
529
530 /* Enable MMU, block exceptions, set priv mode, disable single step */
531 movi SR_MMU | SR_BL | SR_MD, r1
532 or r0, r1, r0
533 movi ~SR_SS, r1
534 and r0, r1, r0
535 putcon r0, SSR
536 /* Force control to debug_exception_2 when rte is executed */
537 movi debug_exeception_2, r0
538 ori r0, 1, r0 /* force SHmedia, just in case */
539 putcon r0, SPC
540 getcon DCR, SP
541 synco
542 rte
543 debug_exeception_2:
544 /* Restore saved regs */
545 putcon SP, KCR1
546 movi resvec_save_area, SP
547 ld.q SP, 24, r0
548 putcon r0, SSR
549 ld.q SP, 16, r0
550 putcon r0, SPC
551 ld.q SP, 0, r0
552 ld.q SP, 8, r1
553
554 /* Save other original registers into reg_save_area */
555 movi reg_save_area, SP
556 st.q SP, SAVED_R2, r2
557 st.q SP, SAVED_R3, r3
558 st.q SP, SAVED_R4, r4
559 st.q SP, SAVED_R5, r5
560 st.q SP, SAVED_R6, r6
561 st.q SP, SAVED_R18, r18
562 gettr tr0, r3
563 st.q SP, SAVED_TR0, r3
564
565 /* Set args for debug class handler */
566 getcon EXPEVT, r2
567 movi ret_from_exception, r3
568 ori r3, 1, r3
569 movi EVENT_DEBUG, r4
570 or SP, ZERO, r5
571 getcon KCR1, SP
572 pta handle_exception, tr0
573 blink tr0, ZERO
574
575 .balign 256
576 debug_interrupt:
577 /* !!! WE COME HERE IN REAL MODE !!! */
578 /* Hook-up debug interrupt to allow various debugging options to be
579 * hooked into its handler. */
580 /* Save original stack pointer into KCR1 */
581 synco
582 putcon SP, KCR1
583 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
584 ocbp SP, 0
585 ocbp SP, 32
586 synco
587
588 /* Save other original registers into reg_save_area thru real addresses */
589 st.q SP, SAVED_R2, r2
590 st.q SP, SAVED_R3, r3
591 st.q SP, SAVED_R4, r4
592 st.q SP, SAVED_R5, r5
593 st.q SP, SAVED_R6, r6
594 st.q SP, SAVED_R18, r18
595 gettr tr0, r3
596 st.q SP, SAVED_TR0, r3
597
598 /* move (spc,ssr)->(pspc,pssr). The rte will shift
599 them back again, so that they look like the originals
600 as far as the real handler code is concerned. */
601 getcon spc, r6
602 putcon r6, pspc
603 getcon ssr, r6
604 putcon r6, pssr
605
606 ! construct useful SR for handle_exception
607 movi 3, r6
608 shlli r6, 30, r6
609 getcon sr, r18
610 or r18, r6, r6
611 putcon r6, ssr
612
613 ! SSR is now the current SR with the MD and MMU bits set
614 ! i.e. the rte will switch back to priv mode and put
615 ! the mmu back on
616
617 ! construct spc
618 movi handle_exception, r18
619 ori r18, 1, r18 ! for safety (do we need this?)
620 putcon r18, spc
621
622 /* Set args for Non-debug, Not a TLB miss class handler */
623
624 ! EXPEVT==0x80 is unused, so 'steal' this value to put the
625 ! debug interrupt handler in the vectoring table
626 movi 0x80, r2
627 movi ret_from_exception, r3
628 ori r3, 1, r3
629 movi EVENT_FAULT_NOT_TLB, r4
630
631 or SP, ZERO, r5
632 movi CONFIG_PAGE_OFFSET, r6
633 add r6, r5, r5
634 getcon KCR1, SP
635
636 synco ! for safety
637 rte ! -> handle_exception, switch back to priv mode again
638
639 LRESVEC_block_end: /* Marker. Unused. */
640
641 .balign TEXT_SIZE
642
643 /*
644 * Second level handler for VBR-based exceptions. Pre-handler.
645 * In common to all stack-frame sensitive handlers.
646 *
647 * Inputs:
648 * (KCR0) Current [current task union]
649 * (KCR1) Original SP
650 * (r2) INTEVT/EXPEVT
651 * (r3) appropriate return address
652 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug)
653 * (r5) Pointer to reg_save_area
654 * (SP) Original SP
655 *
656 * Available registers:
657 * (r6)
658 * (r18)
659 * (tr0)
660 *
661 */
662 handle_exception:
663 /* Common 2nd level handler. */
664
665 /* First thing we need an appropriate stack pointer */
666 getcon SSR, r6
667 shlri r6, 30, r6
668 andi r6, 1, r6
669 pta stack_ok, tr0
670 bne r6, ZERO, tr0 /* Original stack pointer is fine */
671
672 /* Set stack pointer for user fault */
673 getcon KCR0, SP
674 movi THREAD_SIZE, r6 /* Point to the end */
675 add SP, r6, SP
676
677 stack_ok:
678
679 /* DEBUG : check for underflow/overflow of the kernel stack */
680 pta no_underflow, tr0
681 getcon KCR0, r6
682 movi 1024, r18
683 add r6, r18, r6
684 bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone
685
686 /* Just panic to cause a crash. */
687 bad_sp:
688 ld.b r63, 0, r6
689 nop
690
691 no_underflow:
692 pta bad_sp, tr0
693 getcon kcr0, r6
694 movi THREAD_SIZE, r18
695 add r18, r6, r6
696 bgt SP, r6, tr0 ! sp above the stack
697
698 /* Make some room for the BASIC frame. */
699 movi -(FRAME_SIZE), r6
700 add SP, r6, SP
701
702 /* Could do this with no stalling if we had another spare register, but the
703 code below will be OK. */
704 ld.q r5, SAVED_R2, r6
705 ld.q r5, SAVED_R3, r18
706 st.q SP, FRAME_R(2), r6
707 ld.q r5, SAVED_R4, r6
708 st.q SP, FRAME_R(3), r18
709 ld.q r5, SAVED_R5, r18
710 st.q SP, FRAME_R(4), r6
711 ld.q r5, SAVED_R6, r6
712 st.q SP, FRAME_R(5), r18
713 ld.q r5, SAVED_R18, r18
714 st.q SP, FRAME_R(6), r6
715 ld.q r5, SAVED_TR0, r6
716 st.q SP, FRAME_R(18), r18
717 st.q SP, FRAME_T(0), r6
718
719 /* Keep old SP around */
720 getcon KCR1, r6
721
722 /* Save the rest of the general purpose registers */
723 st.q SP, FRAME_R(0), r0
724 st.q SP, FRAME_R(1), r1
725 st.q SP, FRAME_R(7), r7
726 st.q SP, FRAME_R(8), r8
727 st.q SP, FRAME_R(9), r9
728 st.q SP, FRAME_R(10), r10
729 st.q SP, FRAME_R(11), r11
730 st.q SP, FRAME_R(12), r12
731 st.q SP, FRAME_R(13), r13
732 st.q SP, FRAME_R(14), r14
733
734 /* SP is somewhere else */
735 st.q SP, FRAME_R(15), r6
736
737 st.q SP, FRAME_R(16), r16
738 st.q SP, FRAME_R(17), r17
739 /* r18 is saved earlier. */
740 st.q SP, FRAME_R(19), r19
741 st.q SP, FRAME_R(20), r20
742 st.q SP, FRAME_R(21), r21
743 st.q SP, FRAME_R(22), r22
744 st.q SP, FRAME_R(23), r23
745 st.q SP, FRAME_R(24), r24
746 st.q SP, FRAME_R(25), r25
747 st.q SP, FRAME_R(26), r26
748 st.q SP, FRAME_R(27), r27
749 st.q SP, FRAME_R(28), r28
750 st.q SP, FRAME_R(29), r29
751 st.q SP, FRAME_R(30), r30
752 st.q SP, FRAME_R(31), r31
753 st.q SP, FRAME_R(32), r32
754 st.q SP, FRAME_R(33), r33
755 st.q SP, FRAME_R(34), r34
756 st.q SP, FRAME_R(35), r35
757 st.q SP, FRAME_R(36), r36
758 st.q SP, FRAME_R(37), r37
759 st.q SP, FRAME_R(38), r38
760 st.q SP, FRAME_R(39), r39
761 st.q SP, FRAME_R(40), r40
762 st.q SP, FRAME_R(41), r41
763 st.q SP, FRAME_R(42), r42
764 st.q SP, FRAME_R(43), r43
765 st.q SP, FRAME_R(44), r44
766 st.q SP, FRAME_R(45), r45
767 st.q SP, FRAME_R(46), r46
768 st.q SP, FRAME_R(47), r47
769 st.q SP, FRAME_R(48), r48
770 st.q SP, FRAME_R(49), r49
771 st.q SP, FRAME_R(50), r50
772 st.q SP, FRAME_R(51), r51
773 st.q SP, FRAME_R(52), r52
774 st.q SP, FRAME_R(53), r53
775 st.q SP, FRAME_R(54), r54
776 st.q SP, FRAME_R(55), r55
777 st.q SP, FRAME_R(56), r56
778 st.q SP, FRAME_R(57), r57
779 st.q SP, FRAME_R(58), r58
780 st.q SP, FRAME_R(59), r59
781 st.q SP, FRAME_R(60), r60
782 st.q SP, FRAME_R(61), r61
783 st.q SP, FRAME_R(62), r62
784
785 /*
786 * Save the S* registers.
787 */
788 getcon SSR, r61
789 st.q SP, FRAME_S(FSSR), r61
790 getcon SPC, r62
791 st.q SP, FRAME_S(FSPC), r62
792 movi -1, r62 /* Reset syscall_nr */
793 st.q SP, FRAME_S(FSYSCALL_ID), r62
794
795 /* Save the rest of the target registers */
796 gettr tr1, r6
797 st.q SP, FRAME_T(1), r6
798 gettr tr2, r6
799 st.q SP, FRAME_T(2), r6
800 gettr tr3, r6
801 st.q SP, FRAME_T(3), r6
802 gettr tr4, r6
803 st.q SP, FRAME_T(4), r6
804 gettr tr5, r6
805 st.q SP, FRAME_T(5), r6
806 gettr tr6, r6
807 st.q SP, FRAME_T(6), r6
808 gettr tr7, r6
809 st.q SP, FRAME_T(7), r6
810
811 ! setup FP so that unwinder can wind back through nested kernel mode
812 ! exceptions
813 add SP, ZERO, r14
814
815 /* For syscall and debug race condition, get TRA now */
816 getcon TRA, r5
817
818 /* We are in a safe position to turn SR.BL off, but set IMASK=0xf
819 * Also set FD, to catch FPU usage in the kernel.
820 *
821 * benedict.gaster@superh.com 29/07/2002
822 *
823 * On all SH5-101 revisions it is unsafe to raise the IMASK and at the
824 * same time change BL from 1->0, as any pending interrupt of a level
825 * higher than he previous value of IMASK will leak through and be
826 * taken unexpectedly.
827 *
828 * To avoid this we raise the IMASK and then issue another PUTCON to
829 * enable interrupts.
830 */
831 getcon SR, r6
832 movi SR_IMASK | SR_FD, r7
833 or r6, r7, r6
834 putcon r6, SR
835 movi SR_UNBLOCK_EXC, r7
836 and r6, r7, r6
837 putcon r6, SR
838
839
840 /* Now call the appropriate 3rd level handler */
841 or r3, ZERO, LINK
842 movi trap_jtable, r3
843 shlri r2, 3, r2
844 ldx.l r2, r3, r3
845 shlri r2, 2, r2
846 ptabs r3, tr0
847 or SP, ZERO, r3
848 blink tr0, ZERO
849
850 /*
851 * Second level handler for VBR-based exceptions. Post-handlers.
852 *
853 * Post-handlers for interrupts (ret_from_irq), exceptions
854 * (ret_from_exception) and common reentrance doors (restore_all
855 * to get back to the original context, ret_from_syscall loop to
856 * check kernel exiting).
857 *
858 * ret_with_reschedule and work_notifysig are an inner lables of
859 * the ret_from_syscall loop.
860 *
861 * In common to all stack-frame sensitive handlers.
862 *
863 * Inputs:
864 * (SP) struct pt_regs *, original register's frame pointer (basic)
865 *
866 */
867 .global ret_from_irq
868 ret_from_irq:
869 ld.q SP, FRAME_S(FSSR), r6
870 shlri r6, 30, r6
871 andi r6, 1, r6
872 pta resume_kernel, tr0
873 bne r6, ZERO, tr0 /* no further checks */
874 STI()
875 pta ret_with_reschedule, tr0
876 blink tr0, ZERO /* Do not check softirqs */
877
878 .global ret_from_exception
879 ret_from_exception:
880 preempt_stop()
881
882 ld.q SP, FRAME_S(FSSR), r6
883 shlri r6, 30, r6
884 andi r6, 1, r6
885 pta resume_kernel, tr0
886 bne r6, ZERO, tr0 /* no further checks */
887
888 /* Check softirqs */
889
890 #ifdef CONFIG_PREEMPT
891 pta ret_from_syscall, tr0
892 blink tr0, ZERO
893
894 resume_kernel:
895 CLI()
896
897 pta restore_all, tr0
898
899 getcon KCR0, r6
900 ld.l r6, TI_PRE_COUNT, r7
901 beq/u r7, ZERO, tr0
902
903 need_resched:
904 ld.l r6, TI_FLAGS, r7
905 movi (1 << TIF_NEED_RESCHED), r8
906 and r8, r7, r8
907 bne r8, ZERO, tr0
908
909 getcon SR, r7
910 andi r7, 0xf0, r7
911 bne r7, ZERO, tr0
912
913 movi preempt_schedule_irq, r7
914 ori r7, 1, r7
915 ptabs r7, tr1
916 blink tr1, LINK
917
918 pta need_resched, tr1
919 blink tr1, ZERO
920 #endif
921
922 .global ret_from_syscall
923 ret_from_syscall:
924
925 ret_with_reschedule:
926 getcon KCR0, r6 ! r6 contains current_thread_info
927 ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags
928
929 movi _TIF_NEED_RESCHED, r8
930 and r8, r7, r8
931 pta work_resched, tr0
932 bne r8, ZERO, tr0
933
934 pta restore_all, tr1
935
936 movi _TIF_SIGPENDING, r8
937 and r8, r7, r8
938 pta work_notifysig, tr0
939 bne r8, ZERO, tr0
940
941 blink tr1, ZERO
942
943 work_resched:
944 pta ret_from_syscall, tr0
945 gettr tr0, LINK
946 movi schedule, r6
947 ptabs r6, tr0
948 blink tr0, ZERO /* Call schedule(), return on top */
949
950 work_notifysig:
951 gettr tr1, LINK
952
953 movi do_notify_resume, r6
954 ptabs r6, tr0
955 or SP, ZERO, r2
956 or r7, ZERO, r3
957 blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */
958
959 restore_all:
960 /* Do prefetches */
961
962 ld.q SP, FRAME_T(0), r6
963 ld.q SP, FRAME_T(1), r7
964 ld.q SP, FRAME_T(2), r8
965 ld.q SP, FRAME_T(3), r9
966 ptabs r6, tr0
967 ptabs r7, tr1
968 ptabs r8, tr2
969 ptabs r9, tr3
970 ld.q SP, FRAME_T(4), r6
971 ld.q SP, FRAME_T(5), r7
972 ld.q SP, FRAME_T(6), r8
973 ld.q SP, FRAME_T(7), r9
974 ptabs r6, tr4
975 ptabs r7, tr5
976 ptabs r8, tr6
977 ptabs r9, tr7
978
979 ld.q SP, FRAME_R(0), r0
980 ld.q SP, FRAME_R(1), r1
981 ld.q SP, FRAME_R(2), r2
982 ld.q SP, FRAME_R(3), r3
983 ld.q SP, FRAME_R(4), r4
984 ld.q SP, FRAME_R(5), r5
985 ld.q SP, FRAME_R(6), r6
986 ld.q SP, FRAME_R(7), r7
987 ld.q SP, FRAME_R(8), r8
988 ld.q SP, FRAME_R(9), r9
989 ld.q SP, FRAME_R(10), r10
990 ld.q SP, FRAME_R(11), r11
991 ld.q SP, FRAME_R(12), r12
992 ld.q SP, FRAME_R(13), r13
993 ld.q SP, FRAME_R(14), r14
994
995 ld.q SP, FRAME_R(16), r16
996 ld.q SP, FRAME_R(17), r17
997 ld.q SP, FRAME_R(18), r18
998 ld.q SP, FRAME_R(19), r19
999 ld.q SP, FRAME_R(20), r20
1000 ld.q SP, FRAME_R(21), r21
1001 ld.q SP, FRAME_R(22), r22
1002 ld.q SP, FRAME_R(23), r23
1003 ld.q SP, FRAME_R(24), r24
1004 ld.q SP, FRAME_R(25), r25
1005 ld.q SP, FRAME_R(26), r26
1006 ld.q SP, FRAME_R(27), r27
1007 ld.q SP, FRAME_R(28), r28
1008 ld.q SP, FRAME_R(29), r29
1009 ld.q SP, FRAME_R(30), r30
1010 ld.q SP, FRAME_R(31), r31
1011 ld.q SP, FRAME_R(32), r32
1012 ld.q SP, FRAME_R(33), r33
1013 ld.q SP, FRAME_R(34), r34
1014 ld.q SP, FRAME_R(35), r35
1015 ld.q SP, FRAME_R(36), r36
1016 ld.q SP, FRAME_R(37), r37
1017 ld.q SP, FRAME_R(38), r38
1018 ld.q SP, FRAME_R(39), r39
1019 ld.q SP, FRAME_R(40), r40
1020 ld.q SP, FRAME_R(41), r41
1021 ld.q SP, FRAME_R(42), r42
1022 ld.q SP, FRAME_R(43), r43
1023 ld.q SP, FRAME_R(44), r44
1024 ld.q SP, FRAME_R(45), r45
1025 ld.q SP, FRAME_R(46), r46
1026 ld.q SP, FRAME_R(47), r47
1027 ld.q SP, FRAME_R(48), r48
1028 ld.q SP, FRAME_R(49), r49
1029 ld.q SP, FRAME_R(50), r50
1030 ld.q SP, FRAME_R(51), r51
1031 ld.q SP, FRAME_R(52), r52
1032 ld.q SP, FRAME_R(53), r53
1033 ld.q SP, FRAME_R(54), r54
1034 ld.q SP, FRAME_R(55), r55
1035 ld.q SP, FRAME_R(56), r56
1036 ld.q SP, FRAME_R(57), r57
1037 ld.q SP, FRAME_R(58), r58
1038
1039 getcon SR, r59
1040 movi SR_BLOCK_EXC, r60
1041 or r59, r60, r59
1042 putcon r59, SR /* SR.BL = 1, keep nesting out */
1043 ld.q SP, FRAME_S(FSSR), r61
1044 ld.q SP, FRAME_S(FSPC), r62
1045 movi SR_ASID_MASK, r60
1046 and r59, r60, r59
1047 andc r61, r60, r61 /* Clear out older ASID */
1048 or r59, r61, r61 /* Retain current ASID */
1049 putcon r61, SSR
1050 putcon r62, SPC
1051
1052 /* Ignore FSYSCALL_ID */
1053
1054 ld.q SP, FRAME_R(59), r59
1055 ld.q SP, FRAME_R(60), r60
1056 ld.q SP, FRAME_R(61), r61
1057 ld.q SP, FRAME_R(62), r62
1058
1059 /* Last touch */
1060 ld.q SP, FRAME_R(15), SP
1061 rte
1062 nop
1063
1064 /*
1065 * Third level handlers for VBR-based exceptions. Adapting args to
1066 * and/or deflecting to fourth level handlers.
1067 *
1068 * Fourth level handlers interface.
1069 * Most are C-coded handlers directly pointed by the trap_jtable.
1070 * (Third = Fourth level)
1071 * Inputs:
1072 * (r2) fault/interrupt code, entry number (e.g. NMI = 14,
1073 * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...)
1074 * (r3) struct pt_regs *, original register's frame pointer
1075 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault)
1076 * (r5) TRA control register (for syscall/debug benefit only)
1077 * (LINK) return address
1078 * (SP) = r3
1079 *
1080 * Kernel TLB fault handlers will get a slightly different interface.
1081 * (r2) struct pt_regs *, original register's frame pointer
1082 * (r3) page fault error code (see asm/thread_info.h)
1083 * (r4) Effective Address of fault
1084 * (LINK) return address
1085 * (SP) = r2
1086 *
1087 * fpu_error_or_IRQ? is a helper to deflect to the right cause.
1088 *
1089 */
1090 #ifdef CONFIG_MMU
1091 tlb_miss_load:
1092 or SP, ZERO, r2
1093 or ZERO, ZERO, r3 /* Read */
1094 getcon TEA, r4
1095 pta call_do_page_fault, tr0
1096 beq ZERO, ZERO, tr0
1097
1098 tlb_miss_store:
1099 or SP, ZERO, r2
1100 movi FAULT_CODE_WRITE, r3 /* Write */
1101 getcon TEA, r4
1102 pta call_do_page_fault, tr0
1103 beq ZERO, ZERO, tr0
1104
1105 itlb_miss_or_IRQ:
1106 pta its_IRQ, tr0
1107 beqi/u r4, EVENT_INTERRUPT, tr0
1108
1109 /* ITLB miss */
1110 or SP, ZERO, r2
1111 movi FAULT_CODE_ITLB, r3
1112 getcon TEA, r4
1113 /* Fall through */
1114
1115 call_do_page_fault:
1116 movi do_page_fault, r6
1117 ptabs r6, tr0
1118 blink tr0, ZERO
1119 #endif /* CONFIG_MMU */
1120
1121 fpu_error_or_IRQA:
1122 pta its_IRQ, tr0
1123 beqi/l r4, EVENT_INTERRUPT, tr0
1124 #ifdef CONFIG_SH_FPU
1125 movi fpu_state_restore_trap_handler, r6
1126 #else
1127 movi do_exception_error, r6
1128 #endif
1129 ptabs r6, tr0
1130 blink tr0, ZERO
1131
1132 fpu_error_or_IRQB:
1133 pta its_IRQ, tr0
1134 beqi/l r4, EVENT_INTERRUPT, tr0
1135 #ifdef CONFIG_SH_FPU
1136 movi fpu_state_restore_trap_handler, r6
1137 #else
1138 movi do_exception_error, r6
1139 #endif
1140 ptabs r6, tr0
1141 blink tr0, ZERO
1142
1143 its_IRQ:
1144 movi do_IRQ, r6
1145 ptabs r6, tr0
1146 blink tr0, ZERO
1147
1148 /*
1149 * system_call/unknown_trap third level handler:
1150 *
1151 * Inputs:
1152 * (r2) fault/interrupt code, entry number (TRAP = 11)
1153 * (r3) struct pt_regs *, original register's frame pointer
1154 * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault)
1155 * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr)
1156 * (SP) = r3
1157 * (LINK) return address: ret_from_exception
1158 * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7)
1159 *
1160 * Outputs:
1161 * (*r3) Syscall reply (Saved r2)
1162 * (LINK) In case of syscall only it can be scrapped.
1163 * Common second level post handler will be ret_from_syscall.
1164 * Common (non-trace) exit point to that is syscall_ret (saving
1165 * result to r2). Common bad exit point is syscall_bad (returning
1166 * ENOSYS then saved to r2).
1167 *
1168 */
1169
1170 unknown_trap:
1171 /* Unknown Trap or User Trace */
1172 movi do_unknown_trapa, r6
1173 ptabs r6, tr0
1174 ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */
1175 andi r2, 0x1ff, r2 /* r2 = syscall # */
1176 blink tr0, LINK
1177
1178 pta syscall_ret, tr0
1179 blink tr0, ZERO
1180
1181 /* New syscall implementation*/
1182 system_call:
1183 pta unknown_trap, tr0
1184 or r5, ZERO, r4 /* TRA (=r5) -> r4 */
1185 shlri r4, 20, r4
1186 bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */
1187
1188 /* It's a system call */
1189 st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */
1190 andi r5, 0x1ff, r5 /* syscall # -> r5 */
1191
1192 STI()
1193
1194 pta syscall_allowed, tr0
1195 movi NR_syscalls - 1, r4 /* Last valid */
1196 bgeu/l r4, r5, tr0
1197
1198 syscall_bad:
1199 /* Return ENOSYS ! */
1200 movi -(ENOSYS), r2 /* Fall-through */
1201
1202 .global syscall_ret
1203 syscall_ret:
1204 st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */
1205 ld.q SP, FRAME_S(FSPC), r2
1206 addi r2, 4, r2 /* Move PC, being pre-execution event */
1207 st.q SP, FRAME_S(FSPC), r2
1208 pta ret_from_syscall, tr0
1209 blink tr0, ZERO
1210
1211
1212 /* A different return path for ret_from_fork, because we now need
1213 * to call schedule_tail with the later kernels. Because prev is
1214 * loaded into r2 by switch_to() means we can just call it straight away
1215 */
1216
1217 .global ret_from_fork
1218 ret_from_fork:
1219
1220 movi schedule_tail,r5
1221 ori r5, 1, r5
1222 ptabs r5, tr0
1223 blink tr0, LINK
1224
1225 ld.q SP, FRAME_S(FSPC), r2
1226 addi r2, 4, r2 /* Move PC, being pre-execution event */
1227 st.q SP, FRAME_S(FSPC), r2
1228 pta ret_from_syscall, tr0
1229 blink tr0, ZERO
1230
1231 syscall_allowed:
1232 /* Use LINK to deflect the exit point, default is syscall_ret */
1233 pta syscall_ret, tr0
1234 gettr tr0, LINK
1235 pta syscall_notrace, tr0
1236
1237 getcon KCR0, r2
1238 ld.l r2, TI_FLAGS, r4
1239 movi _TIF_WORK_SYSCALL_MASK, r6
1240 and r6, r4, r6
1241 beq/l r6, ZERO, tr0
1242
1243 /* Trace it by calling syscall_trace before and after */
1244 movi do_syscall_trace_enter, r4
1245 or SP, ZERO, r2
1246 ptabs r4, tr0
1247 blink tr0, LINK
1248
1249 /* Save the retval */
1250 st.q SP, FRAME_R(2), r2
1251
1252 /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
1253 ld.q SP, FRAME_S(FSYSCALL_ID), r5
1254 andi r5, 0x1ff, r5
1255
1256 pta syscall_ret_trace, tr0
1257 gettr tr0, LINK
1258
1259 syscall_notrace:
1260 /* Now point to the appropriate 4th level syscall handler */
1261 movi sys_call_table, r4
1262 shlli r5, 2, r5
1263 ldx.l r4, r5, r5
1264 ptabs r5, tr0
1265
1266 /* Prepare original args */
1267 ld.q SP, FRAME_R(2), r2
1268 ld.q SP, FRAME_R(3), r3
1269 ld.q SP, FRAME_R(4), r4
1270 ld.q SP, FRAME_R(5), r5
1271 ld.q SP, FRAME_R(6), r6
1272 ld.q SP, FRAME_R(7), r7
1273
1274 /* And now the trick for those syscalls requiring regs * ! */
1275 or SP, ZERO, r8
1276
1277 /* Call it */
1278 blink tr0, ZERO /* LINK is already properly set */
1279
1280 syscall_ret_trace:
1281 /* We get back here only if under trace */
1282 st.q SP, FRAME_R(9), r2 /* Save return value */
1283
1284 movi do_syscall_trace_leave, LINK
1285 or SP, ZERO, r2
1286 ptabs LINK, tr0
1287 blink tr0, LINK
1288
1289 /* This needs to be done after any syscall tracing */
1290 ld.q SP, FRAME_S(FSPC), r2
1291 addi r2, 4, r2 /* Move PC, being pre-execution event */
1292 st.q SP, FRAME_S(FSPC), r2
1293
1294 pta ret_from_syscall, tr0
1295 blink tr0, ZERO /* Resume normal return sequence */
1296
1297 /*
1298 * --- Switch to running under a particular ASID and return the previous ASID value
1299 * --- The caller is assumed to have done a cli before calling this.
1300 *
1301 * Input r2 : new ASID
1302 * Output r2 : old ASID
1303 */
1304
1305 .global switch_and_save_asid
1306 switch_and_save_asid:
1307 getcon sr, r0
1308 movi 255, r4
1309 shlli r4, 16, r4 /* r4 = mask to select ASID */
1310 and r0, r4, r3 /* r3 = shifted old ASID */
1311 andi r2, 255, r2 /* mask down new ASID */
1312 shlli r2, 16, r2 /* align new ASID against SR.ASID */
1313 andc r0, r4, r0 /* efface old ASID from SR */
1314 or r0, r2, r0 /* insert the new ASID */
1315 putcon r0, ssr
1316 movi 1f, r0
1317 putcon r0, spc
1318 rte
1319 nop
1320 1:
1321 ptabs LINK, tr0
1322 shlri r3, 16, r2 /* r2 = old ASID */
1323 blink tr0, r63
1324
1325 .global route_to_panic_handler
1326 route_to_panic_handler:
1327 /* Switch to real mode, goto panic_handler, don't return. Useful for
1328 last-chance debugging, e.g. if no output wants to go to the console.
1329 */
1330
1331 movi panic_handler - CONFIG_PAGE_OFFSET, r1
1332 ptabs r1, tr0
1333 pta 1f, tr1
1334 gettr tr1, r0
1335 putcon r0, spc
1336 getcon sr, r0
1337 movi 1, r1
1338 shlli r1, 31, r1
1339 andc r0, r1, r0
1340 putcon r0, ssr
1341 rte
1342 nop
1343 1: /* Now in real mode */
1344 blink tr0, r63
1345 nop
1346
1347 .global peek_real_address_q
1348 peek_real_address_q:
1349 /* Two args:
1350 r2 : real mode address to peek
1351 r2(out) : result quadword
1352
1353 This is provided as a cheapskate way of manipulating device
1354 registers for debugging (to avoid the need to ioremap the debug
1355 module, and to avoid the need to ioremap the watchpoint
1356 controller in a way that identity maps sufficient bits to avoid the
1357 SH5-101 cut2 silicon defect).
1358
1359 This code is not performance critical
1360 */
1361
1362 add.l r2, r63, r2 /* sign extend address */
1363 getcon sr, r0 /* r0 = saved original SR */
1364 movi 1, r1
1365 shlli r1, 28, r1
1366 or r0, r1, r1 /* r0 with block bit set */
1367 putcon r1, sr /* now in critical section */
1368 movi 1, r36
1369 shlli r36, 31, r36
1370 andc r1, r36, r1 /* turn sr.mmu off in real mode section */
1371
1372 putcon r1, ssr
1373 movi .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1374 movi 1f, r37 /* virtual mode return addr */
1375 putcon r36, spc
1376
1377 synco
1378 rte
1379 nop
1380
1381 .peek0: /* come here in real mode, don't touch caches!!
1382 still in critical section (sr.bl==1) */
1383 putcon r0, ssr
1384 putcon r37, spc
1385 /* Here's the actual peek. If the address is bad, all bets are now off
1386 * what will happen (handlers invoked in real-mode = bad news) */
1387 ld.q r2, 0, r2
1388 synco
1389 rte /* Back to virtual mode */
1390 nop
1391
1392 1:
1393 ptabs LINK, tr0
1394 blink tr0, r63
1395
1396 .global poke_real_address_q
1397 poke_real_address_q:
1398 /* Two args:
1399 r2 : real mode address to poke
1400 r3 : quadword value to write.
1401
1402 This is provided as a cheapskate way of manipulating device
1403 registers for debugging (to avoid the need to ioremap the debug
1404 module, and to avoid the need to ioremap the watchpoint
1405 controller in a way that identity maps sufficient bits to avoid the
1406 SH5-101 cut2 silicon defect).
1407
1408 This code is not performance critical
1409 */
1410
1411 add.l r2, r63, r2 /* sign extend address */
1412 getcon sr, r0 /* r0 = saved original SR */
1413 movi 1, r1
1414 shlli r1, 28, r1
1415 or r0, r1, r1 /* r0 with block bit set */
1416 putcon r1, sr /* now in critical section */
1417 movi 1, r36
1418 shlli r36, 31, r36
1419 andc r1, r36, r1 /* turn sr.mmu off in real mode section */
1420
1421 putcon r1, ssr
1422 movi .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1423 movi 1f, r37 /* virtual mode return addr */
1424 putcon r36, spc
1425
1426 synco
1427 rte
1428 nop
1429
1430 .poke0: /* come here in real mode, don't touch caches!!
1431 still in critical section (sr.bl==1) */
1432 putcon r0, ssr
1433 putcon r37, spc
1434 /* Here's the actual poke. If the address is bad, all bets are now off
1435 * what will happen (handlers invoked in real-mode = bad news) */
1436 st.q r2, 0, r3
1437 synco
1438 rte /* Back to virtual mode */
1439 nop
1440
1441 1:
1442 ptabs LINK, tr0
1443 blink tr0, r63
1444
1445 #ifdef CONFIG_MMU
1446 /*
1447 * --- User Access Handling Section
1448 */
1449
1450 /*
1451 * User Access support. It all moved to non inlined Assembler
1452 * functions in here.
1453 *
1454 * __kernel_size_t __copy_user(void *__to, const void *__from,
1455 * __kernel_size_t __n)
1456 *
1457 * Inputs:
1458 * (r2) target address
1459 * (r3) source address
1460 * (r4) size in bytes
1461 *
1462 * Ouputs:
1463 * (*r2) target data
1464 * (r2) non-copied bytes
1465 *
1466 * If a fault occurs on the user pointer, bail out early and return the
1467 * number of bytes not copied in r2.
1468 * Strategy : for large blocks, call a real memcpy function which can
1469 * move >1 byte at a time using unaligned ld/st instructions, and can
1470 * manipulate the cache using prefetch + alloco to improve the speed
1471 * further. If a fault occurs in that function, just revert to the
1472 * byte-by-byte approach used for small blocks; this is rare so the
1473 * performance hit for that case does not matter.
1474 *
1475 * For small blocks it's not worth the overhead of setting up and calling
1476 * the memcpy routine; do the copy a byte at a time.
1477 *
1478 */
1479 .global __copy_user
1480 __copy_user:
1481 pta __copy_user_byte_by_byte, tr1
1482 movi 16, r0 ! this value is a best guess, should tune it by benchmarking
1483 bge/u r0, r4, tr1
1484 pta copy_user_memcpy, tr0
1485 addi SP, -32, SP
1486 /* Save arguments in case we have to fix-up unhandled page fault */
1487 st.q SP, 0, r2
1488 st.q SP, 8, r3
1489 st.q SP, 16, r4
1490 st.q SP, 24, r35 ! r35 is callee-save
1491 /* Save LINK in a register to reduce RTS time later (otherwise
1492 ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */
1493 ori LINK, 0, r35
1494 blink tr0, LINK
1495
1496 /* Copy completed normally if we get back here */
1497 ptabs r35, tr0
1498 ld.q SP, 24, r35
1499 /* don't restore r2-r4, pointless */
1500 /* set result=r2 to zero as the copy must have succeeded. */
1501 or r63, r63, r2
1502 addi SP, 32, SP
1503 blink tr0, r63 ! RTS
1504
1505 .global __copy_user_fixup
1506 __copy_user_fixup:
1507 /* Restore stack frame */
1508 ori r35, 0, LINK
1509 ld.q SP, 24, r35
1510 ld.q SP, 16, r4
1511 ld.q SP, 8, r3
1512 ld.q SP, 0, r2
1513 addi SP, 32, SP
1514 /* Fall through to original code, in the 'same' state we entered with */
1515
1516 /* The slow byte-by-byte method is used if the fast copy traps due to a bad
1517 user address. In that rare case, the speed drop can be tolerated. */
1518 __copy_user_byte_by_byte:
1519 pta ___copy_user_exit, tr1
1520 pta ___copy_user1, tr0
1521 beq/u r4, r63, tr1 /* early exit for zero length copy */
1522 sub r2, r3, r0
1523 addi r0, -1, r0
1524
1525 ___copy_user1:
1526 ld.b r3, 0, r5 /* Fault address 1 */
1527
1528 /* Could rewrite this to use just 1 add, but the second comes 'free'
1529 due to load latency */
1530 addi r3, 1, r3
1531 addi r4, -1, r4 /* No real fixup required */
1532 ___copy_user2:
1533 stx.b r3, r0, r5 /* Fault address 2 */
1534 bne r4, ZERO, tr0
1535
1536 ___copy_user_exit:
1537 or r4, ZERO, r2
1538 ptabs LINK, tr0
1539 blink tr0, ZERO
1540
1541 /*
1542 * __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
1543 *
1544 * Inputs:
1545 * (r2) target address
1546 * (r3) size in bytes
1547 *
1548 * Ouputs:
1549 * (*r2) zero-ed target data
1550 * (r2) non-zero-ed bytes
1551 */
1552 .global __clear_user
1553 __clear_user:
1554 pta ___clear_user_exit, tr1
1555 pta ___clear_user1, tr0
1556 beq/u r3, r63, tr1
1557
1558 ___clear_user1:
1559 st.b r2, 0, ZERO /* Fault address */
1560 addi r2, 1, r2
1561 addi r3, -1, r3 /* No real fixup required */
1562 bne r3, ZERO, tr0
1563
1564 ___clear_user_exit:
1565 or r3, ZERO, r2
1566 ptabs LINK, tr0
1567 blink tr0, ZERO
1568
1569 #endif /* CONFIG_MMU */
1570
1571 /*
1572 * int __strncpy_from_user(unsigned long __dest, unsigned long __src,
1573 * int __count)
1574 *
1575 * Inputs:
1576 * (r2) target address
1577 * (r3) source address
1578 * (r4) maximum size in bytes
1579 *
1580 * Ouputs:
1581 * (*r2) copied data
1582 * (r2) -EFAULT (in case of faulting)
1583 * copied data (otherwise)
1584 */
1585 .global __strncpy_from_user
1586 __strncpy_from_user:
1587 pta ___strncpy_from_user1, tr0
1588 pta ___strncpy_from_user_done, tr1
1589 or r4, ZERO, r5 /* r5 = original count */
1590 beq/u r4, r63, tr1 /* early exit if r4==0 */
1591 movi -(EFAULT), r6 /* r6 = reply, no real fixup */
1592 or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
1593
1594 ___strncpy_from_user1:
1595 ld.b r3, 0, r7 /* Fault address: only in reading */
1596 st.b r2, 0, r7
1597 addi r2, 1, r2
1598 addi r3, 1, r3
1599 beq/u ZERO, r7, tr1
1600 addi r4, -1, r4 /* return real number of copied bytes */
1601 bne/l ZERO, r4, tr0
1602
1603 ___strncpy_from_user_done:
1604 sub r5, r4, r6 /* If done, return copied */
1605
1606 ___strncpy_from_user_exit:
1607 or r6, ZERO, r2
1608 ptabs LINK, tr0
1609 blink tr0, ZERO
1610
1611 /*
1612 * extern long __strnlen_user(const char *__s, long __n)
1613 *
1614 * Inputs:
1615 * (r2) source address
1616 * (r3) source size in bytes
1617 *
1618 * Ouputs:
1619 * (r2) -EFAULT (in case of faulting)
1620 * string length (otherwise)
1621 */
1622 .global __strnlen_user
1623 __strnlen_user:
1624 pta ___strnlen_user_set_reply, tr0
1625 pta ___strnlen_user1, tr1
1626 or ZERO, ZERO, r5 /* r5 = counter */
1627 movi -(EFAULT), r6 /* r6 = reply, no real fixup */
1628 or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
1629 beq r3, ZERO, tr0
1630
1631 ___strnlen_user1:
1632 ldx.b r2, r5, r7 /* Fault address: only in reading */
1633 addi r3, -1, r3 /* No real fixup */
1634 addi r5, 1, r5
1635 beq r3, ZERO, tr0
1636 bne r7, ZERO, tr1
1637 ! The line below used to be active. This meant led to a junk byte lying between each pair
1638 ! of entries in the argv & envp structures in memory. Whilst the program saw the right data
1639 ! via the argv and envp arguments to main, it meant the 'flat' representation visible through
1640 ! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
1641 ! addi r5, 1, r5 /* Include '\0' */
1642
1643 ___strnlen_user_set_reply:
1644 or r5, ZERO, r6 /* If done, return counter */
1645
1646 ___strnlen_user_exit:
1647 or r6, ZERO, r2
1648 ptabs LINK, tr0
1649 blink tr0, ZERO
1650
1651 /*
1652 * extern long __get_user_asm_?(void *val, long addr)
1653 *
1654 * Inputs:
1655 * (r2) dest address
1656 * (r3) source address (in User Space)
1657 *
1658 * Ouputs:
1659 * (r2) -EFAULT (faulting)
1660 * 0 (not faulting)
1661 */
1662 .global __get_user_asm_b
1663 __get_user_asm_b:
1664 or r2, ZERO, r4
1665 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1666
1667 ___get_user_asm_b1:
1668 ld.b r3, 0, r5 /* r5 = data */
1669 st.b r4, 0, r5
1670 or ZERO, ZERO, r2
1671
1672 ___get_user_asm_b_exit:
1673 ptabs LINK, tr0
1674 blink tr0, ZERO
1675
1676
1677 .global __get_user_asm_w
1678 __get_user_asm_w:
1679 or r2, ZERO, r4
1680 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1681
1682 ___get_user_asm_w1:
1683 ld.w r3, 0, r5 /* r5 = data */
1684 st.w r4, 0, r5
1685 or ZERO, ZERO, r2
1686
1687 ___get_user_asm_w_exit:
1688 ptabs LINK, tr0
1689 blink tr0, ZERO
1690
1691
1692 .global __get_user_asm_l
1693 __get_user_asm_l:
1694 or r2, ZERO, r4
1695 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1696
1697 ___get_user_asm_l1:
1698 ld.l r3, 0, r5 /* r5 = data */
1699 st.l r4, 0, r5
1700 or ZERO, ZERO, r2
1701
1702 ___get_user_asm_l_exit:
1703 ptabs LINK, tr0
1704 blink tr0, ZERO
1705
1706
1707 .global __get_user_asm_q
1708 __get_user_asm_q:
1709 or r2, ZERO, r4
1710 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1711
1712 ___get_user_asm_q1:
1713 ld.q r3, 0, r5 /* r5 = data */
1714 st.q r4, 0, r5
1715 or ZERO, ZERO, r2
1716
1717 ___get_user_asm_q_exit:
1718 ptabs LINK, tr0
1719 blink tr0, ZERO
1720
1721 /*
1722 * extern long __put_user_asm_?(void *pval, long addr)
1723 *
1724 * Inputs:
1725 * (r2) kernel pointer to value
1726 * (r3) dest address (in User Space)
1727 *
1728 * Ouputs:
1729 * (r2) -EFAULT (faulting)
1730 * 0 (not faulting)
1731 */
1732 .global __put_user_asm_b
1733 __put_user_asm_b:
1734 ld.b r2, 0, r4 /* r4 = data */
1735 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1736
1737 ___put_user_asm_b1:
1738 st.b r3, 0, r4
1739 or ZERO, ZERO, r2
1740
1741 ___put_user_asm_b_exit:
1742 ptabs LINK, tr0
1743 blink tr0, ZERO
1744
1745
1746 .global __put_user_asm_w
1747 __put_user_asm_w:
1748 ld.w r2, 0, r4 /* r4 = data */
1749 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1750
1751 ___put_user_asm_w1:
1752 st.w r3, 0, r4
1753 or ZERO, ZERO, r2
1754
1755 ___put_user_asm_w_exit:
1756 ptabs LINK, tr0
1757 blink tr0, ZERO
1758
1759
1760 .global __put_user_asm_l
1761 __put_user_asm_l:
1762 ld.l r2, 0, r4 /* r4 = data */
1763 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1764
1765 ___put_user_asm_l1:
1766 st.l r3, 0, r4
1767 or ZERO, ZERO, r2
1768
1769 ___put_user_asm_l_exit:
1770 ptabs LINK, tr0
1771 blink tr0, ZERO
1772
1773
1774 .global __put_user_asm_q
1775 __put_user_asm_q:
1776 ld.q r2, 0, r4 /* r4 = data */
1777 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1778
1779 ___put_user_asm_q1:
1780 st.q r3, 0, r4
1781 or ZERO, ZERO, r2
1782
1783 ___put_user_asm_q_exit:
1784 ptabs LINK, tr0
1785 blink tr0, ZERO
1786
1787 panic_stash_regs:
1788 /* The idea is : when we get an unhandled panic, we dump the registers
1789 to a known memory location, the just sit in a tight loop.
1790 This allows the human to look at the memory region through the GDB
1791 session (assuming the debug module's SHwy initiator isn't locked up
1792 or anything), to hopefully analyze the cause of the panic. */
1793
1794 /* On entry, former r15 (SP) is in DCR
1795 former r0 is at resvec_saved_area + 0
1796 former r1 is at resvec_saved_area + 8
1797 former tr0 is at resvec_saved_area + 32
1798 DCR is the only register whose value is lost altogether.
1799 */
1800
1801 movi 0xffffffff80000000, r0 ! phy of dump area
1802 ld.q SP, 0x000, r1 ! former r0
1803 st.q r0, 0x000, r1
1804 ld.q SP, 0x008, r1 ! former r1
1805 st.q r0, 0x008, r1
1806 st.q r0, 0x010, r2
1807 st.q r0, 0x018, r3
1808 st.q r0, 0x020, r4
1809 st.q r0, 0x028, r5
1810 st.q r0, 0x030, r6
1811 st.q r0, 0x038, r7
1812 st.q r0, 0x040, r8
1813 st.q r0, 0x048, r9
1814 st.q r0, 0x050, r10
1815 st.q r0, 0x058, r11
1816 st.q r0, 0x060, r12
1817 st.q r0, 0x068, r13
1818 st.q r0, 0x070, r14
1819 getcon dcr, r14
1820 st.q r0, 0x078, r14
1821 st.q r0, 0x080, r16
1822 st.q r0, 0x088, r17
1823 st.q r0, 0x090, r18
1824 st.q r0, 0x098, r19
1825 st.q r0, 0x0a0, r20
1826 st.q r0, 0x0a8, r21
1827 st.q r0, 0x0b0, r22
1828 st.q r0, 0x0b8, r23
1829 st.q r0, 0x0c0, r24
1830 st.q r0, 0x0c8, r25
1831 st.q r0, 0x0d0, r26
1832 st.q r0, 0x0d8, r27
1833 st.q r0, 0x0e0, r28
1834 st.q r0, 0x0e8, r29
1835 st.q r0, 0x0f0, r30
1836 st.q r0, 0x0f8, r31
1837 st.q r0, 0x100, r32
1838 st.q r0, 0x108, r33
1839 st.q r0, 0x110, r34
1840 st.q r0, 0x118, r35
1841 st.q r0, 0x120, r36
1842 st.q r0, 0x128, r37
1843 st.q r0, 0x130, r38
1844 st.q r0, 0x138, r39
1845 st.q r0, 0x140, r40
1846 st.q r0, 0x148, r41
1847 st.q r0, 0x150, r42
1848 st.q r0, 0x158, r43
1849 st.q r0, 0x160, r44
1850 st.q r0, 0x168, r45
1851 st.q r0, 0x170, r46
1852 st.q r0, 0x178, r47
1853 st.q r0, 0x180, r48
1854 st.q r0, 0x188, r49
1855 st.q r0, 0x190, r50
1856 st.q r0, 0x198, r51
1857 st.q r0, 0x1a0, r52
1858 st.q r0, 0x1a8, r53
1859 st.q r0, 0x1b0, r54
1860 st.q r0, 0x1b8, r55
1861 st.q r0, 0x1c0, r56
1862 st.q r0, 0x1c8, r57
1863 st.q r0, 0x1d0, r58
1864 st.q r0, 0x1d8, r59
1865 st.q r0, 0x1e0, r60
1866 st.q r0, 0x1e8, r61
1867 st.q r0, 0x1f0, r62
1868 st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake...
1869
1870 ld.q SP, 0x020, r1 ! former tr0
1871 st.q r0, 0x200, r1
1872 gettr tr1, r1
1873 st.q r0, 0x208, r1
1874 gettr tr2, r1
1875 st.q r0, 0x210, r1
1876 gettr tr3, r1
1877 st.q r0, 0x218, r1
1878 gettr tr4, r1
1879 st.q r0, 0x220, r1
1880 gettr tr5, r1
1881 st.q r0, 0x228, r1
1882 gettr tr6, r1
1883 st.q r0, 0x230, r1
1884 gettr tr7, r1
1885 st.q r0, 0x238, r1
1886
1887 getcon sr, r1
1888 getcon ssr, r2
1889 getcon pssr, r3
1890 getcon spc, r4
1891 getcon pspc, r5
1892 getcon intevt, r6
1893 getcon expevt, r7
1894 getcon pexpevt, r8
1895 getcon tra, r9
1896 getcon tea, r10
1897 getcon kcr0, r11
1898 getcon kcr1, r12
1899 getcon vbr, r13
1900 getcon resvec, r14
1901
1902 st.q r0, 0x240, r1
1903 st.q r0, 0x248, r2
1904 st.q r0, 0x250, r3
1905 st.q r0, 0x258, r4
1906 st.q r0, 0x260, r5
1907 st.q r0, 0x268, r6
1908 st.q r0, 0x270, r7
1909 st.q r0, 0x278, r8
1910 st.q r0, 0x280, r9
1911 st.q r0, 0x288, r10
1912 st.q r0, 0x290, r11
1913 st.q r0, 0x298, r12
1914 st.q r0, 0x2a0, r13
1915 st.q r0, 0x2a8, r14
1916
1917 getcon SPC,r2
1918 getcon SSR,r3
1919 getcon EXPEVT,r4
1920 /* Prepare to jump to C - physical address */
1921 movi panic_handler-CONFIG_PAGE_OFFSET, r1
1922 ori r1, 1, r1
1923 ptabs r1, tr0
1924 getcon DCR, SP
1925 blink tr0, ZERO
1926 nop
1927 nop
1928 nop
1929 nop
1930
1931
1932
1933
1934 /*
1935 * --- Signal Handling Section
1936 */
1937
1938 /*
1939 * extern long long _sa_default_rt_restorer
1940 * extern long long _sa_default_restorer
1941 *
1942 * or, better,
1943 *
1944 * extern void _sa_default_rt_restorer(void)
1945 * extern void _sa_default_restorer(void)
1946 *
1947 * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn()
1948 * from user space. Copied into user space by signal management.
1949 * Both must be quad aligned and 2 quad long (4 instructions).
1950 *
1951 */
1952 .balign 8
1953 .global sa_default_rt_restorer
1954 sa_default_rt_restorer:
1955 movi 0x10, r9
1956 shori __NR_rt_sigreturn, r9
1957 trapa r9
1958 nop
1959
1960 .balign 8
1961 .global sa_default_restorer
1962 sa_default_restorer:
1963 movi 0x10, r9
1964 shori __NR_sigreturn, r9
1965 trapa r9
1966 nop
1967
1968 /*
1969 * --- __ex_table Section
1970 */
1971
1972 /*
1973 * User Access Exception Table.
1974 */
1975 .section __ex_table, "a"
1976
1977 .global asm_uaccess_start /* Just a marker */
1978 asm_uaccess_start:
1979
1980 #ifdef CONFIG_MMU
1981 .long ___copy_user1, ___copy_user_exit
1982 .long ___copy_user2, ___copy_user_exit
1983 .long ___clear_user1, ___clear_user_exit
1984 #endif
1985 .long ___strncpy_from_user1, ___strncpy_from_user_exit
1986 .long ___strnlen_user1, ___strnlen_user_exit
1987 .long ___get_user_asm_b1, ___get_user_asm_b_exit
1988 .long ___get_user_asm_w1, ___get_user_asm_w_exit
1989 .long ___get_user_asm_l1, ___get_user_asm_l_exit
1990 .long ___get_user_asm_q1, ___get_user_asm_q_exit
1991 .long ___put_user_asm_b1, ___put_user_asm_b_exit
1992 .long ___put_user_asm_w1, ___put_user_asm_w_exit
1993 .long ___put_user_asm_l1, ___put_user_asm_l_exit
1994 .long ___put_user_asm_q1, ___put_user_asm_q_exit
1995
1996 .global asm_uaccess_end /* Just a marker */
1997 asm_uaccess_end:
1998
1999
2000
2001
2002 /*
2003 * --- .init.text Section
2004 */
2005
2006 __INIT
2007
2008 /*
2009 * void trap_init (void)
2010 *
2011 */
2012 .global trap_init
2013 trap_init:
2014 addi SP, -24, SP /* Room to save r28/r29/r30 */
2015 st.q SP, 0, r28
2016 st.q SP, 8, r29
2017 st.q SP, 16, r30
2018
2019 /* Set VBR and RESVEC */
2020 movi LVBR_block, r19
2021 andi r19, -4, r19 /* reset MMUOFF + reserved */
2022 /* For RESVEC exceptions we force the MMU off, which means we need the
2023 physical address. */
2024 movi LRESVEC_block-CONFIG_PAGE_OFFSET, r20
2025 andi r20, -4, r20 /* reset reserved */
2026 ori r20, 1, r20 /* set MMUOFF */
2027 putcon r19, VBR
2028 putcon r20, RESVEC
2029
2030 /* Sanity check */
2031 movi LVBR_block_end, r21
2032 andi r21, -4, r21
2033 movi BLOCK_SIZE, r29 /* r29 = expected size */
2034 or r19, ZERO, r30
2035 add r19, r29, r19
2036
2037 /*
2038 * Ugly, but better loop forever now than crash afterwards.
2039 * We should print a message, but if we touch LVBR or
2040 * LRESVEC blocks we should not be surprised if we get stuck
2041 * in trap_init().
2042 */
2043 pta trap_init_loop, tr1
2044 gettr tr1, r28 /* r28 = trap_init_loop */
2045 sub r21, r30, r30 /* r30 = actual size */
2046
2047 /*
2048 * VBR/RESVEC handlers overlap by being bigger than
2049 * allowed. Very bad. Just loop forever.
2050 * (r28) panic/loop address
2051 * (r29) expected size
2052 * (r30) actual size
2053 */
2054 trap_init_loop:
2055 bne r19, r21, tr1
2056
2057 /* Now that exception vectors are set up reset SR.BL */
2058 getcon SR, r22
2059 movi SR_UNBLOCK_EXC, r23
2060 and r22, r23, r22
2061 putcon r22, SR
2062
2063 addi SP, 24, SP
2064 ptabs LINK, tr0
2065 blink tr0, ZERO
2066
This page took 0.073467 seconds and 5 git commands to generate.