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