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