2 * arch/sh/kernel/cpu/sh5/entry.S
4 * Copyright (C) 2000, 2001 Paolo Alberelli
5 * Copyright (C) 2004 - 2007 Paul Mundt
6 * Copyright (C) 2003, 2004 Richard Curnow
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
12 #include <linux/errno.h>
13 #include <linux/sys.h>
14 #include <cpu/registers.h>
15 #include <asm/processor.h>
16 #include <asm/unistd.h>
17 #include <asm/thread_info.h>
18 #include <asm/asm-offsets.h>
23 #define SR_ASID_MASK 0x00ff0000
24 #define SR_FD_MASK 0x00008000
25 #define SR_SS 0x08000000
26 #define SR_BL 0x10000000
27 #define SR_MD 0x40000000
32 #define EVENT_INTERRUPT 0
33 #define EVENT_FAULT_TLB 1
34 #define EVENT_FAULT_NOT_TLB 2
38 #define RESET_CAUSE 0x20
39 #define DEBUGSS_CAUSE 0x980
42 * Frame layout. Quad index.
44 #define FRAME_T(x) FRAME_TBASE+(x*8)
45 #define FRAME_R(x) FRAME_RBASE+(x*8)
46 #define FRAME_S(x) FRAME_SBASE+(x*8)
51 /* Arrange the save frame to be a multiple of 32 bytes long */
53 #define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */
54 #define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */
55 #define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */
56 #define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */
58 #define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */
59 #define FP_FRAME_BASE 0
69 /* These are the registers saved in the TLB path that aren't saved in the first
70 level of the normal one. */
71 #define TLB_SAVED_R25 7*8
72 #define TLB_SAVED_TR1 8*8
73 #define TLB_SAVED_TR2 9*8
74 #define TLB_SAVED_TR3 10*8
75 #define TLB_SAVED_TR4 11*8
76 /* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing
77 breakage otherwise. */
78 #define TLB_SAVED_R0 12*8
79 #define TLB_SAVED_R1 13*8
92 # define preempt_stop() CLI()
94 # define preempt_stop()
95 # define resume_kernel restore_all
100 #define FAST_TLBMISS_STACK_CACHELINES 4
101 #define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES)
103 /* Register back-up area for all exceptions */
105 /* Allow for 16 quadwords to be pushed by fast tlbmiss handling
106 * register saves etc. */
107 .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0
108 /* This is 32 byte aligned by construction */
109 /* Register back-up area for all exceptions */
129 /* Save area for RESVEC exceptions. We cannot use reg_save_area because of
130 * reentrancy. Note this area may be accessed via physical address.
131 * Align so this fits a whole single cache line, for ease of purging.
142 /* Jump table of 3rd level handlers */
144 .long do_exception_error /* 0x000 */
145 .long do_exception_error /* 0x020 */
147 .long tlb_miss_load /* 0x040 */
148 .long tlb_miss_store /* 0x060 */
150 .long do_exception_error
151 .long do_exception_error
153 ! ARTIFICIAL pseudo-EXPEVT setting
154 .long do_debug_interrupt /* 0x080 */
156 .long tlb_miss_load /* 0x0A0 */
157 .long tlb_miss_store /* 0x0C0 */
159 .long do_exception_error
160 .long do_exception_error
162 .long do_address_error_load /* 0x0E0 */
163 .long do_address_error_store /* 0x100 */
165 .long do_fpu_error /* 0x120 */
167 .long do_exception_error /* 0x120 */
169 .long do_exception_error /* 0x140 */
170 .long system_call /* 0x160 */
171 .long do_reserved_inst /* 0x180 */
172 .long do_illegal_slot_inst /* 0x1A0 */
173 .long do_exception_error /* 0x1C0 - NMI */
174 .long do_exception_error /* 0x1E0 */
176 .long do_IRQ /* 0x200 - 0x3C0 */
178 .long do_exception_error /* 0x3E0 */
180 .long do_IRQ /* 0x400 - 0x7E0 */
182 .long fpu_error_or_IRQA /* 0x800 */
183 .long fpu_error_or_IRQB /* 0x820 */
184 .long do_IRQ /* 0x840 */
185 .long do_IRQ /* 0x860 */
187 .long do_exception_error /* 0x880 - 0x920 */
189 .long do_software_break_point /* 0x940 */
190 .long do_exception_error /* 0x960 */
191 .long do_single_step /* 0x980 */
194 .long do_exception_error /* 0x9A0 - 0x9E0 */
196 .long do_IRQ /* 0xA00 */
197 .long do_IRQ /* 0xA20 */
199 .long itlb_miss_or_IRQ /* 0xA40 */
203 .long do_IRQ /* 0xA60 */
204 .long do_IRQ /* 0xA80 */
206 .long itlb_miss_or_IRQ /* 0xAA0 */
210 .long do_exception_error /* 0xAC0 */
211 .long do_address_error_exec /* 0xAE0 */
213 .long do_exception_error /* 0xB00 - 0xBE0 */
216 .long do_IRQ /* 0xC00 - 0xE20 */
219 .section .text64, "ax"
222 * --- Exception/Interrupt/Event Handling Section
226 * VBR and RESVEC blocks.
228 * First level handler for VBR-based exceptions.
230 * To avoid waste of space, align to the maximum text block size.
231 * This is assumed to be at most 128 bytes or 32 instructions.
232 * DO NOT EXCEED 32 instructions on the first level handlers !
234 * Also note that RESVEC is contained within the VBR block
235 * where the room left (1KB - TEXT_SIZE) allows placing
236 * the RESVEC block (at most 512B + TEXT_SIZE).
238 * So first (and only) level handler for RESVEC-based exceptions.
240 * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss
241 * and interrupt) we are a lot tight with register space until
242 * saving onto the stack frame, which is done in handle_exception().
246 #define TEXT_SIZE 128
247 #define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */
251 .space 256, 0 /* Power-on class handler, */
252 /* not required here */
254 synco /* TAKum03020 (but probably a good idea anyway.) */
255 /* Save original stack pointer into KCR1 */
258 /* Save other original registers into reg_save_area */
259 movi reg_save_area, SP
260 st.q SP, SAVED_R2, r2
261 st.q SP, SAVED_R3, r3
262 st.q SP, SAVED_R4, r4
263 st.q SP, SAVED_R5, r5
264 st.q SP, SAVED_R6, r6
265 st.q SP, SAVED_R18, r18
267 st.q SP, SAVED_TR0, r3
269 /* Set args for Non-debug, Not a TLB miss class handler */
271 movi ret_from_exception, r3
273 movi EVENT_FAULT_NOT_TLB, r4
276 pta handle_exception, tr0
287 * Instead of the natural .balign 1024 place RESVEC here
288 * respecting the final 1KB alignment.
292 * Instead of '.space 1024-TEXT_SIZE' place the RESVEC
293 * block making sure the final alignment is correct.
297 synco /* TAKum03020 (but probably a good idea anyway.) */
299 movi reg_save_area, SP
300 /* SP is guaranteed 32-byte aligned. */
301 st.q SP, TLB_SAVED_R0 , r0
302 st.q SP, TLB_SAVED_R1 , r1
303 st.q SP, SAVED_R2 , r2
304 st.q SP, SAVED_R3 , r3
305 st.q SP, SAVED_R4 , r4
306 st.q SP, SAVED_R5 , r5
307 st.q SP, SAVED_R6 , r6
308 st.q SP, SAVED_R18, r18
310 /* Save R25 for safety; as/ld may want to use it to achieve the call to
311 * the code in mm/tlbmiss.c */
312 st.q SP, TLB_SAVED_R25, r25
318 st.q SP, SAVED_TR0 , r2
319 st.q SP, TLB_SAVED_TR1 , r3
320 st.q SP, TLB_SAVED_TR2 , r4
321 st.q SP, TLB_SAVED_TR3 , r5
322 st.q SP, TLB_SAVED_TR4 , r18
324 pt do_fast_page_fault, tr0
329 andi r2, 1, r2 /* r2 = SSR.MD */
332 pt fixup_to_invoke_general_handler, tr1
334 /* If the fast path handler fixed the fault, just drop through quickly
335 to the restore code right away to return to the excepting context.
339 fast_tlb_miss_restore:
340 ld.q SP, SAVED_TR0, r2
341 ld.q SP, TLB_SAVED_TR1, r3
342 ld.q SP, TLB_SAVED_TR2, r4
344 ld.q SP, TLB_SAVED_TR3, r5
345 ld.q SP, TLB_SAVED_TR4, r18
353 ld.q SP, TLB_SAVED_R0, r0
354 ld.q SP, TLB_SAVED_R1, r1
355 ld.q SP, SAVED_R2, r2
356 ld.q SP, SAVED_R3, r3
357 ld.q SP, SAVED_R4, r4
358 ld.q SP, SAVED_R5, r5
359 ld.q SP, SAVED_R6, r6
360 ld.q SP, SAVED_R18, r18
361 ld.q SP, TLB_SAVED_R25, r25
365 nop /* for safety, in case the code is run on sh5-101 cut1.x */
367 fixup_to_invoke_general_handler:
369 /* OK, new method. Restore stuff that's not expected to get saved into
370 the 'first-level' reg save area, then just fall through to setting
371 up the registers and calling the second-level handler. */
373 /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore
374 r25,tr1-4 and save r6 to get into the right state. */
376 ld.q SP, TLB_SAVED_TR1, r3
377 ld.q SP, TLB_SAVED_TR2, r4
378 ld.q SP, TLB_SAVED_TR3, r5
379 ld.q SP, TLB_SAVED_TR4, r18
380 ld.q SP, TLB_SAVED_R25, r25
382 ld.q SP, TLB_SAVED_R0, r0
383 ld.q SP, TLB_SAVED_R1, r1
390 /* Set args for Non-debug, TLB miss class handler */
392 movi ret_from_exception, r3
394 movi EVENT_FAULT_TLB, r4
397 pta handle_exception, tr0
399 #else /* CONFIG_MMU */
403 /* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE
404 DOES END UP AT VBR+0x600 */
416 synco /* TAKum03020 (but probably a good idea anyway.) */
417 /* Save original stack pointer into KCR1 */
420 /* Save other original registers into reg_save_area */
421 movi reg_save_area, SP
422 st.q SP, SAVED_R2, r2
423 st.q SP, SAVED_R3, r3
424 st.q SP, SAVED_R4, r4
425 st.q SP, SAVED_R5, r5
426 st.q SP, SAVED_R6, r6
427 st.q SP, SAVED_R18, r18
429 st.q SP, SAVED_TR0, r3
431 /* Set args for interrupt class handler */
433 movi ret_from_irq, r3
435 movi EVENT_INTERRUPT, r4
438 pta handle_exception, tr0
440 .balign TEXT_SIZE /* let's waste the bare minimum */
442 LVBR_block_end: /* Marker. Used for total checking */
446 /* Panic handler. Called with MMU off. Possible causes/actions:
447 * - Reset: Jump to program start.
448 * - Single Step: Turn off Single Step & return.
449 * - Others: Call panic handler, passing PC as arg.
450 * (this may need to be extended...)
453 synco /* TAKum03020 (but probably a good idea anyway.) */
455 /* First save r0-1 and tr0, as we need to use these */
456 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
465 sub r1, r0, r1 /* r1=0 if reset */
466 movi _stext-CONFIG_PAGE_OFFSET, r0
469 beqi r1, 0, tr0 /* Jump to start address if reset */
472 movi DEBUGSS_CAUSE, r1
473 sub r1, r0, r1 /* r1=0 if single step */
474 pta single_step_panic, tr0
475 beqi r1, 0, tr0 /* jump if single step */
477 /* Now jump to where we save the registers. */
478 movi panic_stash_regs-CONFIG_PAGE_OFFSET, r1
483 /* We are in a handler with Single Step set. We need to resume the
484 * handler, by turning on MMU & turning off Single Step. */
491 /* Restore EXPEVT, as the rte won't do this */
506 synco /* TAKum03020 (but probably a good idea anyway.) */
508 * Single step/software_break_point first level handler.
509 * Called with MMU off, so the first thing we do is enable it
510 * by doing an rte with appropriate SSR.
513 /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */
514 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
516 /* With the MMU off, we are bypassing the cache, so purge any
517 * data that will be made stale by the following stores.
529 /* Enable MMU, block exceptions, set priv mode, disable single step */
530 movi SR_MMU | SR_BL | SR_MD, r1
535 /* Force control to debug_exception_2 when rte is executed */
536 movi debug_exeception_2, r0
537 ori r0, 1, r0 /* force SHmedia, just in case */
543 /* Restore saved regs */
545 movi resvec_save_area, SP
553 /* Save other original registers into reg_save_area */
554 movi reg_save_area, SP
555 st.q SP, SAVED_R2, r2
556 st.q SP, SAVED_R3, r3
557 st.q SP, SAVED_R4, r4
558 st.q SP, SAVED_R5, r5
559 st.q SP, SAVED_R6, r6
560 st.q SP, SAVED_R18, r18
562 st.q SP, SAVED_TR0, r3
564 /* Set args for debug class handler */
566 movi ret_from_exception, r3
571 pta handle_exception, tr0
576 /* !!! WE COME HERE IN REAL MODE !!! */
577 /* Hook-up debug interrupt to allow various debugging options to be
578 * hooked into its handler. */
579 /* Save original stack pointer into KCR1 */
582 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP
587 /* Save other original registers into reg_save_area thru real addresses */
588 st.q SP, SAVED_R2, r2
589 st.q SP, SAVED_R3, r3
590 st.q SP, SAVED_R4, r4
591 st.q SP, SAVED_R5, r5
592 st.q SP, SAVED_R6, r6
593 st.q SP, SAVED_R18, r18
595 st.q SP, SAVED_TR0, r3
597 /* move (spc,ssr)->(pspc,pssr). The rte will shift
598 them back again, so that they look like the originals
599 as far as the real handler code is concerned. */
605 ! construct useful SR for handle_exception
612 ! SSR is now the current SR with the MD and MMU bits set
613 ! i.e. the rte will switch back to priv mode and put
617 movi handle_exception, r18
618 ori r18, 1, r18 ! for safety (do we need this?)
621 /* Set args for Non-debug, Not a TLB miss class handler */
623 ! EXPEVT==0x80 is unused, so 'steal' this value to put the
624 ! debug interrupt handler in the vectoring table
626 movi ret_from_exception, r3
628 movi EVENT_FAULT_NOT_TLB, r4
631 movi CONFIG_PAGE_OFFSET, r6
636 rte ! -> handle_exception, switch back to priv mode again
638 LRESVEC_block_end: /* Marker. Unused. */
643 * Second level handler for VBR-based exceptions. Pre-handler.
644 * In common to all stack-frame sensitive handlers.
647 * (KCR0) Current [current task union]
650 * (r3) appropriate return address
651 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug)
652 * (r5) Pointer to reg_save_area
655 * Available registers:
662 /* Common 2nd level handler. */
664 /* First thing we need an appropriate stack pointer */
669 bne r6, ZERO, tr0 /* Original stack pointer is fine */
671 /* Set stack pointer for user fault */
673 movi THREAD_SIZE, r6 /* Point to the end */
678 /* DEBUG : check for underflow/overflow of the kernel stack */
679 pta no_underflow, tr0
683 bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone
685 /* Just panic to cause a crash. */
693 movi THREAD_SIZE, r18
695 bgt SP, r6, tr0 ! sp above the stack
697 /* Make some room for the BASIC frame. */
698 movi -(FRAME_SIZE), r6
701 /* Could do this with no stalling if we had another spare register, but the
702 code below will be OK. */
703 ld.q r5, SAVED_R2, r6
704 ld.q r5, SAVED_R3, r18
705 st.q SP, FRAME_R(2), r6
706 ld.q r5, SAVED_R4, r6
707 st.q SP, FRAME_R(3), r18
708 ld.q r5, SAVED_R5, r18
709 st.q SP, FRAME_R(4), r6
710 ld.q r5, SAVED_R6, r6
711 st.q SP, FRAME_R(5), r18
712 ld.q r5, SAVED_R18, r18
713 st.q SP, FRAME_R(6), r6
714 ld.q r5, SAVED_TR0, r6
715 st.q SP, FRAME_R(18), r18
716 st.q SP, FRAME_T(0), r6
718 /* Keep old SP around */
721 /* Save the rest of the general purpose registers */
722 st.q SP, FRAME_R(0), r0
723 st.q SP, FRAME_R(1), r1
724 st.q SP, FRAME_R(7), r7
725 st.q SP, FRAME_R(8), r8
726 st.q SP, FRAME_R(9), r9
727 st.q SP, FRAME_R(10), r10
728 st.q SP, FRAME_R(11), r11
729 st.q SP, FRAME_R(12), r12
730 st.q SP, FRAME_R(13), r13
731 st.q SP, FRAME_R(14), r14
733 /* SP is somewhere else */
734 st.q SP, FRAME_R(15), r6
736 st.q SP, FRAME_R(16), r16
737 st.q SP, FRAME_R(17), r17
738 /* r18 is saved earlier. */
739 st.q SP, FRAME_R(19), r19
740 st.q SP, FRAME_R(20), r20
741 st.q SP, FRAME_R(21), r21
742 st.q SP, FRAME_R(22), r22
743 st.q SP, FRAME_R(23), r23
744 st.q SP, FRAME_R(24), r24
745 st.q SP, FRAME_R(25), r25
746 st.q SP, FRAME_R(26), r26
747 st.q SP, FRAME_R(27), r27
748 st.q SP, FRAME_R(28), r28
749 st.q SP, FRAME_R(29), r29
750 st.q SP, FRAME_R(30), r30
751 st.q SP, FRAME_R(31), r31
752 st.q SP, FRAME_R(32), r32
753 st.q SP, FRAME_R(33), r33
754 st.q SP, FRAME_R(34), r34
755 st.q SP, FRAME_R(35), r35
756 st.q SP, FRAME_R(36), r36
757 st.q SP, FRAME_R(37), r37
758 st.q SP, FRAME_R(38), r38
759 st.q SP, FRAME_R(39), r39
760 st.q SP, FRAME_R(40), r40
761 st.q SP, FRAME_R(41), r41
762 st.q SP, FRAME_R(42), r42
763 st.q SP, FRAME_R(43), r43
764 st.q SP, FRAME_R(44), r44
765 st.q SP, FRAME_R(45), r45
766 st.q SP, FRAME_R(46), r46
767 st.q SP, FRAME_R(47), r47
768 st.q SP, FRAME_R(48), r48
769 st.q SP, FRAME_R(49), r49
770 st.q SP, FRAME_R(50), r50
771 st.q SP, FRAME_R(51), r51
772 st.q SP, FRAME_R(52), r52
773 st.q SP, FRAME_R(53), r53
774 st.q SP, FRAME_R(54), r54
775 st.q SP, FRAME_R(55), r55
776 st.q SP, FRAME_R(56), r56
777 st.q SP, FRAME_R(57), r57
778 st.q SP, FRAME_R(58), r58
779 st.q SP, FRAME_R(59), r59
780 st.q SP, FRAME_R(60), r60
781 st.q SP, FRAME_R(61), r61
782 st.q SP, FRAME_R(62), r62
785 * Save the S* registers.
788 st.q SP, FRAME_S(FSSR), r61
790 st.q SP, FRAME_S(FSPC), r62
791 movi -1, r62 /* Reset syscall_nr */
792 st.q SP, FRAME_S(FSYSCALL_ID), r62
794 /* Save the rest of the target registers */
796 st.q SP, FRAME_T(1), r6
798 st.q SP, FRAME_T(2), r6
800 st.q SP, FRAME_T(3), r6
802 st.q SP, FRAME_T(4), r6
804 st.q SP, FRAME_T(5), r6
806 st.q SP, FRAME_T(6), r6
808 st.q SP, FRAME_T(7), r6
810 ! setup FP so that unwinder can wind back through nested kernel mode
814 #ifdef CONFIG_POOR_MANS_STRACE
815 /* We've pushed all the registers now, so only r2-r4 hold anything
816 * useful. Move them into callee save registers */
821 /* Preserve r2 as the event code */
835 /* For syscall and debug race condition, get TRA now */
838 /* We are in a safe position to turn SR.BL off, but set IMASK=0xf
839 * Also set FD, to catch FPU usage in the kernel.
841 * benedict.gaster@superh.com 29/07/2002
843 * On all SH5-101 revisions it is unsafe to raise the IMASK and at the
844 * same time change BL from 1->0, as any pending interrupt of a level
845 * higher than he previous value of IMASK will leak through and be
846 * taken unexpectedly.
848 * To avoid this we raise the IMASK and then issue another PUTCON to
852 movi SR_IMASK | SR_FD, r7
855 movi SR_UNBLOCK_EXC, r7
860 /* Now call the appropriate 3rd level handler */
871 * Second level handler for VBR-based exceptions. Post-handlers.
873 * Post-handlers for interrupts (ret_from_irq), exceptions
874 * (ret_from_exception) and common reentrance doors (restore_all
875 * to get back to the original context, ret_from_syscall loop to
876 * check kernel exiting).
878 * ret_with_reschedule and work_notifysig are an inner lables of
879 * the ret_from_syscall loop.
881 * In common to all stack-frame sensitive handlers.
884 * (SP) struct pt_regs *, original register's frame pointer (basic)
889 #ifdef CONFIG_POOR_MANS_STRACE
890 pta evt_debug_ret_from_irq, tr0
894 ld.q SP, FRAME_S(FSSR), r6
897 pta resume_kernel, tr0
898 bne r6, ZERO, tr0 /* no further checks */
900 pta ret_with_reschedule, tr0
901 blink tr0, ZERO /* Do not check softirqs */
903 .global ret_from_exception
907 #ifdef CONFIG_POOR_MANS_STRACE
908 pta evt_debug_ret_from_exc, tr0
913 ld.q SP, FRAME_S(FSSR), r6
916 pta resume_kernel, tr0
917 bne r6, ZERO, tr0 /* no further checks */
921 #ifdef CONFIG_PREEMPT
922 pta ret_from_syscall, tr0
929 ld.l r6, TI_PRE_COUNT, r7
933 ld.l r6, TI_FLAGS, r7
934 movi (1 << TIF_NEED_RESCHED), r8
942 movi ((PREEMPT_ACTIVE >> 16) & 65535), r8
943 shori (PREEMPT_ACTIVE & 65535), r8
944 st.l r6, TI_PRE_COUNT, r8
952 st.l r6, TI_PRE_COUNT, ZERO
955 pta need_resched, tr1
959 .global ret_from_syscall
963 getcon KCR0, r6 ! r6 contains current_thread_info
964 ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags
966 movi _TIF_NEED_RESCHED, r8
968 pta work_resched, tr0
973 movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8
975 pta work_notifysig, tr0
981 pta ret_from_syscall, tr0
985 blink tr0, ZERO /* Call schedule(), return on top */
990 movi do_notify_resume, r6
994 blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */
999 ld.q SP, FRAME_T(0), r6
1000 ld.q SP, FRAME_T(1), r7
1001 ld.q SP, FRAME_T(2), r8
1002 ld.q SP, FRAME_T(3), r9
1007 ld.q SP, FRAME_T(4), r6
1008 ld.q SP, FRAME_T(5), r7
1009 ld.q SP, FRAME_T(6), r8
1010 ld.q SP, FRAME_T(7), r9
1016 ld.q SP, FRAME_R(0), r0
1017 ld.q SP, FRAME_R(1), r1
1018 ld.q SP, FRAME_R(2), r2
1019 ld.q SP, FRAME_R(3), r3
1020 ld.q SP, FRAME_R(4), r4
1021 ld.q SP, FRAME_R(5), r5
1022 ld.q SP, FRAME_R(6), r6
1023 ld.q SP, FRAME_R(7), r7
1024 ld.q SP, FRAME_R(8), r8
1025 ld.q SP, FRAME_R(9), r9
1026 ld.q SP, FRAME_R(10), r10
1027 ld.q SP, FRAME_R(11), r11
1028 ld.q SP, FRAME_R(12), r12
1029 ld.q SP, FRAME_R(13), r13
1030 ld.q SP, FRAME_R(14), r14
1032 ld.q SP, FRAME_R(16), r16
1033 ld.q SP, FRAME_R(17), r17
1034 ld.q SP, FRAME_R(18), r18
1035 ld.q SP, FRAME_R(19), r19
1036 ld.q SP, FRAME_R(20), r20
1037 ld.q SP, FRAME_R(21), r21
1038 ld.q SP, FRAME_R(22), r22
1039 ld.q SP, FRAME_R(23), r23
1040 ld.q SP, FRAME_R(24), r24
1041 ld.q SP, FRAME_R(25), r25
1042 ld.q SP, FRAME_R(26), r26
1043 ld.q SP, FRAME_R(27), r27
1044 ld.q SP, FRAME_R(28), r28
1045 ld.q SP, FRAME_R(29), r29
1046 ld.q SP, FRAME_R(30), r30
1047 ld.q SP, FRAME_R(31), r31
1048 ld.q SP, FRAME_R(32), r32
1049 ld.q SP, FRAME_R(33), r33
1050 ld.q SP, FRAME_R(34), r34
1051 ld.q SP, FRAME_R(35), r35
1052 ld.q SP, FRAME_R(36), r36
1053 ld.q SP, FRAME_R(37), r37
1054 ld.q SP, FRAME_R(38), r38
1055 ld.q SP, FRAME_R(39), r39
1056 ld.q SP, FRAME_R(40), r40
1057 ld.q SP, FRAME_R(41), r41
1058 ld.q SP, FRAME_R(42), r42
1059 ld.q SP, FRAME_R(43), r43
1060 ld.q SP, FRAME_R(44), r44
1061 ld.q SP, FRAME_R(45), r45
1062 ld.q SP, FRAME_R(46), r46
1063 ld.q SP, FRAME_R(47), r47
1064 ld.q SP, FRAME_R(48), r48
1065 ld.q SP, FRAME_R(49), r49
1066 ld.q SP, FRAME_R(50), r50
1067 ld.q SP, FRAME_R(51), r51
1068 ld.q SP, FRAME_R(52), r52
1069 ld.q SP, FRAME_R(53), r53
1070 ld.q SP, FRAME_R(54), r54
1071 ld.q SP, FRAME_R(55), r55
1072 ld.q SP, FRAME_R(56), r56
1073 ld.q SP, FRAME_R(57), r57
1074 ld.q SP, FRAME_R(58), r58
1077 movi SR_BLOCK_EXC, r60
1079 putcon r59, SR /* SR.BL = 1, keep nesting out */
1080 ld.q SP, FRAME_S(FSSR), r61
1081 ld.q SP, FRAME_S(FSPC), r62
1082 movi SR_ASID_MASK, r60
1084 andc r61, r60, r61 /* Clear out older ASID */
1085 or r59, r61, r61 /* Retain current ASID */
1089 /* Ignore FSYSCALL_ID */
1091 ld.q SP, FRAME_R(59), r59
1092 ld.q SP, FRAME_R(60), r60
1093 ld.q SP, FRAME_R(61), r61
1094 ld.q SP, FRAME_R(62), r62
1097 ld.q SP, FRAME_R(15), SP
1102 * Third level handlers for VBR-based exceptions. Adapting args to
1103 * and/or deflecting to fourth level handlers.
1105 * Fourth level handlers interface.
1106 * Most are C-coded handlers directly pointed by the trap_jtable.
1107 * (Third = Fourth level)
1109 * (r2) fault/interrupt code, entry number (e.g. NMI = 14,
1110 * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...)
1111 * (r3) struct pt_regs *, original register's frame pointer
1112 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault)
1113 * (r5) TRA control register (for syscall/debug benefit only)
1114 * (LINK) return address
1117 * Kernel TLB fault handlers will get a slightly different interface.
1118 * (r2) struct pt_regs *, original register's frame pointer
1119 * (r3) writeaccess, whether it's a store fault as opposed to load fault
1120 * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault
1121 * (r5) Effective Address of fault
1122 * (LINK) return address
1125 * fpu_error_or_IRQ? is a helper to deflect to the right cause.
1131 or ZERO, ZERO, r3 /* Read */
1132 or ZERO, ZERO, r4 /* Data */
1134 pta call_do_page_fault, tr0
1139 movi 1, r3 /* Write */
1140 or ZERO, ZERO, r4 /* Data */
1142 pta call_do_page_fault, tr0
1147 beqi/u r4, EVENT_INTERRUPT, tr0
1149 or ZERO, ZERO, r3 /* Read */
1150 movi 1, r4 /* Text */
1155 movi do_page_fault, r6
1158 #endif /* CONFIG_MMU */
1162 beqi/l r4, EVENT_INTERRUPT, tr0
1163 #ifdef CONFIG_SH_FPU
1164 movi do_fpu_state_restore, r6
1166 movi do_exception_error, r6
1173 beqi/l r4, EVENT_INTERRUPT, tr0
1174 #ifdef CONFIG_SH_FPU
1175 movi do_fpu_state_restore, r6
1177 movi do_exception_error, r6
1188 * system_call/unknown_trap third level handler:
1191 * (r2) fault/interrupt code, entry number (TRAP = 11)
1192 * (r3) struct pt_regs *, original register's frame pointer
1193 * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault)
1194 * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr)
1196 * (LINK) return address: ret_from_exception
1197 * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7)
1200 * (*r3) Syscall reply (Saved r2)
1201 * (LINK) In case of syscall only it can be scrapped.
1202 * Common second level post handler will be ret_from_syscall.
1203 * Common (non-trace) exit point to that is syscall_ret (saving
1204 * result to r2). Common bad exit point is syscall_bad (returning
1205 * ENOSYS then saved to r2).
1210 /* Unknown Trap or User Trace */
1211 movi do_unknown_trapa, r6
1213 ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */
1214 andi r2, 0x1ff, r2 /* r2 = syscall # */
1217 pta syscall_ret, tr0
1220 /* New syscall implementation*/
1222 pta unknown_trap, tr0
1223 or r5, ZERO, r4 /* TRA (=r5) -> r4 */
1225 bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */
1227 /* It's a system call */
1228 st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */
1229 andi r5, 0x1ff, r5 /* syscall # -> r5 */
1233 pta syscall_allowed, tr0
1234 movi NR_syscalls - 1, r4 /* Last valid */
1238 /* Return ENOSYS ! */
1239 movi -(ENOSYS), r2 /* Fall-through */
1243 st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */
1245 #ifdef CONFIG_POOR_MANS_STRACE
1246 /* nothing useful in registers at this point */
1251 ld.q SP, FRAME_R(9), r2
1256 ld.q SP, FRAME_S(FSPC), r2
1257 addi r2, 4, r2 /* Move PC, being pre-execution event */
1258 st.q SP, FRAME_S(FSPC), r2
1259 pta ret_from_syscall, tr0
1263 /* A different return path for ret_from_fork, because we now need
1264 * to call schedule_tail with the later kernels. Because prev is
1265 * loaded into r2 by switch_to() means we can just call it straight away
1268 .global ret_from_fork
1271 movi schedule_tail,r5
1276 #ifdef CONFIG_POOR_MANS_STRACE
1277 /* nothing useful in registers at this point */
1282 ld.q SP, FRAME_R(9), r2
1287 ld.q SP, FRAME_S(FSPC), r2
1288 addi r2, 4, r2 /* Move PC, being pre-execution event */
1289 st.q SP, FRAME_S(FSPC), r2
1290 pta ret_from_syscall, tr0
1296 /* Use LINK to deflect the exit point, default is syscall_ret */
1297 pta syscall_ret, tr0
1299 pta syscall_notrace, tr0
1302 ld.l r2, TI_FLAGS, r4
1303 movi _TIF_WORK_SYSCALL_MASK, r6
1307 /* Trace it by calling syscall_trace before and after */
1308 movi do_syscall_trace_enter, r4
1313 /* Save the retval */
1314 st.q SP, FRAME_R(2), r2
1316 /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
1317 ld.q SP, FRAME_S(FSYSCALL_ID), r5
1320 pta syscall_ret_trace, tr0
1324 /* Now point to the appropriate 4th level syscall handler */
1325 movi sys_call_table, r4
1330 /* Prepare original args */
1331 ld.q SP, FRAME_R(2), r2
1332 ld.q SP, FRAME_R(3), r3
1333 ld.q SP, FRAME_R(4), r4
1334 ld.q SP, FRAME_R(5), r5
1335 ld.q SP, FRAME_R(6), r6
1336 ld.q SP, FRAME_R(7), r7
1338 /* And now the trick for those syscalls requiring regs * ! */
1342 blink tr0, ZERO /* LINK is already properly set */
1345 /* We get back here only if under trace */
1346 st.q SP, FRAME_R(9), r2 /* Save return value */
1348 movi do_syscall_trace_leave, LINK
1353 /* This needs to be done after any syscall tracing */
1354 ld.q SP, FRAME_S(FSPC), r2
1355 addi r2, 4, r2 /* Move PC, being pre-execution event */
1356 st.q SP, FRAME_S(FSPC), r2
1358 pta ret_from_syscall, tr0
1359 blink tr0, ZERO /* Resume normal return sequence */
1362 * --- Switch to running under a particular ASID and return the previous ASID value
1363 * --- The caller is assumed to have done a cli before calling this.
1365 * Input r2 : new ASID
1366 * Output r2 : old ASID
1369 .global switch_and_save_asid
1370 switch_and_save_asid:
1373 shlli r4, 16, r4 /* r4 = mask to select ASID */
1374 and r0, r4, r3 /* r3 = shifted old ASID */
1375 andi r2, 255, r2 /* mask down new ASID */
1376 shlli r2, 16, r2 /* align new ASID against SR.ASID */
1377 andc r0, r4, r0 /* efface old ASID from SR */
1378 or r0, r2, r0 /* insert the new ASID */
1386 shlri r3, 16, r2 /* r2 = old ASID */
1389 .global route_to_panic_handler
1390 route_to_panic_handler:
1391 /* Switch to real mode, goto panic_handler, don't return. Useful for
1392 last-chance debugging, e.g. if no output wants to go to the console.
1395 movi panic_handler - CONFIG_PAGE_OFFSET, r1
1407 1: /* Now in real mode */
1411 .global peek_real_address_q
1412 peek_real_address_q:
1414 r2 : real mode address to peek
1415 r2(out) : result quadword
1417 This is provided as a cheapskate way of manipulating device
1418 registers for debugging (to avoid the need to onchip_remap the debug
1419 module, and to avoid the need to onchip_remap the watchpoint
1420 controller in a way that identity maps sufficient bits to avoid the
1421 SH5-101 cut2 silicon defect).
1423 This code is not performance critical
1426 add.l r2, r63, r2 /* sign extend address */
1427 getcon sr, r0 /* r0 = saved original SR */
1430 or r0, r1, r1 /* r0 with block bit set */
1431 putcon r1, sr /* now in critical section */
1434 andc r1, r36, r1 /* turn sr.mmu off in real mode section */
1437 movi .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1438 movi 1f, r37 /* virtual mode return addr */
1445 .peek0: /* come here in real mode, don't touch caches!!
1446 still in critical section (sr.bl==1) */
1449 /* Here's the actual peek. If the address is bad, all bets are now off
1450 * what will happen (handlers invoked in real-mode = bad news) */
1453 rte /* Back to virtual mode */
1460 .global poke_real_address_q
1461 poke_real_address_q:
1463 r2 : real mode address to poke
1464 r3 : quadword value to write.
1466 This is provided as a cheapskate way of manipulating device
1467 registers for debugging (to avoid the need to onchip_remap the debug
1468 module, and to avoid the need to onchip_remap the watchpoint
1469 controller in a way that identity maps sufficient bits to avoid the
1470 SH5-101 cut2 silicon defect).
1472 This code is not performance critical
1475 add.l r2, r63, r2 /* sign extend address */
1476 getcon sr, r0 /* r0 = saved original SR */
1479 or r0, r1, r1 /* r0 with block bit set */
1480 putcon r1, sr /* now in critical section */
1483 andc r1, r36, r1 /* turn sr.mmu off in real mode section */
1486 movi .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1487 movi 1f, r37 /* virtual mode return addr */
1494 .poke0: /* come here in real mode, don't touch caches!!
1495 still in critical section (sr.bl==1) */
1498 /* Here's the actual poke. If the address is bad, all bets are now off
1499 * what will happen (handlers invoked in real-mode = bad news) */
1502 rte /* Back to virtual mode */
1511 * --- User Access Handling Section
1515 * User Access support. It all moved to non inlined Assembler
1516 * functions in here.
1518 * __kernel_size_t __copy_user(void *__to, const void *__from,
1519 * __kernel_size_t __n)
1522 * (r2) target address
1523 * (r3) source address
1524 * (r4) size in bytes
1528 * (r2) non-copied bytes
1530 * If a fault occurs on the user pointer, bail out early and return the
1531 * number of bytes not copied in r2.
1532 * Strategy : for large blocks, call a real memcpy function which can
1533 * move >1 byte at a time using unaligned ld/st instructions, and can
1534 * manipulate the cache using prefetch + alloco to improve the speed
1535 * further. If a fault occurs in that function, just revert to the
1536 * byte-by-byte approach used for small blocks; this is rare so the
1537 * performance hit for that case does not matter.
1539 * For small blocks it's not worth the overhead of setting up and calling
1540 * the memcpy routine; do the copy a byte at a time.
1545 pta __copy_user_byte_by_byte, tr1
1546 movi 16, r0 ! this value is a best guess, should tune it by benchmarking
1548 pta copy_user_memcpy, tr0
1550 /* Save arguments in case we have to fix-up unhandled page fault */
1554 st.q SP, 24, r35 ! r35 is callee-save
1555 /* Save LINK in a register to reduce RTS time later (otherwise
1556 ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */
1560 /* Copy completed normally if we get back here */
1563 /* don't restore r2-r4, pointless */
1564 /* set result=r2 to zero as the copy must have succeeded. */
1567 blink tr0, r63 ! RTS
1569 .global __copy_user_fixup
1571 /* Restore stack frame */
1578 /* Fall through to original code, in the 'same' state we entered with */
1580 /* The slow byte-by-byte method is used if the fast copy traps due to a bad
1581 user address. In that rare case, the speed drop can be tolerated. */
1582 __copy_user_byte_by_byte:
1583 pta ___copy_user_exit, tr1
1584 pta ___copy_user1, tr0
1585 beq/u r4, r63, tr1 /* early exit for zero length copy */
1590 ld.b r3, 0, r5 /* Fault address 1 */
1592 /* Could rewrite this to use just 1 add, but the second comes 'free'
1593 due to load latency */
1595 addi r4, -1, r4 /* No real fixup required */
1597 stx.b r3, r0, r5 /* Fault address 2 */
1606 * __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
1609 * (r2) target address
1610 * (r3) size in bytes
1613 * (*r2) zero-ed target data
1614 * (r2) non-zero-ed bytes
1616 .global __clear_user
1618 pta ___clear_user_exit, tr1
1619 pta ___clear_user1, tr0
1623 st.b r2, 0, ZERO /* Fault address */
1625 addi r3, -1, r3 /* No real fixup required */
1633 #endif /* CONFIG_MMU */
1636 * int __strncpy_from_user(unsigned long __dest, unsigned long __src,
1640 * (r2) target address
1641 * (r3) source address
1642 * (r4) maximum size in bytes
1646 * (r2) -EFAULT (in case of faulting)
1647 * copied data (otherwise)
1649 .global __strncpy_from_user
1650 __strncpy_from_user:
1651 pta ___strncpy_from_user1, tr0
1652 pta ___strncpy_from_user_done, tr1
1653 or r4, ZERO, r5 /* r5 = original count */
1654 beq/u r4, r63, tr1 /* early exit if r4==0 */
1655 movi -(EFAULT), r6 /* r6 = reply, no real fixup */
1656 or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
1658 ___strncpy_from_user1:
1659 ld.b r3, 0, r7 /* Fault address: only in reading */
1664 addi r4, -1, r4 /* return real number of copied bytes */
1667 ___strncpy_from_user_done:
1668 sub r5, r4, r6 /* If done, return copied */
1670 ___strncpy_from_user_exit:
1676 * extern long __strnlen_user(const char *__s, long __n)
1679 * (r2) source address
1680 * (r3) source size in bytes
1683 * (r2) -EFAULT (in case of faulting)
1684 * string length (otherwise)
1686 .global __strnlen_user
1688 pta ___strnlen_user_set_reply, tr0
1689 pta ___strnlen_user1, tr1
1690 or ZERO, ZERO, r5 /* r5 = counter */
1691 movi -(EFAULT), r6 /* r6 = reply, no real fixup */
1692 or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
1696 ldx.b r2, r5, r7 /* Fault address: only in reading */
1697 addi r3, -1, r3 /* No real fixup */
1701 ! The line below used to be active. This meant led to a junk byte lying between each pair
1702 ! of entries in the argv & envp structures in memory. Whilst the program saw the right data
1703 ! via the argv and envp arguments to main, it meant the 'flat' representation visible through
1704 ! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
1705 ! addi r5, 1, r5 /* Include '\0' */
1707 ___strnlen_user_set_reply:
1708 or r5, ZERO, r6 /* If done, return counter */
1710 ___strnlen_user_exit:
1716 * extern long __get_user_asm_?(void *val, long addr)
1720 * (r3) source address (in User Space)
1723 * (r2) -EFAULT (faulting)
1726 .global __get_user_asm_b
1729 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1732 ld.b r3, 0, r5 /* r5 = data */
1736 ___get_user_asm_b_exit:
1741 .global __get_user_asm_w
1744 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1747 ld.w r3, 0, r5 /* r5 = data */
1751 ___get_user_asm_w_exit:
1756 .global __get_user_asm_l
1759 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1762 ld.l r3, 0, r5 /* r5 = data */
1766 ___get_user_asm_l_exit:
1771 .global __get_user_asm_q
1774 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1777 ld.q r3, 0, r5 /* r5 = data */
1781 ___get_user_asm_q_exit:
1786 * extern long __put_user_asm_?(void *pval, long addr)
1789 * (r2) kernel pointer to value
1790 * (r3) dest address (in User Space)
1793 * (r2) -EFAULT (faulting)
1796 .global __put_user_asm_b
1798 ld.b r2, 0, r4 /* r4 = data */
1799 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1805 ___put_user_asm_b_exit:
1810 .global __put_user_asm_w
1812 ld.w r2, 0, r4 /* r4 = data */
1813 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1819 ___put_user_asm_w_exit:
1824 .global __put_user_asm_l
1826 ld.l r2, 0, r4 /* r4 = data */
1827 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1833 ___put_user_asm_l_exit:
1838 .global __put_user_asm_q
1840 ld.q r2, 0, r4 /* r4 = data */
1841 movi -(EFAULT), r2 /* r2 = reply, no real fixup */
1847 ___put_user_asm_q_exit:
1852 /* The idea is : when we get an unhandled panic, we dump the registers
1853 to a known memory location, the just sit in a tight loop.
1854 This allows the human to look at the memory region through the GDB
1855 session (assuming the debug module's SHwy initiator isn't locked up
1856 or anything), to hopefully analyze the cause of the panic. */
1858 /* On entry, former r15 (SP) is in DCR
1859 former r0 is at resvec_saved_area + 0
1860 former r1 is at resvec_saved_area + 8
1861 former tr0 is at resvec_saved_area + 32
1862 DCR is the only register whose value is lost altogether.
1865 movi 0xffffffff80000000, r0 ! phy of dump area
1866 ld.q SP, 0x000, r1 ! former r0
1868 ld.q SP, 0x008, r1 ! former r1
1932 st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake...
1934 ld.q SP, 0x020, r1 ! former tr0
1984 /* Prepare to jump to C - physical address */
1985 movi panic_handler-CONFIG_PAGE_OFFSET, r1
1999 * --- Signal Handling Section
2003 * extern long long _sa_default_rt_restorer
2004 * extern long long _sa_default_restorer
2008 * extern void _sa_default_rt_restorer(void)
2009 * extern void _sa_default_restorer(void)
2011 * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn()
2012 * from user space. Copied into user space by signal management.
2013 * Both must be quad aligned and 2 quad long (4 instructions).
2017 .global sa_default_rt_restorer
2018 sa_default_rt_restorer:
2020 shori __NR_rt_sigreturn, r9
2025 .global sa_default_restorer
2026 sa_default_restorer:
2028 shori __NR_sigreturn, r9
2033 * --- __ex_table Section
2037 * User Access Exception Table.
2039 .section __ex_table, "a"
2041 .global asm_uaccess_start /* Just a marker */
2045 .long ___copy_user1, ___copy_user_exit
2046 .long ___copy_user2, ___copy_user_exit
2047 .long ___clear_user1, ___clear_user_exit
2049 .long ___strncpy_from_user1, ___strncpy_from_user_exit
2050 .long ___strnlen_user1, ___strnlen_user_exit
2051 .long ___get_user_asm_b1, ___get_user_asm_b_exit
2052 .long ___get_user_asm_w1, ___get_user_asm_w_exit
2053 .long ___get_user_asm_l1, ___get_user_asm_l_exit
2054 .long ___get_user_asm_q1, ___get_user_asm_q_exit
2055 .long ___put_user_asm_b1, ___put_user_asm_b_exit
2056 .long ___put_user_asm_w1, ___put_user_asm_w_exit
2057 .long ___put_user_asm_l1, ___put_user_asm_l_exit
2058 .long ___put_user_asm_q1, ___put_user_asm_q_exit
2060 .global asm_uaccess_end /* Just a marker */
2067 * --- .text.init Section
2070 .section .text.init, "ax"
2073 * void trap_init (void)
2078 addi SP, -24, SP /* Room to save r28/r29/r30 */
2083 /* Set VBR and RESVEC */
2084 movi LVBR_block, r19
2085 andi r19, -4, r19 /* reset MMUOFF + reserved */
2086 /* For RESVEC exceptions we force the MMU off, which means we need the
2087 physical address. */
2088 movi LRESVEC_block-CONFIG_PAGE_OFFSET, r20
2089 andi r20, -4, r20 /* reset reserved */
2090 ori r20, 1, r20 /* set MMUOFF */
2095 movi LVBR_block_end, r21
2097 movi BLOCK_SIZE, r29 /* r29 = expected size */
2102 * Ugly, but better loop forever now than crash afterwards.
2103 * We should print a message, but if we touch LVBR or
2104 * LRESVEC blocks we should not be surprised if we get stuck
2107 pta trap_init_loop, tr1
2108 gettr tr1, r28 /* r28 = trap_init_loop */
2109 sub r21, r30, r30 /* r30 = actual size */
2112 * VBR/RESVEC handlers overlap by being bigger than
2113 * allowed. Very bad. Just loop forever.
2114 * (r28) panic/loop address
2115 * (r29) expected size
2121 /* Now that exception vectors are set up reset SR.BL */
2123 movi SR_UNBLOCK_EXC, r23