trap_subr64.S revision 95719
195719Sbenno/* $FreeBSD: head/sys/powerpc/aim/trap_subr.S 95719 2002-04-29 12:14:31Z benno $ */
295719Sbenno/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $	*/
395719Sbenno
495719Sbenno/*
595719Sbenno * Copyright (C) 1995, 1996 Wolfgang Solfrank.
695719Sbenno * Copyright (C) 1995, 1996 TooLs GmbH.
795719Sbenno * All rights reserved.
895719Sbenno *
995719Sbenno * Redistribution and use in source and binary forms, with or without
1095719Sbenno * modification, are permitted provided that the following conditions
1195719Sbenno * are met:
1295719Sbenno * 1. Redistributions of source code must retain the above copyright
1395719Sbenno *    notice, this list of conditions and the following disclaimer.
1495719Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1595719Sbenno *    notice, this list of conditions and the following disclaimer in the
1695719Sbenno *    documentation and/or other materials provided with the distribution.
1795719Sbenno * 3. All advertising materials mentioning features or use of this software
1895719Sbenno *    must display the following acknowledgement:
1995719Sbenno *	This product includes software developed by TooLs GmbH.
2095719Sbenno * 4. The name of TooLs GmbH may not be used to endorse or promote products
2195719Sbenno *    derived from this software without specific prior written permission.
2295719Sbenno *
2395719Sbenno * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2495719Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2595719Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2695719Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2795719Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2895719Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2995719Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3095719Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3195719Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3295719Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3395719Sbenno */
3495719Sbenno
3595719Sbenno/*
3695719Sbenno * NOTICE: This is not a standalone file.  to use it, #include it in
3795719Sbenno * your port's locore.S, like so:
3895719Sbenno *
3995719Sbenno *	#include <powerpc/powerpc/trap_subr.S>
4095719Sbenno */
4195719Sbenno
4295719Sbenno/*
4395719Sbenno * XXX Fake AST trap vector.  This is here until we work out how to safely
4495719Sbenno * remove the AST code.
4595719Sbenno */
4695719Sbenno#define	EXC_AST	0x3000
4795719Sbenno	.data
4895719Sbenno	.align	4
4995719Sbennoastpending:
5095719Sbenno	.long	0
5195719Sbenno
5295719Sbenno/*
5395719Sbenno * Data used during primary/secondary traps/interrupts
5495719Sbenno */
5595719Sbenno#define	tempsave	EXC_MCHK+0xe0 /* primary save area for trap handling */
5695719Sbenno#define	disisave	EXC_DSI+0xe0  /* primary save area for dsi/isi traps */
5795719Sbenno
5895719Sbenno/*
5995719Sbenno * XXX Interrupt and spill stacks need to be per-CPU.
6095719Sbenno */
6195719Sbenno	.data
6295719Sbenno	.align	4
6395719Sbennointstk:
6495719Sbenno	.space	INTSTK		/* interrupt stack */
6595719Sbenno
6695719SbennoGLOBAL(intr_depth)
6795719Sbenno	.long	-1		/* in-use marker */
6895719Sbenno
6995719Sbenno	.comm	spillstk,SPILLSTK,8
7095719Sbenno
7195719Sbenno/*
7295719Sbenno * This code gets copied to all the trap vectors
7395719Sbenno * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
7495719Sbenno * traps when using IPKDB).
7595719Sbenno */
7695719Sbenno	.text
7795719Sbenno	.globl	_C_LABEL(trapcode),_C_LABEL(trapsize)
7895719Sbenno_C_LABEL(trapcode):
7995719Sbenno	mtsprg	1,1			/* save SP */
8095719Sbenno	stmw	28,tempsave(0)		/* free r28-r31 */
8195719Sbenno	mflr	28			/* save LR */
8295719Sbenno	mfcr	29			/* save CR */
8395719Sbenno/* Test whether we already had PR set */
8495719Sbenno	mfsrr1	31
8595719Sbenno	mtcr	31
8695719Sbenno	bc	4,17,1f			/* branch if PSL_PR is clear */
8795719Sbenno	mfsprg	31,0
8895719Sbenno	lwz	1,PC_CURPCB(31)
8995719Sbenno	addi	1,1,USPACE		/* stack is top of user struct */
9095719Sbenno1:
9195719Sbenno	bla	s_trap
9295719Sbenno_C_LABEL(trapsize) = .-_C_LABEL(trapcode)
9395719Sbenno
9495719Sbenno/*
9595719Sbenno * For ALI: has to save DSISR and DAR
9695719Sbenno */
9795719Sbenno	.globl	_C_LABEL(alitrap),_C_LABEL(alisize)
9895719Sbenno_C_LABEL(alitrap):
9995719Sbenno	mtsprg	1,1			/* save SP */
10095719Sbenno	stmw	28,tempsave(0)		/* free r28-r31 */
10195719Sbenno	mfdar	30
10295719Sbenno	mfdsisr	31
10395719Sbenno	stmw	30,tempsave+16(0)
10495719Sbenno	mflr	28			/* save LR */
10595719Sbenno	mfcr	29			/* save CR */
10695719Sbenno/* Test whether we already had PR set */
10795719Sbenno	mfsrr1	31
10895719Sbenno	mtcr	31
10995719Sbenno	bc	4,17,1f			/* branch if PSL_PR is clear */
11095719Sbenno	mfsprg	31,0
11195719Sbenno	lwz	1,PC_CURPCB(31)
11295719Sbenno	addi	1,1,USPACE		/* stack is top of user struct */
11395719Sbenno1:
11495719Sbenno	bla	s_trap
11595719Sbenno_C_LABEL(alisize) = .-_C_LABEL(alitrap)
11695719Sbenno
11795719Sbenno/*
11895719Sbenno * Similar to the above for DSI
11995719Sbenno * Has to handle BAT spills
12095719Sbenno * and standard pagetable spills
12195719Sbenno */
12295719Sbenno	.globl	_C_LABEL(dsitrap),_C_LABEL(dsisize)
12395719Sbenno_C_LABEL(dsitrap):
12495719Sbenno	stmw	28,disisave(0)		/* free r28-r31 */
12595719Sbenno	mfcr	29			/* save CR */
12695719Sbenno	mfxer	30			/* save XER */
12795719Sbenno	mtsprg	2,30			/* in SPRG2 */
12895719Sbenno	mfsrr1	31			/* test kernel mode */
12995719Sbenno	mtcr	31
13095719Sbenno	bc	12,17,1f		/* branch if PSL_PR is set */
13195719Sbenno	mfdar	31			/* get fault address */
13295719Sbenno	rlwinm	31,31,7,25,28		/* get segment * 8 */
13395719Sbenno
13495719Sbenno	/* get batu */
13595719Sbenno	addis	31,31,_C_LABEL(battable)@ha
13695719Sbenno	lwz	30,_C_LABEL(battable)@l(31)
13795719Sbenno	mtcr	30
13895719Sbenno	bc	4,30,1f			/* branch if supervisor valid is
13995719Sbenno					   false */
14095719Sbenno	/* get batl */
14195719Sbenno	lwz	31,_C_LABEL(battable)+4@l(31)
14295719Sbenno/* We randomly use the highest two bat registers here */
14395719Sbenno	mftb	28
14495719Sbenno	andi.	28,28,1
14595719Sbenno	bne	2f
14695719Sbenno	mtdbatu	2,30
14795719Sbenno	mtdbatl	2,31
14895719Sbenno	b	3f
14995719Sbenno2:
15095719Sbenno	mtdbatu	3,30
15195719Sbenno	mtdbatl	3,31
15295719Sbenno3:
15395719Sbenno	mfsprg	30,2			/* restore XER */
15495719Sbenno	mtxer	30
15595719Sbenno	mtcr	29			/* restore CR */
15695719Sbenno	lmw	28,disisave(0)		/* restore r28-r31 */
15795719Sbenno	rfi				/* return to trapped code */
15895719Sbenno1:
15995719Sbenno	mflr	28			/* save LR */
16095719Sbenno	bla	s_dsitrap
16195719Sbenno_C_LABEL(dsisize) = .-_C_LABEL(dsitrap)
16295719Sbenno
16395719Sbenno/*
16495719Sbenno * Dedicated MPC601 version of the above.
16595719Sbenno * Considers different BAT format and combined implementation
16695719Sbenno * (being addressed as I-BAT).
16795719Sbenno */
16895719Sbenno	.globl	_C_LABEL(dsitrap601),_C_LABEL(dsi601size)
16995719Sbenno_C_LABEL(dsitrap601):
17095719Sbenno	stmw	28,disisave(0)		/* free r28-r31 */
17195719Sbenno	mfcr	29			/* save CR */
17295719Sbenno	mfxer	30			/* save XER */
17395719Sbenno	mtsprg	2,30			/* in SPRG2 */
17495719Sbenno	mfsrr1	31			/* test kernel mode */
17595719Sbenno	mtcr	31
17695719Sbenno	bc	12,17,1f		/* branch if PSL_PR is set */
17795719Sbenno	mfdar	31			/* get fault address */
17895719Sbenno	rlwinm	31,31,12,20,28		/* get "segment" battable offset */
17995719Sbenno
18095719Sbenno	/* get batl */
18195719Sbenno	addis	31,31,_C_LABEL(battable)@ha
18295719Sbenno	lwz	30,_C_LABEL(battable)+4@l(31)
18395719Sbenno	mtcr	30
18495719Sbenno	bc	4,25,1f			/* branch if Valid is is false,
18595719Sbenno					   presently assumes supervisor only */
18695719Sbenno
18795719Sbenno	/* get batu */
18895719Sbenno	lwz	31,_C_LABEL(battable)@l(31)
18995719Sbenno/* We randomly use the highest two bat registers here */
19095719Sbenno	mfspr	28,SPR_RTCL_R
19195719Sbenno	andi.	28,28,128
19295719Sbenno	bne	2f
19395719Sbenno	mtibatu	2,31
19495719Sbenno	mtibatl	2,30
19595719Sbenno	b	3f
19695719Sbenno2:
19795719Sbenno	mtibatu	3,31
19895719Sbenno	mtibatl	3,30
19995719Sbenno3:
20095719Sbenno	mfsprg	30,2			/* restore XER */
20195719Sbenno	mtxer	30
20295719Sbenno	mtcr	29			/* restore CR */
20395719Sbenno	lmw	28,disisave(0)		/* restore r28-r31 */
20495719Sbenno	rfi				/* return to trapped code */
20595719Sbenno1:
20695719Sbenno	mflr	28			/* save LR */
20795719Sbenno	bla	s_dsitrap
20895719Sbenno_C_LABEL(dsi601size) = .-_C_LABEL(dsitrap601)
20995719Sbenno
21095719Sbenno/*
21195719Sbenno * Similar to the above for ISI
21295719Sbenno */
21395719Sbenno	.globl	_C_LABEL(isitrap),_C_LABEL(isisize)
21495719Sbenno_C_LABEL(isitrap):
21595719Sbenno	stmw	28,disisave(0)		/* free r28-r31 */
21695719Sbenno	mflr	28			/* save LR */
21795719Sbenno	mfcr	29			/* save CR */
21895719Sbenno	mfsrr1	31			/* test kernel mode */
21995719Sbenno	mtcr	31
22095719Sbenno	bc	12,17,1f		/* branch if PSL_PR is set */
22195719Sbenno	mfsrr0	31			/* get fault address */
22295719Sbenno	rlwinm	31,31,7,25,28		/* get segment * 8 */
22395719Sbenno
22495719Sbenno	/* get batu */
22595719Sbenno	addis	31,31,_C_LABEL(battable)@ha
22695719Sbenno	lwz	30,_C_LABEL(battable)@l(31)
22795719Sbenno	mtcr	30
22895719Sbenno	bc	4,30,1f			/* branch if supervisor valid is
22995719Sbenno					   false */
23095719Sbenno	mtibatu	3,30
23195719Sbenno
23295719Sbenno	/* get batl */
23395719Sbenno	lwz	30,_C_LABEL(battable)+4@l(31)
23495719Sbenno	mtibatl	3,30
23595719Sbenno
23695719Sbenno	mtcr	29			/* restore CR */
23795719Sbenno	lmw	28,disisave(0)		/* restore r28-r31 */
23895719Sbenno	rfi				/* return to trapped code */
23995719Sbenno1:
24095719Sbenno	bla	s_isitrap
24195719Sbenno_C_LABEL(isisize)= .-_C_LABEL(isitrap)
24295719Sbenno
24395719Sbenno/*
24495719Sbenno * Dedicated MPC601 version of the above.
24595719Sbenno * Considers different BAT format.
24695719Sbenno */
24795719Sbenno	.globl	_C_LABEL(isitrap601),_C_LABEL(isi601size)
24895719Sbenno_C_LABEL(isitrap601):
24995719Sbenno	stmw	28,disisave(0)		/* free r28-r31 */
25095719Sbenno	mflr	28			/* save LR */
25195719Sbenno	mfcr	29			/* save CR */
25295719Sbenno	mfsrr1	31			/* test kernel mode */
25395719Sbenno	mtcr	31
25495719Sbenno	bc	12,17,1f		/* branch if PSL_PR is set */
25595719Sbenno	mfsrr0	31			/* get fault address */
25695719Sbenno	rlwinm	31,31,12,20,28		/* get "segment" battable offset */
25795719Sbenno
25895719Sbenno	/* get batl */
25995719Sbenno	addis	31,31,_C_LABEL(battable)@ha
26095719Sbenno	lwz	30,_C_LABEL(battable)+4@l(31)
26195719Sbenno	mtcr	30
26295719Sbenno	bc	4,25,1f			/* branch if Valid is is false,
26395719Sbenno					   presently assumes supervisor only */
26495719Sbenno	/* get batu */
26595719Sbenno	lwz	31,_C_LABEL(battable)@l(31)
26695719Sbenno
26795719Sbenno	mtibatu	3,31
26895719Sbenno	mtibatl	3,30
26995719Sbenno
27095719Sbenno	mtcr	29			/* restore CR */
27195719Sbenno	lmw	28,disisave(0)		/* restore r28-r31 */
27295719Sbenno	rfi				/* return to trapped code */
27395719Sbenno1:
27495719Sbenno	bla	s_isitrap
27595719Sbenno_C_LABEL(isi601size)= .-_C_LABEL(isitrap601)
27695719Sbenno
27795719Sbenno/*
27895719Sbenno * This one for the external interrupt handler.
27995719Sbenno */
28095719Sbenno	.globl	_C_LABEL(extint),_C_LABEL(extsize)
28195719Sbenno_C_LABEL(extint):
28295719Sbenno	mtsprg	1,1			/* save SP */
28395719Sbenno	stmw	28,tempsave(0)		/* free r28-r31 */
28495719Sbenno	mflr	28			/* save LR */
28595719Sbenno	mfcr	29			/* save CR */
28695719Sbenno	mfxer	30			/* save XER */
28795719Sbenno	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
28895719Sbenno	addi	1,1,intstk+INTSTK@l	/* this is really intr_depth! */
28995719Sbenno	lwz	31,0(1)			/* were we already running on intstk? */
29095719Sbenno	addic.	31,31,1
29195719Sbenno	stw	31,0(1)
29295719Sbenno	beq	1f
29395719Sbenno	mfsprg	1,1			/* yes, get old SP */
29495719Sbenno1:
29595719Sbenno	ba	extintr
29695719Sbenno_C_LABEL(extsize) = .-_C_LABEL(extint)
29795719Sbenno
29895719Sbenno/*
29995719Sbenno * And this one for the decrementer interrupt handler.
30095719Sbenno */
30195719Sbenno	.globl	_C_LABEL(decrint),_C_LABEL(decrsize)
30295719Sbenno_C_LABEL(decrint):
30395719Sbenno	mtsprg	1,1			/* save SP */
30495719Sbenno	stmw	28,tempsave(0)		/* free r28-r31 */
30595719Sbenno	mflr	28			/* save LR */
30695719Sbenno	mfcr	29			/* save CR */
30795719Sbenno	mfxer	30			/* save XER */
30895719Sbenno	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
30995719Sbenno	addi	1,1,intstk+INTSTK@l
31095719Sbenno	lwz	31,0(1)			/* were we already running on intstk? */
31195719Sbenno	addic.	31,31,1
31295719Sbenno	stw	31,0(1)
31395719Sbenno	beq	1f
31495719Sbenno	mfsprg	1,1			/* yes, get old SP */
31595719Sbenno1:
31695719Sbenno	ba	decrintr
31795719Sbenno_C_LABEL(decrsize) = .-_C_LABEL(decrint)
31895719Sbenno
31995719Sbenno/*
32095719Sbenno * Now the tlb software load for 603 processors:
32195719Sbenno * (Code essentially from the 603e User Manual, Chapter 5, but
32295719Sbenno * corrected a lot.)
32395719Sbenno */
32495719Sbenno
32595719Sbenno	.globl	_C_LABEL(tlbimiss),_C_LABEL(tlbimsize)
32695719Sbenno_C_LABEL(tlbimiss):
32795719Sbenno#ifdef PMAPDEBUG
32895719Sbenno	mfspr	2,SPR_IMISS		/* exception address */
32995719Sbenno	li	1,24			/* get rid of the lower */
33095719Sbenno	srw	2,2,1			/*   24 bits */
33195719Sbenno	li	1,1			/* Load 1 */
33295719Sbenno	cmpl	2,1,1			/* is it > 16MB */
33395719Sbenno	blt	99f			/* nope, skip saving these SPRs */
33495719Sbenno	li	1,0xc0			/* arbitrary */
33595719Sbenno	mfspr	2,SPR_HASH1
33695719Sbenno	stw	2,0(1)
33795719Sbenno	mfspr	2,SPR_HASH2
33895719Sbenno	stw	2,4(1)
33995719Sbenno	mfspr	2,SPR_IMISS
34095719Sbenno	stw	2,8(1)
34195719Sbenno	mfspr	2,SPR_ICMP
34295719Sbenno	stw	2,12(1)
34395719Sbenno99:
34495719Sbenno#endif /* PMAPDEBUG */
34595719Sbenno	mfspr	2,SPR_HASH1		/* get first pointer */
34695719Sbenno	li	1,8
34795719Sbenno	mfctr	0			/* save counter */
34895719Sbenno	mfspr	3,SPR_ICMP		/* get first compare value */
34995719Sbenno	addi	2,2,-8			/* predec pointer */
35095719Sbenno1:
35195719Sbenno	mtctr	1			/* load counter */
35295719Sbenno2:
35395719Sbenno	lwzu	1,8(2)			/* get next pte */
35495719Sbenno	cmpl	0,1,3			/* see if found pte */
35595719Sbenno	bdneq	2b			/* loop if not eq */
35695719Sbenno	bne	3f			/* not found */
35795719Sbenno	lwz	1,4(2)			/* load tlb entry lower word */
35895719Sbenno	andi.	3,1,8			/* check G-bit */
35995719Sbenno	bne	4f			/* if guarded, take ISI */
36095719Sbenno	mtctr	0			/* restore counter */
36195719Sbenno	mfspr	0,SPR_IMISS		/* get the miss address for the tlbli */
36295719Sbenno	mfsrr1	3			/* get the saved cr0 bits */
36395719Sbenno	mtcrf	0x80,3			/* and restore */
36495719Sbenno	ori	1,1,0x100		/* set the reference bit */
36595719Sbenno	mtspr	SPR_RPA,1		/* set the pte */
36695719Sbenno	srwi	1,1,8			/* get byte 7 of pte */
36795719Sbenno	tlbli	0			/* load the itlb */
36895719Sbenno	stb	1,6(2)			/* update page table */
36995719Sbenno	rfi
37095719Sbenno
37195719Sbenno3:	/* not found in pteg */
37295719Sbenno	andi.	1,3,0x40		/* have we already done second hash? */
37395719Sbenno	bne	5f
37495719Sbenno	mfspr	2,SPR_HASH2		/* get the second pointer */
37595719Sbenno	ori	3,3,0x40		/* change the compare value */
37695719Sbenno	li	1,8
37795719Sbenno	addi	2,2,-8			/* predec pointer */
37895719Sbenno	b	1b
37995719Sbenno4:	/* guarded */
38095719Sbenno	mfsrr1	3
38195719Sbenno	andi.	2,3,0xffff		/* clean upper srr1 */
38295719Sbenno	oris	2,2,0x8000000@h		/* set srr<4> to flag prot violation */
38395719Sbenno	b	6f
38495719Sbenno5:	/* not found anywhere */
38595719Sbenno	mfsrr1	3
38695719Sbenno	andi.	2,3,0xffff		/* clean upper srr1 */
38795719Sbenno	oris	2,2,0x40000000@h	/* set srr1<1> to flag pte not found */
38895719Sbenno6:
38995719Sbenno	mtctr	0			/* restore counter */
39095719Sbenno	mtsrr1	2
39195719Sbenno	mfmsr	0
39295719Sbenno	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
39395719Sbenno	mtcrf	0x80,3			/* restore cr0 */
39495719Sbenno	mtmsr	0			/* now with native gprs */
39595719Sbenno	isync
39695719Sbenno	ba	EXC_ISI
39795719Sbenno_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss)
39895719Sbenno
39995719Sbenno	.globl	_C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize)
40095719Sbenno_C_LABEL(tlbdlmiss):
40195719Sbenno	mfspr	2,SPR_HASH1		/* get first pointer */
40295719Sbenno	li	1,8
40395719Sbenno	mfctr	0			/* save counter */
40495719Sbenno	mfspr	3,SPR_DCMP		/* get first compare value */
40595719Sbenno	addi	2,2,-8			/* predec pointer */
40695719Sbenno1:
40795719Sbenno	mtctr	1			/* load counter */
40895719Sbenno2:
40995719Sbenno	lwzu	1,8(2)			/* get next pte */
41095719Sbenno	cmpl	0,1,3			/* see if found pte */
41195719Sbenno	bdneq	2b			/* loop if not eq */
41295719Sbenno	bne	3f			/* not found */
41395719Sbenno	lwz	1,4(2)			/* load tlb entry lower word */
41495719Sbenno	mtctr	0			/* restore counter */
41595719Sbenno	mfspr	0,SPR_DMISS		/* get the miss address for the tlbld */
41695719Sbenno	mfsrr1	3			/* get the saved cr0 bits */
41795719Sbenno	mtcrf	0x80,3			/* and restore */
41895719Sbenno	ori	1,1,0x100		/* set the reference bit */
41995719Sbenno	mtspr	SPR_RPA,1			/* set the pte */
42095719Sbenno	srwi	1,1,8			/* get byte 7 of pte */
42195719Sbenno	tlbld	0			/* load the dtlb */
42295719Sbenno	stb	1,6(2)			/* update page table */
42395719Sbenno	rfi
42495719Sbenno
42595719Sbenno3:	/* not found in pteg */
42695719Sbenno	andi.	1,3,0x40		/* have we already done second hash? */
42795719Sbenno	bne	5f
42895719Sbenno	mfspr	2,SPR_HASH2		/* get the second pointer */
42995719Sbenno	ori	3,3,0x40		/* change the compare value */
43095719Sbenno	li	1,8
43195719Sbenno	addi	2,2,-8			/* predec pointer */
43295719Sbenno	b	1b
43395719Sbenno5:	/* not found anywhere */
43495719Sbenno	mfsrr1	3
43595719Sbenno	lis	1,0x40000000@h		/* set dsisr<1> to flag pte not found */
43695719Sbenno	mtctr	0			/* restore counter */
43795719Sbenno	andi.	2,3,0xffff		/* clean upper srr1 */
43895719Sbenno	mtsrr1	2
43995719Sbenno	mtdsisr	1			/* load the dsisr */
44095719Sbenno	mfspr	1,SPR_DMISS		/* get the miss address */
44195719Sbenno	mtdar	1			/* put in dar */
44295719Sbenno	mfmsr	0
44395719Sbenno	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
44495719Sbenno	mtcrf	0x80,3			/* restore cr0 */
44595719Sbenno	mtmsr	0			/* now with native gprs */
44695719Sbenno	isync
44795719Sbenno	ba	EXC_DSI
44895719Sbenno_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss)
44995719Sbenno
45095719Sbenno	.globl	_C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize)
45195719Sbenno_C_LABEL(tlbdsmiss):
45295719Sbenno	mfspr	2,SPR_HASH1		/* get first pointer */
45395719Sbenno	li	1,8
45495719Sbenno	mfctr	0			/* save counter */
45595719Sbenno	mfspr	3,SPR_DCMP		/* get first compare value */
45695719Sbenno	addi	2,2,-8			/* predec pointer */
45795719Sbenno1:
45895719Sbenno	mtctr	1			/* load counter */
45995719Sbenno2:
46095719Sbenno	lwzu	1,8(2)			/* get next pte */
46195719Sbenno	cmpl	0,1,3			/* see if found pte */
46295719Sbenno	bdneq	2b			/* loop if not eq */
46395719Sbenno	bne	3f			/* not found */
46495719Sbenno	lwz	1,4(2)			/* load tlb entry lower word */
46595719Sbenno	andi.	3,1,0x80		/* check the C-bit */
46695719Sbenno	beq	4f
46795719Sbenno5:
46895719Sbenno	mtctr	0			/* restore counter */
46995719Sbenno	mfspr	0,SPR_DMISS		/* get the miss address for the tlbld */
47095719Sbenno	mfsrr1	3			/* get the saved cr0 bits */
47195719Sbenno	mtcrf	0x80,3			/* and restore */
47295719Sbenno	mtspr	SPR_RPA,1		/* set the pte */
47395719Sbenno	tlbld	0			/* load the dtlb */
47495719Sbenno	rfi
47595719Sbenno
47695719Sbenno3:	/* not found in pteg */
47795719Sbenno	andi.	1,3,0x40		/* have we already done second hash? */
47895719Sbenno	bne	5f
47995719Sbenno	mfspr	2,SPR_HASH2		/* get the second pointer */
48095719Sbenno	ori	3,3,0x40		/* change the compare value */
48195719Sbenno	li	1,8
48295719Sbenno	addi	2,2,-8			/* predec pointer */
48395719Sbenno	b	1b
48495719Sbenno4:	/* found, but C-bit = 0 */
48595719Sbenno	rlwinm.	3,1,30,0,1		/* test PP */
48695719Sbenno	bge-	7f
48795719Sbenno	andi.	3,1,1
48895719Sbenno	beq+	8f
48995719Sbenno9:	/* found, but protection violation (PP==00)*/
49095719Sbenno	mfsrr1	3
49195719Sbenno	lis	1,0xa000000@h		/* indicate protection violation
49295719Sbenno					   on store */
49395719Sbenno	b	1f
49495719Sbenno7:	/* found, PP=1x */
49595719Sbenno	mfspr	3,SPR_DMISS		/* get the miss address */
49695719Sbenno	mfsrin	1,3			/* get the segment register */
49795719Sbenno	mfsrr1	3
49895719Sbenno	rlwinm	3,3,18,31,31		/* get PR-bit */
49995719Sbenno	rlwnm.	2,2,3,1,1		/* get the key */
50095719Sbenno	bne-	9b			/* protection violation */
50195719Sbenno8:	/* found, set reference/change bits */
50295719Sbenno	lwz	1,4(2)			/* reload tlb entry */
50395719Sbenno	ori	1,1,0x180
50495719Sbenno	sth	1,6(2)
50595719Sbenno	b	5b
50695719Sbenno5:	/* not found anywhere */
50795719Sbenno	mfsrr1	3
50895719Sbenno	lis	1,0x42000000@h		/* set dsisr<1> to flag pte not found */
50995719Sbenno					/* dsisr<6> to flag store */
51095719Sbenno1:
51195719Sbenno	mtctr	0			/* restore counter */
51295719Sbenno	andi.	2,3,0xffff		/* clean upper srr1 */
51395719Sbenno	mtsrr1	2
51495719Sbenno	mtdsisr	1			/* load the dsisr */
51595719Sbenno	mfspr	1,SPR_DMISS		/* get the miss address */
51695719Sbenno	mtdar	1			/* put in dar */
51795719Sbenno	mfmsr	0
51895719Sbenno	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
51995719Sbenno	mtcrf	0x80,3			/* restore cr0 */
52095719Sbenno	mtmsr	0			/* now with native gprs */
52195719Sbenno	isync
52295719Sbenno	ba	EXC_DSI
52395719Sbenno_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss)
52495719Sbenno
52595719Sbenno#if defined(DDB) || defined(KGDB)
52695719Sbenno#define	ddbsave	0xde0		/* primary save area for DDB */
52795719Sbenno/*
52895719Sbenno * In case of DDB we want a separate trap catcher for it
52995719Sbenno */
53095719Sbenno	.local	ddbstk
53195719Sbenno	.comm	ddbstk,INTSTK,8		/* ddb stack */
53295719Sbenno
53395719Sbenno	.globl	_C_LABEL(ddblow),_C_LABEL(ddbsize)
53495719Sbenno_C_LABEL(ddblow):
53595719Sbenno	mtsprg	1,1			/* save SP */
53695719Sbenno	stmw	28,ddbsave(0)		/* free r28-r31 */
53795719Sbenno	mflr	28			/* save LR */
53895719Sbenno	mfcr	29			/* save CR */
53995719Sbenno	lis	1,ddbstk+INTSTK@ha	/* get new SP */
54095719Sbenno	addi	1,1,ddbstk+INTSTK@l
54195719Sbenno	bla	ddbtrap
54295719Sbenno_C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
54395719Sbenno#endif	/* DDB | KGDB */
54495719Sbenno
54595719Sbenno#ifdef IPKDB
54695719Sbenno#define	ipkdbsave	0xde0		/* primary save area for IPKDB */
54795719Sbenno/*
54895719Sbenno * In case of IPKDB we want a separate trap catcher for it
54995719Sbenno */
55095719Sbenno
55195719Sbenno	.local	ipkdbstk
55295719Sbenno	.comm	ipkdbstk,INTSTK,8		/* ipkdb stack */
55395719Sbenno
55495719Sbenno	.globl	_C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
55595719Sbenno_C_LABEL(ipkdblow):
55695719Sbenno	mtsprg	1,1			/* save SP */
55795719Sbenno	stmw	28,ipkdbsave(0)		/* free r28-r31 */
55895719Sbenno	mflr	28			/* save LR */
55995719Sbenno	mfcr	29			/* save CR */
56095719Sbenno	lis	1,ipkdbstk+INTSTK@ha	/* get new SP */
56195719Sbenno	addi	1,1,ipkdbstk+INTSTK@l
56295719Sbenno	bla	ipkdbtrap
56395719Sbenno_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
56495719Sbenno#endif	/* IPKDB */
56595719Sbenno
56695719Sbenno/*
56795719Sbenno * FRAME_SETUP assumes:
56895719Sbenno *	SPRG1		SP (1)
56995719Sbenno *	savearea	r28-r31,DAR,DSISR	(DAR & DSISR only for DSI traps)
57095719Sbenno *	28		LR
57195719Sbenno *	29		CR
57295719Sbenno *	1		kernel stack
57395719Sbenno *	LR		trap type
57495719Sbenno *	SRR0/1		as at start of trap
57595719Sbenno */
57695719Sbenno#define	FRAME_SETUP(savearea)						\
57795719Sbenno/* Have to enable translation to allow access of kernel stack: */	\
57895719Sbenno	mfsrr0	30;							\
57995719Sbenno	mfsrr1	31;							\
58095719Sbenno	stmw	30,savearea+24(0);					\
58195719Sbenno	mfmsr	30;							\
58295719Sbenno	ori	30,30,(PSL_DR|PSL_IR);					\
58395719Sbenno	mtmsr	30;							\
58495719Sbenno	isync;								\
58595719Sbenno	mfsprg	31,1;							\
58695719Sbenno	stwu	31,-FRAMELEN(1);					\
58795719Sbenno	stw	0,FRAME_0+8(1);						\
58895719Sbenno	stw	31,FRAME_1+8(1);					\
58995719Sbenno	stw	28,FRAME_LR+8(1);					\
59095719Sbenno	stw	29,FRAME_CR+8(1);					\
59195719Sbenno	lmw	28,savearea(0);						\
59295719Sbenno	stmw	2,FRAME_2+8(1);						\
59395719Sbenno	lmw	28,savearea+16(0);					\
59495719Sbenno	mfxer	3;							\
59595719Sbenno	mfctr	4;							\
59695719Sbenno	mflr	5;							\
59795719Sbenno	andi.	5,5,0xff00;						\
59895719Sbenno	stw	3,FRAME_XER+8(1);					\
59995719Sbenno	stw	4,FRAME_CTR+8(1);					\
60095719Sbenno	stw	5,FRAME_EXC+8(1);					\
60195719Sbenno	stw	28,FRAME_DAR+8(1);					\
60295719Sbenno	stw	29,FRAME_DSISR+8(1);					\
60395719Sbenno	stw	30,FRAME_SRR0+8(1);					\
60495719Sbenno	stw	31,FRAME_SRR1+8(1)
60595719Sbenno
60695719Sbenno#define	FRAME_LEAVE(savearea)						\
60795719Sbenno/* Now restore regs: */							\
60895719Sbenno	lwz	2,FRAME_SRR0+8(1);					\
60995719Sbenno	lwz	3,FRAME_SRR1+8(1);					\
61095719Sbenno	lwz	4,FRAME_CTR+8(1);					\
61195719Sbenno	lwz	5,FRAME_XER+8(1);					\
61295719Sbenno	lwz	6,FRAME_LR+8(1);					\
61395719Sbenno	lwz	7,FRAME_CR+8(1);					\
61495719Sbenno	stw	2,savearea(0);						\
61595719Sbenno	stw	3,savearea+4(0);					\
61695719Sbenno	mtctr	4;							\
61795719Sbenno	mtxer	5;							\
61895719Sbenno	mtlr	6;							\
61995719Sbenno	mtsprg	1,7;			/* save cr */			\
62095719Sbenno	lmw	2,FRAME_2+8(1);						\
62195719Sbenno	lwz	0,FRAME_0+8(1);						\
62295719Sbenno	lwz	1,FRAME_1+8(1);						\
62395719Sbenno	mtsprg	2,2;			/* save r2 & r3 */		\
62495719Sbenno	mtsprg	3,3;							\
62595719Sbenno/* Disable translation, machine check and recoverability: */		\
62695719Sbenno	mfmsr	2;							\
62795719Sbenno	andi.	2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;			\
62895719Sbenno	mtmsr	2;							\
62995719Sbenno	isync;								\
63095719Sbenno/* Decide whether we return to user mode: */				\
63195719Sbenno	lwz	3,savearea+4(0);					\
63295719Sbenno	mtcr	3;							\
63395719Sbenno	bc	4,17,1f;		/* branch if PSL_PR is false */	\
63495719Sbenno/* Restore user & kernel access SR: */					\
63595719Sbenno	mfsprg	2,0;							\
63695719Sbenno	lwz	2,PC_CURPMAP(2);					\
63795719Sbenno	lwz	3,PM_SR+0(2);						\
63895719Sbenno	mtsr	0,3;			/* restore SR0 */		\
63995719Sbenno	lwz	3,PM_SR+4(2);						\
64095719Sbenno	mtsr	1,3;			/* restore SR1 */		\
64195719Sbenno	lwz	3,PM_SR+8(2);						\
64295719Sbenno	mtsr	2,3;			/* restore SR2 */		\
64395719Sbenno	lwz	3,PM_SR+12(2);						\
64495719Sbenno	mtsr	3,3;			/* restore SR3 */		\
64595719Sbenno	lwz	3,PM_SR+16(2);						\
64695719Sbenno	mtsr	4,3;			/* restore SR4 */		\
64795719Sbenno	lwz	3,PM_SR+20(2);						\
64895719Sbenno	mtsr	5,3;			/* restore SR5 */		\
64995719Sbenno	lwz	3,PM_SR+24(2);						\
65095719Sbenno	mtsr	6,3;			/* restore SR6 */		\
65195719Sbenno	lwz	3,PM_SR+28(2);						\
65295719Sbenno	mtsr	7,3;			/* restore SR7 */		\
65395719Sbenno	lwz	3,PM_USRSR(2);						\
65495719Sbenno	mtsr	USER_SR,3;						\
65595719Sbenno	lwz	3,PM_KERNELSR(2);					\
65695719Sbenno	mtsr	KERNEL_SR,3;						\
65795719Sbenno1:	mfsprg	2,1;			/* restore cr */		\
65895719Sbenno	mtcr	2;							\
65995719Sbenno	lwz	2,savearea(0);						\
66095719Sbenno	lwz	3,savearea+4(0);					\
66195719Sbenno	mtsrr0	2;							\
66295719Sbenno	mtsrr1	3;							\
66395719Sbenno	mfsprg	2,2;			/* restore r2 & r3 */		\
66495719Sbenno	mfsprg	3,3
66595719Sbenno
66695719Sbenno/*
66795719Sbenno * Preamble code for DSI/ISI traps
66895719Sbenno */
66995719Sbennodisitrap:
67095719Sbenno	lmw	30,disisave(0)
67195719Sbenno	stmw	30,tempsave(0)
67295719Sbenno	lmw	30,disisave+8(0)
67395719Sbenno	stmw	30,tempsave+8(0)
67495719Sbenno	mfdar	30
67595719Sbenno	mfdsisr	31
67695719Sbenno	stmw	30,tempsave+16(0)
67795719Sbennorealtrap:
67895719Sbenno/* Test whether we already had PR set */
67995719Sbenno	mfsrr1	1
68095719Sbenno	mtcr	1
68195719Sbenno	mfsprg	1,1			/* restore SP (might have been
68295719Sbenno					   overwritten) */
68395719Sbenno	bc	4,17,s_trap		/* branch if PSL_PR is false */
68495719Sbenno	mfsprg	31,0
68595719Sbenno	lwz	1,PC_CURPCB(31)
68695719Sbenno	addi	1,1,USPACE		/* stack is top of user struct */
68795719Sbenno
68895719Sbenno/*
68995719Sbenno * Now the common trap catching code.
69095719Sbenno */
69195719Sbennos_trap:
69295719Sbenno/* First have to enable KERNEL mapping */
69395719Sbenno	lis	31,KERNEL_SEGMENT@h
69495719Sbenno	ori	31,31,KERNEL_SEGMENT@l
69595719Sbenno	mtsr	KERNEL_SR,31
69695719Sbenno/* Obliterate SRs so BAT spills work correctly */
69795719Sbenno	lis	31,EMPTY_SEGMENT@h
69895719Sbenno	ori	31,31,EMPTY_SEGMENT@l
69995719Sbenno	mtsr	0,31
70095719Sbenno	mtsr	1,31
70195719Sbenno	mtsr	2,31
70295719Sbenno	mtsr	3,31
70395719Sbenno	mtsr	4,31
70495719Sbenno	mtsr	5,31
70595719Sbenno	mtsr	6,31
70695719Sbenno	mtsr	7,31
70795719Sbenno	FRAME_SETUP(tempsave)
70895719Sbenno/* Now we can recover interrupts again: */
70995719Sbenno	mfmsr	7
71095719Sbenno	ori	7,7,(PSL_EE|PSL_ME|PSL_RI)@l
71195719Sbenno	mtmsr	7
71295719Sbenno	isync
71395719Sbenno/* Call C trap code: */
71495719Sbennotrapagain:
71595719Sbenno	addi	3,1,8
71695719Sbenno	bl	_C_LABEL(trap)
71795719Sbenno	.globl	_C_LABEL(trapexit)
71895719Sbenno_C_LABEL(trapexit):
71995719Sbenno/* Disable interrupts: */
72095719Sbenno	mfmsr	3
72195719Sbenno	andi.	3,3,~PSL_EE@l
72295719Sbenno	mtmsr	3
72395719Sbenno/* Test AST pending: */
72495719Sbenno	lwz	5,FRAME_SRR1+8(1)
72595719Sbenno	mtcr	5
72695719Sbenno	bc	4,17,1f			/* branch if PSL_PR is false */
72795719Sbenno	lis	3,_C_LABEL(astpending)@ha
72895719Sbenno	lwz	4,_C_LABEL(astpending)@l(3)
72995719Sbenno	andi.	4,4,1
73095719Sbenno	beq	1f
73195719Sbenno	li	6,EXC_AST
73295719Sbenno	stw	6,FRAME_EXC+8(1)
73395719Sbenno	b	trapagain
73495719Sbenno1:
73595719Sbenno	FRAME_LEAVE(tempsave)
73695719Sbenno	rfi
73795719Sbenno
73895719Sbenno/*
73995719Sbenno * DSI second stage fault handler
74095719Sbenno */
74195719Sbennos_dsitrap:
74295719Sbenno	mfdsisr	31			/* test whether this may be a
74395719Sbenno					   spill fault */
74495719Sbenno	mtcr	31
74595719Sbenno	mtsprg	1,1			/* save SP */
74695719Sbenno	bc	4,1,disitrap		/* branch if table miss is false */
74795719Sbenno	lis	1,spillstk+SPILLSTK@ha
74895719Sbenno	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
74995719Sbenno	stwu	1,-SPFRAMELEN(1)
75095719Sbenno	stw	0,SPFRAME_R0(1)		/* save non-volatile registers */
75195719Sbenno	stw	3,SPFRAME_R3(1)
75295719Sbenno	stw	4,SPFRAME_R4(1)
75395719Sbenno	stw	5,SPFRAME_R5(1)
75495719Sbenno	stw	6,SPFRAME_R6(1)
75595719Sbenno	stw	7,SPFRAME_R7(1)
75695719Sbenno	stw	8,SPFRAME_R8(1)
75795719Sbenno	stw	9,SPFRAME_R9(1)
75895719Sbenno	stw	10,SPFRAME_R10(1)
75995719Sbenno	stw	11,SPFRAME_R11(1)
76095719Sbenno	stw	12,SPFRAME_R12(1)
76195719Sbenno	mflr	30			/* save trap type */
76295719Sbenno	mfctr	31			/* & CTR */
76395719Sbenno	mfdar	3
76495719Sbennos_pte_spill:
76595719Sbenno	bl	_C_LABEL(pmap_pte_spill)	/* try a spill */
76695719Sbenno	or.	3,3,3
76795719Sbenno	mtctr	31			/* restore CTR */
76895719Sbenno	mtlr	30			/* and trap type */
76995719Sbenno	mfsprg	31,2			/* get saved XER */
77095719Sbenno	mtxer	31			/* restore XER */
77195719Sbenno	lwz	12,SPFRAME_R12(1)	/* restore non-volatile registers */
77295719Sbenno	lwz	11,SPFRAME_R11(1)
77395719Sbenno	lwz	10,SPFRAME_R10(1)
77495719Sbenno	lwz	9,SPFRAME_R9(1)
77595719Sbenno	lwz	8,SPFRAME_R8(1)
77695719Sbenno	lwz	7,SPFRAME_R7(1)
77795719Sbenno	lwz	6,SPFRAME_R6(1)
77895719Sbenno	lwz	5,SPFRAME_R5(1)
77995719Sbenno	lwz	4,SPFRAME_R4(1)
78095719Sbenno	lwz	3,SPFRAME_R3(1)
78195719Sbenno	lwz	0,SPFRAME_R0(1)
78295719Sbenno	beq	disitrap
78395719Sbenno	mfsprg	1,1			/* restore SP */
78495719Sbenno	mtcr	29			/* restore CR */
78595719Sbenno	mtlr	28			/* restore LR */
78695719Sbenno	lmw	28,disisave(0)		/* restore r28-r31 */
78795719Sbenno	rfi				/* return to trapped code */
78895719Sbenno
78995719Sbenno/*
79095719Sbenno * ISI second stage fault handler
79195719Sbenno */
79295719Sbennos_isitrap:
79395719Sbenno	mfsrr1	31			/* test whether this may be a
79495719Sbenno					   spill fault */
79595719Sbenno	mtcr	31
79695719Sbenno	mtsprg	1,1			/* save SP */
79795719Sbenno	bc	4,1,disitrap		/* branch if table miss is false */
79895719Sbenno	lis	1,spillstk+SPILLSTK@ha
79995719Sbenno	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
80095719Sbenno	stwu	1,-SPFRAMELEN(1)
80195719Sbenno	stw	0,SPFRAME_R0(1)		/* save non-volatile registers */
80295719Sbenno	stw	3,SPFRAME_R3(1)
80395719Sbenno	stw	4,SPFRAME_R4(1)
80495719Sbenno	stw	5,SPFRAME_R5(1)
80595719Sbenno	stw	6,SPFRAME_R6(1)
80695719Sbenno	stw	7,SPFRAME_R7(1)
80795719Sbenno	stw	8,SPFRAME_R8(1)
80895719Sbenno	stw	9,SPFRAME_R9(1)
80995719Sbenno	stw	10,SPFRAME_R10(1)
81095719Sbenno	stw	11,SPFRAME_R11(1)
81195719Sbenno	stw	12,SPFRAME_R12(1)
81295719Sbenno	mfxer	30			/* save XER */
81395719Sbenno	mtsprg	2,30
81495719Sbenno	mflr	30			/* save trap type */
81595719Sbenno	mfctr	31			/* & ctr */
81695719Sbenno	mfsrr0	3
81795719Sbenno	b	s_pte_spill		/* above */
81895719Sbenno
81995719Sbenno/*
82095719Sbenno * External interrupt second level handler
82195719Sbenno */
82295719Sbenno#define	INTRENTER							\
82395719Sbenno/* Save non-volatile registers: */					\
82495719Sbenno	stwu	1,-IFRAMELEN(1);	/* temporarily */		\
82595719Sbenno	stw	0,IFRAME_R0(1);						\
82695719Sbenno	mfsprg	0,1;			/* get original SP */		\
82795719Sbenno	stw	0,IFRAME_R1(1);		/* and store it */		\
82895719Sbenno	stw	3,IFRAME_R3(1);						\
82995719Sbenno	stw	4,IFRAME_R4(1);						\
83095719Sbenno	stw	5,IFRAME_R5(1);						\
83195719Sbenno	stw	6,IFRAME_R6(1);						\
83295719Sbenno	stw	7,IFRAME_R7(1);						\
83395719Sbenno	stw	8,IFRAME_R8(1);						\
83495719Sbenno	stw	9,IFRAME_R9(1);						\
83595719Sbenno	stw	10,IFRAME_R10(1);					\
83695719Sbenno	stw	11,IFRAME_R11(1);					\
83795719Sbenno	stw	12,IFRAME_R12(1);					\
83895719Sbenno	stw	28,IFRAME_LR(1);	/* saved LR */			\
83995719Sbenno	stw	29,IFRAME_CR(1);	/* saved CR */			\
84095719Sbenno	stw	30,IFRAME_XER(1);	/* saved XER */			\
84195719Sbenno	lmw	28,tempsave(0);		/* restore r28-r31 */		\
84295719Sbenno	mfctr	6;							\
84395719Sbenno	lis	5,_C_LABEL(intr_depth)@ha;				\
84495719Sbenno	lwz	5,_C_LABEL(intr_depth)@l(5);				\
84595719Sbenno	mfsrr0	4;							\
84695719Sbenno	mfsrr1	3;							\
84795719Sbenno	stw	6,IFRAME_CTR(1);					\
84895719Sbenno	stw	5,IFRAME_INTR_DEPTH(1);					\
84995719Sbenno	stw	4,IFRAME_SRR0(1);					\
85095719Sbenno	stw	3,IFRAME_SRR1(1);					\
85195719Sbenno	mtcr	3;							\
85295719Sbenno	bc	4,17,99f;	/* branch if PSL_PR is false */		\
85395719Sbenno	lis	3,EMPTY_SEGMENT@h;					\
85495719Sbenno	ori	3,3,EMPTY_SEGMENT@l;					\
85595719Sbenno	mtsr	0,3;		/* reset SRs so BAT spills work */	\
85695719Sbenno	mtsr	1,3;							\
85795719Sbenno	mtsr	2,3;							\
85895719Sbenno	mtsr	3,3;							\
85995719Sbenno	mtsr	4,3;							\
86095719Sbenno	mtsr	5,3;							\
86195719Sbenno	mtsr	6,3;							\
86295719Sbenno	mtsr	7,3;							\
86395719Sbenno/* interrupts are recoverable here, and enable translation */		\
86495719Sbenno	lis	3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h;			\
86595719Sbenno	ori	3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l;			\
86695719Sbenno	mtsr	KERNEL_SR,3;						\
86795719Sbenno99:	mfmsr	5;							\
86895719Sbenno	ori	5,5,(PSL_IR|PSL_DR|PSL_RI);				\
86995719Sbenno	mtmsr	5;							\
87095719Sbenno	isync
87195719Sbenno
87295719Sbenno	.globl	_C_LABEL(extint_call)
87395719Sbennoextintr:
87495719Sbenno	INTRENTER
87595719Sbenno_C_LABEL(extint_call):
87695719Sbenno	bl	_C_LABEL(extint_call)	/* to be filled in later */
87795719Sbenno
87895719Sbennointr_exit:
87995719Sbenno/* Disable interrupts (should already be disabled) and MMU here: */
88095719Sbenno	mfmsr	3
88195719Sbenno	andi.	3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
88295719Sbenno	mtmsr	3
88395719Sbenno	isync
88495719Sbenno/* restore possibly overwritten registers: */
88595719Sbenno	lwz	12,IFRAME_R12(1)
88695719Sbenno	lwz	11,IFRAME_R11(1)
88795719Sbenno	lwz	10,IFRAME_R10(1)
88895719Sbenno	lwz	9,IFRAME_R9(1)
88995719Sbenno	lwz	8,IFRAME_R8(1)
89095719Sbenno	lwz	7,IFRAME_R7(1)
89195719Sbenno	lwz	6,IFRAME_SRR1(1)
89295719Sbenno	lwz	5,IFRAME_SRR0(1)
89395719Sbenno	lwz	4,IFRAME_CTR(1)
89495719Sbenno	lwz	3,IFRAME_XER(1)
89595719Sbenno	mtsrr1	6
89695719Sbenno	mtsrr0	5
89795719Sbenno	mtctr	4
89895719Sbenno	mtxer	3
89995719Sbenno/* Returning to user mode? */
90095719Sbenno	mtcr	6			/* saved SRR1 */
90195719Sbenno	bc	4,17,1f			/* branch if PSL_PR is false */
90295719Sbenno	mfsprg	31,0
90395719Sbenno	lwz	3,PC_CURPMAP(31)
90495719Sbenno	lwz	4,PM_SR+0(3)
90595719Sbenno	mtsr	0,4			/* Restore SR0 */
90695719Sbenno	lwz	4,PM_SR+4(3)
90795719Sbenno	mtsr	1,4			/* Restore SR1 */
90895719Sbenno	lwz	4,PM_SR+8(3)
90995719Sbenno	mtsr	2,4			/* Restore SR2 */
91095719Sbenno	lwz	4,PM_SR+12(3)
91195719Sbenno	mtsr	3,4			/* Restore SR3 */
91295719Sbenno	lwz	4,PM_SR+16(3)
91395719Sbenno	mtsr	4,4			/* Restore SR4 */
91495719Sbenno	lwz	4,PM_SR+20(3)
91595719Sbenno	mtsr	5,4			/* Restore SR5 */
91695719Sbenno	lwz	4,PM_SR+24(3)
91795719Sbenno	mtsr	6,4			/* Restore SR6 */
91895719Sbenno	lwz	4,PM_SR+28(3)
91995719Sbenno	mtsr	7,4			/* Restore SR7 */
92095719Sbenno	lwz	3,PM_KERNELSR(3)
92195719Sbenno	mtsr	KERNEL_SR,3		/* Restore kernel SR */
92295719Sbenno	lis	3,_C_LABEL(astpending)@ha /* Test AST pending */
92395719Sbenno	lwz	4,_C_LABEL(astpending)@l(3)
92495719Sbenno	andi.	4,4,1
92595719Sbenno	beq	1f
92695719Sbenno/* Setup for entry to realtrap: */
92795719Sbenno	lwz	3,IFRAME_R1(1)		/* get saved SP */
92895719Sbenno	mtsprg	1,3
92995719Sbenno	li	6,EXC_AST
93095719Sbenno	stmw	28,tempsave(0)		/* establish tempsave again */
93195719Sbenno	mtlr	6
93295719Sbenno	lwz	28,IFRAME_LR(1)		/* saved LR */
93395719Sbenno	lwz	29,IFRAME_CR(1)		/* saved CR */
93495719Sbenno	lwz	6,IFRAME_R6(1)
93595719Sbenno	lwz	5,IFRAME_R5(1)
93695719Sbenno	lwz	4,IFRAME_R4(1)
93795719Sbenno	lwz	3,IFRAME_R3(1)
93895719Sbenno	lwz	0,IFRAME_R0(1)
93995719Sbenno	lis	30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
94095719Sbenno	lwz	31,_C_LABEL(intr_depth)@l(30)
94195719Sbenno	addi	31,31,-1
94295719Sbenno	stw	31,_C_LABEL(intr_depth)@l(30)
94395719Sbenno	b	realtrap
94495719Sbenno1:
94595719Sbenno/* Here is the normal exit of extintr: */
94695719Sbenno	lwz	5,IFRAME_CR(1)
94795719Sbenno	lwz	6,IFRAME_LR(1)
94895719Sbenno	mtcr	5
94995719Sbenno	mtlr	6
95095719Sbenno	lwz	6,IFRAME_R6(1)
95195719Sbenno	lwz	5,IFRAME_R5(1)
95295719Sbenno	lis	3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
95395719Sbenno	lwz	4,_C_LABEL(intr_depth)@l(3)
95495719Sbenno	addi	4,4,-1
95595719Sbenno	stw	4,_C_LABEL(intr_depth)@l(3)
95695719Sbenno	lwz	4,IFRAME_R4(1)
95795719Sbenno	lwz	3,IFRAME_R3(1)
95895719Sbenno	lwz	0,IFRAME_R0(1)
95995719Sbenno	lwz	1,IFRAME_R1(1)
96095719Sbenno	rfi
96195719Sbenno
96295719Sbenno/*
96395719Sbenno * Decrementer interrupt second level handler
96495719Sbenno */
96595719Sbennodecrintr:
96695719Sbenno	INTRENTER
96795719Sbenno	addi	3,1,8			/* intr frame -> clock frame */
96895719Sbenno	bl	_C_LABEL(decr_intr)
96995719Sbenno	b	intr_exit
97095719Sbenno
97195719Sbenno#if defined(DDB)
97295719Sbenno/*
97395719Sbenno * Deliberate entry to ddbtrap
97495719Sbenno */
97595719Sbenno	.globl	_C_LABEL(ddb_trap)
97695719Sbenno_C_LABEL(ddb_trap):
97795719Sbenno	mtsprg	1,1
97895719Sbenno	mfmsr	3
97995719Sbenno	mtsrr1	3
98095719Sbenno	andi.	3,3,~(PSL_EE|PSL_ME)@l
98195719Sbenno	mtmsr	3			/* disable interrupts */
98295719Sbenno	isync
98395719Sbenno	stmw	28,ddbsave(0)
98495719Sbenno	mflr	28
98595719Sbenno	li	29,EXC_BPT
98695719Sbenno	mtlr	29
98795719Sbenno	mfcr	29
98895719Sbenno	mtsrr0	28
98995719Sbenno#endif /* DDB */
99095719Sbenno
99195719Sbenno#if defined(DDB) || defined(KGDB)
99295719Sbenno/*
99395719Sbenno * Now the ddb trap catching code.
99495719Sbenno */
99595719Sbennoddbtrap:
99695719Sbenno	FRAME_SETUP(ddbsave)
99795719Sbenno/* Call C trap code: */
99895719Sbenno	addi	3,1,8
99995719Sbenno	bl	_C_LABEL(ddb_trap_glue)
100095719Sbenno	or.	3,3,3
100195719Sbenno	bne	ddbleave
100295719Sbenno/* This wasn't for DDB, so switch to real trap: */
100395719Sbenno	lwz	3,FRAME_EXC+8(1)	/* save exception */
100495719Sbenno	stw	3,ddbsave+8(0)
100595719Sbenno	FRAME_LEAVE(ddbsave)
100695719Sbenno	mtsprg	1,1			/* prepare for entrance to realtrap */
100795719Sbenno	stmw	28,tempsave(0)
100895719Sbenno	mflr	28
100995719Sbenno	mfcr	29
101095719Sbenno	lwz	31,ddbsave+8(0)
101195719Sbenno	mtlr	31
101295719Sbenno	b	realtrap
101395719Sbennoddbleave:
101495719Sbenno	FRAME_LEAVE(ddbsave)
101595719Sbenno	rfi
101695719Sbenno#endif /* DDB || KGDB */
101795719Sbenno
101895719Sbenno#ifdef IPKDB
101995719Sbenno/*
102095719Sbenno * Deliberate entry to ipkdbtrap
102195719Sbenno */
102295719Sbenno	.globl	_C_LABEL(ipkdb_trap)
102395719Sbenno_C_LABEL(ipkdb_trap):
102495719Sbenno	mtsprg	1,1
102595719Sbenno	mfmsr	3
102695719Sbenno	mtsrr1	3
102795719Sbenno	andi.	3,3,~(PSL_EE|PSL_ME)@l
102895719Sbenno	mtmsr	3			/* disable interrupts */
102995719Sbenno	isync
103095719Sbenno	stmw	28,ipkdbsave(0)
103195719Sbenno	mflr	28
103295719Sbenno	li	29,EXC_BPT
103395719Sbenno	mtlr	29
103495719Sbenno	mfcr	29
103595719Sbenno	mtsrr0	28
103695719Sbenno
103795719Sbenno/*
103895719Sbenno * Now the ipkdb trap catching code.
103995719Sbenno */
104095719Sbennoipkdbtrap:
104195719Sbenno	FRAME_SETUP(ipkdbsave)
104295719Sbenno/* Call C trap code: */
104395719Sbenno	addi	3,1,8
104495719Sbenno	bl	_C_LABEL(ipkdb_trap_glue)
104595719Sbenno	or.	3,3,3
104695719Sbenno	bne	ipkdbleave
104795719Sbenno/* This wasn't for IPKDB, so switch to real trap: */
104895719Sbenno	lwz	3,FRAME_EXC+8(1)	/* save exception */
104995719Sbenno	stw	3,ipkdbsave+8(0)
105095719Sbenno	FRAME_LEAVE(ipkdbsave)
105195719Sbenno	mtsprg	1,1			/* prepare for entrance to realtrap */
105295719Sbenno	stmw	28,tempsave(0)
105395719Sbenno	mflr	28
105495719Sbenno	mfcr	29
105595719Sbenno	lwz	31,ipkdbsave+8(0)
105695719Sbenno	mtlr	31
105795719Sbenno	b	realtrap
105895719Sbennoipkdbleave:
105995719Sbenno	FRAME_LEAVE(ipkdbsave)
106095719Sbenno	rfi
106195719Sbenno
106295719Sbennoipkdbfault:
106395719Sbenno	ba	_ipkdbfault
106495719Sbenno_ipkdbfault:
106595719Sbenno	mfsrr0	3
106695719Sbenno	addi	3,3,4
106795719Sbenno	mtsrr0	3
106895719Sbenno	li	3,-1
106995719Sbenno	rfi
107095719Sbenno
107195719Sbenno/*
107295719Sbenno * int ipkdbfbyte(unsigned char *p)
107395719Sbenno */
107495719Sbenno	.globl	_C_LABEL(ipkdbfbyte)
107595719Sbenno_C_LABEL(ipkdbfbyte):
107695719Sbenno	li	9,EXC_DSI		/* establish new fault routine */
107795719Sbenno	lwz	5,0(9)
107895719Sbenno	lis	6,ipkdbfault@ha
107995719Sbenno	lwz	6,ipkdbfault@l(6)
108095719Sbenno	stw	6,0(9)
108195719Sbenno#ifdef	IPKDBUSERHACK
108295719Sbenno	lis	8,_C_LABEL(ipkdbsr)@ha
108395719Sbenno	lwz	8,_C_LABEL(ipkdbsr)@l(8)
108495719Sbenno	mtsr	USER_SR,8
108595719Sbenno	isync
108695719Sbenno#endif
108795719Sbenno	dcbst	0,9			/* flush data... */
108895719Sbenno	sync
108995719Sbenno	icbi	0,9			/* and instruction caches */
109095719Sbenno	lbz	3,0(3)			/* fetch data */
109195719Sbenno	stw	5,0(9)			/* restore previous fault handler */
109295719Sbenno	dcbst	0,9			/* and flush data... */
109395719Sbenno	sync
109495719Sbenno	icbi	0,9			/* and instruction caches */
109595719Sbenno	blr
109695719Sbenno
109795719Sbenno/*
109895719Sbenno * int ipkdbsbyte(unsigned char *p, int c)
109995719Sbenno */
110095719Sbenno	.globl	_C_LABEL(ipkdbsbyte)
110195719Sbenno_C_LABEL(ipkdbsbyte):
110295719Sbenno	li	9,EXC_DSI		/* establish new fault routine */
110395719Sbenno	lwz	5,0(9)
110495719Sbenno	lis	6,ipkdbfault@ha
110595719Sbenno	lwz	6,ipkdbfault@l(6)
110695719Sbenno	stw	6,0(9)
110795719Sbenno#ifdef	IPKDBUSERHACK
110895719Sbenno	lis	8,_C_LABEL(ipkdbsr)@ha
110995719Sbenno	lwz	8,_C_LABEL(ipkdbsr)@l(8)
111095719Sbenno	mtsr	USER_SR,8
111195719Sbenno	isync
111295719Sbenno#endif
111395719Sbenno	dcbst	0,9			/* flush data... */
111495719Sbenno	sync
111595719Sbenno	icbi	0,9			/* and instruction caches */
111695719Sbenno	mr	6,3
111795719Sbenno	xor	3,3,3
111895719Sbenno	stb	4,0(6)
111995719Sbenno	dcbst	0,6			/* Now do appropriate flushes
112095719Sbenno					   to data... */
112195719Sbenno	sync
112295719Sbenno	icbi	0,6			/* and instruction caches */
112395719Sbenno	stw	5,0(9)			/* restore previous fault handler */
112495719Sbenno	dcbst	0,9			/* and flush data... */
112595719Sbenno	sync
112695719Sbenno	icbi	0,9			/* and instruction caches */
112795719Sbenno	blr
112895719Sbenno#endif	/* IPKDB */
1129