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