Linux Audio

Check our new training course

Yocto distribution development and maintenance

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