xref: /openbmc/linux/arch/powerpc/kernel/exceptions-64e.S (revision 2d78eb0342dd2c9c5cde9ae9ada1d33f189a858b)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
22d27cfd3SBenjamin Herrenschmidt/*
32d27cfd3SBenjamin Herrenschmidt *  Boot code and exception vectors for Book3E processors
42d27cfd3SBenjamin Herrenschmidt *
52d27cfd3SBenjamin Herrenschmidt *  Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp.
62d27cfd3SBenjamin Herrenschmidt */
72d27cfd3SBenjamin Herrenschmidt
82d27cfd3SBenjamin Herrenschmidt#include <linux/linkage.h>
92d27cfd3SBenjamin Herrenschmidt#include <linux/threads.h>
102d27cfd3SBenjamin Herrenschmidt#include <asm/reg.h>
112d27cfd3SBenjamin Herrenschmidt#include <asm/page.h>
122d27cfd3SBenjamin Herrenschmidt#include <asm/ppc_asm.h>
132d27cfd3SBenjamin Herrenschmidt#include <asm/asm-offsets.h>
142d27cfd3SBenjamin Herrenschmidt#include <asm/cputable.h>
152d27cfd3SBenjamin Herrenschmidt#include <asm/setup.h>
16a0496d45SJack Miller#include <asm/thread_info.h>
172d27cfd3SBenjamin Herrenschmidt#include <asm/reg_a2.h>
182d27cfd3SBenjamin Herrenschmidt#include <asm/exception-64e.h>
192d27cfd3SBenjamin Herrenschmidt#include <asm/bug.h>
202d27cfd3SBenjamin Herrenschmidt#include <asm/irqflags.h>
212d27cfd3SBenjamin Herrenschmidt#include <asm/ptrace.h>
222d27cfd3SBenjamin Herrenschmidt#include <asm/ppc-opcode.h>
237230c564SBenjamin Herrenschmidt#include <asm/mmu.h>
24fecff0f7SMihai Caraman#include <asm/hw_irq.h>
25fecff0f7SMihai Caraman#include <asm/kvm_asm.h>
262c86cd18SChristophe Leroy#include <asm/kvm_booke_hv_asm.h>
276cc0c16dSNicholas Piggin#include <asm/feature-fixups.h>
282d27cfd3SBenjamin Herrenschmidt#include <asm/context_tracking.h>
291df7d5e4SNicholas Piggin
301df7d5e4SNicholas Piggin/* 64e interrupt returns always use SRR registers */
311df7d5e4SNicholas Piggin#define fast_interrupt_return fast_interrupt_return_srr
321df7d5e4SNicholas Piggin#define interrupt_return interrupt_return_srr
332d27cfd3SBenjamin Herrenschmidt
342d27cfd3SBenjamin Herrenschmidt/* XXX This will ultimately add space for a special exception save
352d27cfd3SBenjamin Herrenschmidt *     structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
362d27cfd3SBenjamin Herrenschmidt *     when taking special interrupts. For now we don't support that,
372d27cfd3SBenjamin Herrenschmidt *     special interrupts from within a non-standard level will probably
382d27cfd3SBenjamin Herrenschmidt *     blow you up
39609af38fSScott Wood */
40609af38fSScott Wood#define SPECIAL_EXC_SRR0	0
41609af38fSScott Wood#define SPECIAL_EXC_SRR1	1
42609af38fSScott Wood#define SPECIAL_EXC_SPRG_GEN	2
43609af38fSScott Wood#define SPECIAL_EXC_SPRG_TLB	3
44609af38fSScott Wood#define SPECIAL_EXC_MAS0	4
45609af38fSScott Wood#define SPECIAL_EXC_MAS1	5
46609af38fSScott Wood#define SPECIAL_EXC_MAS2	6
47609af38fSScott Wood#define SPECIAL_EXC_MAS3	7
48609af38fSScott Wood#define SPECIAL_EXC_MAS6	8
49609af38fSScott Wood#define SPECIAL_EXC_MAS7	9
50609af38fSScott Wood#define SPECIAL_EXC_MAS5	10	/* E.HV only */
51609af38fSScott Wood#define SPECIAL_EXC_MAS8	11	/* E.HV only */
52609af38fSScott Wood#define SPECIAL_EXC_IRQHAPPENED	12
53609af38fSScott Wood#define SPECIAL_EXC_DEAR	13
54609af38fSScott Wood#define SPECIAL_EXC_ESR		14
55609af38fSScott Wood#define SPECIAL_EXC_SOFTE	15
56609af38fSScott Wood#define SPECIAL_EXC_CSRR0	16
57609af38fSScott Wood#define SPECIAL_EXC_CSRR1	17
58609af38fSScott Wood/* must be even to keep 16-byte stack alignment */
592d27cfd3SBenjamin Herrenschmidt#define SPECIAL_EXC_END		18
60609af38fSScott Wood
61609af38fSScott Wood#define SPECIAL_EXC_FRAME_SIZE	(INT_FRAME_SIZE + SPECIAL_EXC_END * 8)
6219007b34STiejun Chen#define SPECIAL_EXC_FRAME_OFFS  (INT_FRAME_SIZE - 288)
63609af38fSScott Wood
64609af38fSScott Wood#define SPECIAL_EXC_STORE(reg, name) \
65609af38fSScott Wood	std	reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
66609af38fSScott Wood
67609af38fSScott Wood#define SPECIAL_EXC_LOAD(reg, name) \
68609af38fSScott Wood	ld	reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
69609af38fSScott Wood
70609af38fSScott WoodSYM_CODE_START_LOCAL(special_reg_save)
71609af38fSScott Wood	/*
72609af38fSScott Wood	 * We only need (or have stack space) to save this stuff if
73609af38fSScott Wood	 * we interrupted the kernel.
74609af38fSScott Wood	 */
75609af38fSScott Wood	ld	r3,_MSR(r1)
76609af38fSScott Wood	andi.	r3,r3,MSR_PR
77609af38fSScott Wood	bnelr
78609af38fSScott Wood
79609af38fSScott Wood	/*
80609af38fSScott Wood	 * Advance to the next TLB exception frame for handler
81609af38fSScott Wood	 * types that don't do it automatically.
82609af38fSScott Wood	 */
83609af38fSScott Wood	LOAD_REG_ADDR(r11,extlb_level_exc)
84609af38fSScott Wood	lwz	r12,0(r11)
85609af38fSScott Wood	mfspr	r10,SPRN_SPRG_TLB_EXFRAME
86609af38fSScott Wood	add	r10,r10,r12
87609af38fSScott Wood	mtspr	SPRN_SPRG_TLB_EXFRAME,r10
88609af38fSScott Wood
89609af38fSScott Wood	/*
90609af38fSScott Wood	 * Save registers needed to allow nesting of certain exceptions
91609af38fSScott Wood	 * (such as TLB misses) inside special exception levels
92609af38fSScott Wood	 */
93609af38fSScott Wood	mfspr	r10,SPRN_SRR0
94609af38fSScott Wood	SPECIAL_EXC_STORE(r10,SRR0)
95609af38fSScott Wood	mfspr	r10,SPRN_SRR1
96609af38fSScott Wood	SPECIAL_EXC_STORE(r10,SRR1)
97609af38fSScott Wood	mfspr	r10,SPRN_SPRG_GEN_SCRATCH
98609af38fSScott Wood	SPECIAL_EXC_STORE(r10,SPRG_GEN)
99609af38fSScott Wood	mfspr	r10,SPRN_SPRG_TLB_SCRATCH
100609af38fSScott Wood	SPECIAL_EXC_STORE(r10,SPRG_TLB)
101609af38fSScott Wood	mfspr	r10,SPRN_MAS0
102609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS0)
103609af38fSScott Wood	mfspr	r10,SPRN_MAS1
104609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS1)
105609af38fSScott Wood	mfspr	r10,SPRN_MAS2
106609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS2)
107609af38fSScott Wood	mfspr	r10,SPRN_MAS3
108609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS3)
109609af38fSScott Wood	mfspr	r10,SPRN_MAS6
110609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS6)
111609af38fSScott Wood	mfspr	r10,SPRN_MAS7
112609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS7)
113609af38fSScott WoodBEGIN_FTR_SECTION
114609af38fSScott Wood	mfspr	r10,SPRN_MAS5
115609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS5)
116609af38fSScott Wood	mfspr	r10,SPRN_MAS8
117609af38fSScott Wood	SPECIAL_EXC_STORE(r10,MAS8)
118609af38fSScott Wood
119609af38fSScott Wood	/* MAS5/8 could have inappropriate values if we interrupted KVM code */
120609af38fSScott Wood	li	r10,0
121609af38fSScott Wood	mtspr	SPRN_MAS5,r10
122609af38fSScott Wood	mtspr	SPRN_MAS8,r10
123609af38fSScott WoodEND_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
124609af38fSScott Wood	mfspr	r10,SPRN_DEAR
125609af38fSScott Wood	SPECIAL_EXC_STORE(r10,DEAR)
126609af38fSScott Wood	mfspr	r10,SPRN_ESR
127609af38fSScott Wood	SPECIAL_EXC_STORE(r10,ESR)
128609af38fSScott Wood
129609af38fSScott Wood	ld	r10,_NIP(r1)
130609af38fSScott Wood	SPECIAL_EXC_STORE(r10,CSRR0)
131609af38fSScott Wood	ld	r10,_MSR(r1)
132609af38fSScott Wood	SPECIAL_EXC_STORE(r10,CSRR1)
133609af38fSScott Wood
134609af38fSScott Wood	blr
135609af38fSScott WoodSYM_CODE_END(special_reg_save)
136609af38fSScott Wood
137609af38fSScott WoodSYM_CODE_START_LOCAL(ret_from_level_except)
138609af38fSScott Wood	ld	r3,_MSR(r1)
1390c2472deSNicholas Piggin	andi.	r3,r3,MSR_PR
1400c2472deSNicholas Piggin	beq	1f
141609af38fSScott Wood	REST_NVGPRS(r1)
142609af38fSScott Wood	b	interrupt_return
143609af38fSScott Wood1:
144609af38fSScott Wood
145609af38fSScott Wood	LOAD_REG_ADDR(r11,extlb_level_exc)
146609af38fSScott Wood	lwz	r12,0(r11)
147609af38fSScott Wood	mfspr	r10,SPRN_SPRG_TLB_EXFRAME
148609af38fSScott Wood	sub	r10,r10,r12
149609af38fSScott Wood	mtspr	SPRN_SPRG_TLB_EXFRAME,r10
150609af38fSScott Wood
151609af38fSScott Wood	/*
152609af38fSScott Wood	 * It's possible that the special level exception interrupted a
153609af38fSScott Wood	 * TLB miss handler, and inserted the same entry that the
154609af38fSScott Wood	 * interrupted handler was about to insert.  On CPUs without TLB
155609af38fSScott Wood	 * write conditional, this can result in a duplicate TLB entry.
156609af38fSScott Wood	 * Wipe all non-bolted entries to be safe.
157609af38fSScott Wood	 *
158609af38fSScott Wood	 * Note that this doesn't protect against any TLB misses
159609af38fSScott Wood	 * we may take accessing the stack from here to the end of
160609af38fSScott Wood	 * the special level exception.  It's not clear how we can
161609af38fSScott Wood	 * reasonably protect against that, but only CPUs with
162609af38fSScott Wood	 * neither TLB write conditional nor bolted kernel memory
163609af38fSScott Wood	 * are affected.  Do any such CPUs even exist?
164609af38fSScott Wood	 */
165609af38fSScott Wood	PPC_TLBILX_ALL(0,R0)
166609af38fSScott Wood
167609af38fSScott Wood	REST_NVGPRS(r1)
168609af38fSScott Wood
169609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,SRR0)
170609af38fSScott Wood	mtspr	SPRN_SRR0,r10
171609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,SRR1)
172609af38fSScott Wood	mtspr	SPRN_SRR1,r10
173609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,SPRG_GEN)
174609af38fSScott Wood	mtspr	SPRN_SPRG_GEN_SCRATCH,r10
175609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,SPRG_TLB)
176609af38fSScott Wood	mtspr	SPRN_SPRG_TLB_SCRATCH,r10
177609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS0)
178609af38fSScott Wood	mtspr	SPRN_MAS0,r10
179609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS1)
180609af38fSScott Wood	mtspr	SPRN_MAS1,r10
181609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS2)
182609af38fSScott Wood	mtspr	SPRN_MAS2,r10
183609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS3)
184609af38fSScott Wood	mtspr	SPRN_MAS3,r10
185609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS6)
186609af38fSScott Wood	mtspr	SPRN_MAS6,r10
187609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS7)
188609af38fSScott Wood	mtspr	SPRN_MAS7,r10
189609af38fSScott WoodBEGIN_FTR_SECTION
190609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS5)
191609af38fSScott Wood	mtspr	SPRN_MAS5,r10
192609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,MAS8)
193609af38fSScott Wood	mtspr	SPRN_MAS8,r10
194609af38fSScott WoodEND_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
195609af38fSScott Wood
196609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,DEAR)
197609af38fSScott Wood	mtspr	SPRN_DEAR,r10
198609af38fSScott Wood	SPECIAL_EXC_LOAD(r10,ESR)
199609af38fSScott Wood	mtspr	SPRN_ESR,r10
200609af38fSScott Wood
201aebd1fb4SNicholas Piggin	stdcx.	r0,0,r1		/* to clear the reservation */
202609af38fSScott Wood
203609af38fSScott Wood	REST_GPRS(2, 9, r1)
204609af38fSScott Wood
205609af38fSScott Wood	ld	r10,_CTR(r1)
206609af38fSScott Wood	ld	r11,_XER(r1)
207609af38fSScott Wood	mtctr	r10
208609af38fSScott Wood	mtxer	r11
209609af38fSScott Wood
210609af38fSScott Wood	blr
211609af38fSScott WoodSYM_CODE_END(ret_from_level_except)
212609af38fSScott Wood
213609af38fSScott Wood.macro ret_from_level srr0 srr1 paca_ex scratch
214609af38fSScott Wood	bl	ret_from_level_except
215609af38fSScott Wood
216609af38fSScott Wood	ld	r10,_LINK(r1)
217609af38fSScott Wood	ld	r11,_CCR(r1)
218609af38fSScott Wood	ld	r0,GPR13(r1)
21953ecaa67SRohan McLure	mtlr	r10
220609af38fSScott Wood	mtcr	r11
221609af38fSScott Wood
222609af38fSScott Wood	REST_GPRS(10, 12, r1)
223609af38fSScott Wood	mtspr	\scratch,r0
224609af38fSScott Wood
225609af38fSScott Wood	std	r10,\paca_ex+EX_R10(r13);
22653ecaa67SRohan McLure	std	r11,\paca_ex+EX_R11(r13);
22753ecaa67SRohan McLure	ld	r10,_NIP(r1)
228609af38fSScott Wood	ld	r11,_MSR(r1)
229609af38fSScott Wood	REST_GPR(0, r1)
230609af38fSScott Wood	REST_GPR(1, r1)
231609af38fSScott Wood	mtspr	\srr0,r10
232609af38fSScott Wood	mtspr	\srr1,r11
233609af38fSScott Wood	ld	r10,\paca_ex+EX_R10(r13)
234609af38fSScott Wood	ld	r11,\paca_ex+EX_R11(r13)
235609af38fSScott Wood	mfspr	r13,\scratch
236609af38fSScott Wood.endm
237609af38fSScott Wood
238609af38fSScott WoodSYM_CODE_START_LOCAL(ret_from_crit_except)
239609af38fSScott Wood	ret_from_level SPRN_CSRR0 SPRN_CSRR1 PACA_EXCRIT SPRN_SPRG_CRIT_SCRATCH
240609af38fSScott Wood	rfci
241609af38fSScott WoodSYM_CODE_END(ret_from_crit_except)
24219007b34STiejun Chen
2432d27cfd3SBenjamin HerrenschmidtSYM_CODE_START_LOCAL(ret_from_mc_except)
244fecff0f7SMihai Caraman	ret_from_level SPRN_MCSRR0 SPRN_MCSRR1 PACA_EXMC SPRN_SPRG_MC_SCRATCH
2452d27cfd3SBenjamin Herrenschmidt	rfmci
2462d27cfd3SBenjamin HerrenschmidtSYM_CODE_END(ret_from_mc_except)
2472d27cfd3SBenjamin Herrenschmidt
2482d27cfd3SBenjamin Herrenschmidt/* Exception prolog code for all exceptions */
2492d27cfd3SBenjamin Herrenschmidt#define EXCEPTION_PROLOG(n, intnum, type, addition)	    		    \
250fecff0f7SMihai Caraman	mtspr	SPRN_SPRG_##type##_SCRATCH,r13;	/* get spare registers */   \
251fecff0f7SMihai Caraman	mfspr	r13,SPRN_SPRG_PACA;	/* get PACA */			    \
25279b5c8dbSMihai Caraman	std	r10,PACA_EX##type+EX_R10(r13);				    \
2532d27cfd3SBenjamin Herrenschmidt	std	r11,PACA_EX##type+EX_R11(r13);				    \
2542d27cfd3SBenjamin Herrenschmidt	mfcr	r10;			/* save CR */			    \
2552d27cfd3SBenjamin Herrenschmidt	mfspr	r11,SPRN_##type##_SRR1;/* what are we coming from */	    \
2562d27cfd3SBenjamin Herrenschmidt	DO_KVM	intnum,SPRN_##type##_SRR1;    /* KVM hook */		    \
2572d27cfd3SBenjamin Herrenschmidt	stw	r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
2582d27cfd3SBenjamin Herrenschmidt	addition;			/* additional code for that exc. */ \
25910c5e83aSDiana Craciun	std	r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */  \
26010c5e83aSDiana Craciun	type##_SET_KSTACK;		/* get special stack if necessary */\
2612d27cfd3SBenjamin Herrenschmidt	andi.	r10,r11,MSR_PR;		/* save stack pointer */	    \
2622d27cfd3SBenjamin Herrenschmidt	beq	1f;			/* branch around if supervisor */   \
2632d27cfd3SBenjamin Herrenschmidt	ld	r1,PACAKSAVE(r13);	/* get kernel stack coming from usr */\
2642d27cfd3SBenjamin Herrenschmidt1:	type##_BTB_FLUSH		\
2652d27cfd3SBenjamin Herrenschmidt	cmpdi	cr1,r1,0;		/* check if SP makes sense */	    \
2662d27cfd3SBenjamin Herrenschmidt	bge-	cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \
2672d27cfd3SBenjamin Herrenschmidt	mfspr	r10,SPRN_##type##_SRR0;	/* read SRR0 before touching stack */
2682d27cfd3SBenjamin Herrenschmidt
2692d27cfd3SBenjamin Herrenschmidt/* Exception type-specific macros */
2705473eb1cSMihai Caraman#define	GEN_SET_KSTACK							    \
2715473eb1cSMihai Caraman	subi	r1,r1,INT_FRAME_SIZE;	/* alloc frame on kernel stack */
2725473eb1cSMihai Caraman#define SPRN_GEN_SRR0	SPRN_SRR0
2735473eb1cSMihai Caraman#define SPRN_GEN_SRR1	SPRN_SRR1
2742d27cfd3SBenjamin Herrenschmidt
2752d27cfd3SBenjamin Herrenschmidt#define	GDBELL_SET_KSTACK	GEN_SET_KSTACK
276609af38fSScott Wood#define SPRN_GDBELL_SRR0	SPRN_GSRR0
2772d27cfd3SBenjamin Herrenschmidt#define SPRN_GDBELL_SRR1	SPRN_GSRR1
2782d27cfd3SBenjamin Herrenschmidt
2792d27cfd3SBenjamin Herrenschmidt#define CRIT_SET_KSTACK						            \
2802d27cfd3SBenjamin Herrenschmidt	ld	r1,PACA_CRIT_STACK(r13);				    \
2812d27cfd3SBenjamin Herrenschmidt	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
282609af38fSScott Wood#define SPRN_CRIT_SRR0	SPRN_CSRR0
2832d27cfd3SBenjamin Herrenschmidt#define SPRN_CRIT_SRR1	SPRN_CSRR1
2842d27cfd3SBenjamin Herrenschmidt
2852d27cfd3SBenjamin Herrenschmidt#define DBG_SET_KSTACK						            \
2862d27cfd3SBenjamin Herrenschmidt	ld	r1,PACA_DBG_STACK(r13);					    \
2872d27cfd3SBenjamin Herrenschmidt	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
288609af38fSScott Wood#define SPRN_DBG_SRR0	SPRN_DSRR0
2892d27cfd3SBenjamin Herrenschmidt#define SPRN_DBG_SRR1	SPRN_DSRR1
2902d27cfd3SBenjamin Herrenschmidt
2912d27cfd3SBenjamin Herrenschmidt#define MC_SET_KSTACK						            \
29210c5e83aSDiana Craciun	ld	r1,PACA_MC_STACK(r13);					    \
29310c5e83aSDiana Craciun	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE
29410c5e83aSDiana Craciun#define SPRN_MC_SRR0	SPRN_MCSRR0
29510c5e83aSDiana Craciun#define SPRN_MC_SRR1	SPRN_MCSRR1
29610c5e83aSDiana Craciun
29710c5e83aSDiana Craciun#define GEN_BTB_FLUSH			\
29810c5e83aSDiana Craciun	START_BTB_FLUSH_SECTION		\
29910c5e83aSDiana Craciun		beq 1f;			\
30010c5e83aSDiana Craciun		BTB_FLUSH(r10)			\
30110c5e83aSDiana Craciun		1:		\
30210c5e83aSDiana Craciun	END_BTB_FLUSH_SECTION
30310c5e83aSDiana Craciun
30410c5e83aSDiana Craciun#define CRIT_BTB_FLUSH			\
30510c5e83aSDiana Craciun	START_BTB_FLUSH_SECTION		\
30610c5e83aSDiana Craciun		BTB_FLUSH(r10)		\
30710c5e83aSDiana Craciun	END_BTB_FLUSH_SECTION
308fecff0f7SMihai Caraman
309fecff0f7SMihai Caraman#define DBG_BTB_FLUSH CRIT_BTB_FLUSH
3102d27cfd3SBenjamin Herrenschmidt#define MC_BTB_FLUSH CRIT_BTB_FLUSH
311fecff0f7SMihai Caraman#define GDBELL_BTB_FLUSH GEN_BTB_FLUSH
312fecff0f7SMihai Caraman
3132d27cfd3SBenjamin Herrenschmidt#define NORMAL_EXCEPTION_PROLOG(n, intnum, addition)			    \
314fecff0f7SMihai Caraman	EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n))
315fecff0f7SMihai Caraman
3162d27cfd3SBenjamin Herrenschmidt#define CRIT_EXCEPTION_PROLOG(n, intnum, addition)			    \
317fecff0f7SMihai Caraman	EXCEPTION_PROLOG(n, intnum, CRIT, addition##_CRIT(n))
318fecff0f7SMihai Caraman
3192d27cfd3SBenjamin Herrenschmidt#define DBG_EXCEPTION_PROLOG(n, intnum, addition)			    \
320fecff0f7SMihai Caraman	EXCEPTION_PROLOG(n, intnum, DBG, addition##_DBG(n))
321fecff0f7SMihai Caraman
3222d27cfd3SBenjamin Herrenschmidt#define MC_EXCEPTION_PROLOG(n, intnum, addition)			    \
3232d27cfd3SBenjamin Herrenschmidt	EXCEPTION_PROLOG(n, intnum, MC, addition##_MC(n))
3242d27cfd3SBenjamin Herrenschmidt
3257230c564SBenjamin Herrenschmidt#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)			    \
3265473eb1cSMihai Caraman	EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
3277230c564SBenjamin Herrenschmidt
3287230c564SBenjamin Herrenschmidt/* Variants of the "addition" argument for the prolog
3297230c564SBenjamin Herrenschmidt */
3302d27cfd3SBenjamin Herrenschmidt#define PROLOG_ADDITION_NONE_GEN(n)
3317230c564SBenjamin Herrenschmidt#define PROLOG_ADDITION_NONE_GDBELL(n)
3324e26bc4aSMadhavan Srinivasan#define PROLOG_ADDITION_NONE_CRIT(n)
33301417c6cSMadhavan Srinivasan#define PROLOG_ADDITION_NONE_DBG(n)
3349b69d48cSNicholas Piggin#define PROLOG_ADDITION_NONE_MC(n)
3352d27cfd3SBenjamin Herrenschmidt
336c6ac667bSNicholas Piggin#define PROLOG_ADDITION_MASKABLE_GEN(n)					    \
337c6ac667bSNicholas Piggin	lbz	r10,PACAIRQSOFTMASK(r13);	/* are irqs soft-masked? */ \
338c6ac667bSNicholas Piggin	andi.	r10,r10,IRQS_DISABLED;	/* yes -> go out of line */ \
339c6ac667bSNicholas Piggin	bne	masked_interrupt_book3e_##n
340c6ac667bSNicholas Piggin
341c6ac667bSNicholas Piggin/*
3427230c564SBenjamin Herrenschmidt * Additional regs must be re-loaded from paca before EXCEPTION_COMMON* is
3432d27cfd3SBenjamin Herrenschmidt * called, because that does SAVE_NVGPRS which must see the original register
3442d27cfd3SBenjamin Herrenschmidt * values, otherwise the scratch values might be restored when exiting the
3452d27cfd3SBenjamin Herrenschmidt * interrupt.
3467230c564SBenjamin Herrenschmidt */
3472d27cfd3SBenjamin Herrenschmidt#define PROLOG_ADDITION_2REGS_GEN(n)					    \
3482d27cfd3SBenjamin Herrenschmidt	std	r14,PACA_EXGEN+EX_R14(r13);				    \
3497230c564SBenjamin Herrenschmidt	std	r15,PACA_EXGEN+EX_R15(r13)
3502d27cfd3SBenjamin Herrenschmidt
3512d27cfd3SBenjamin Herrenschmidt#define PROLOG_ADDITION_1REG_GEN(n)					    \
3522d27cfd3SBenjamin Herrenschmidt	std	r14,PACA_EXGEN+EX_R14(r13);
3537230c564SBenjamin Herrenschmidt
3542d27cfd3SBenjamin Herrenschmidt#define PROLOG_ADDITION_2REGS_CRIT(n)					    \
3552d27cfd3SBenjamin Herrenschmidt	std	r14,PACA_EXCRIT+EX_R14(r13);				    \
3562d27cfd3SBenjamin Herrenschmidt	std	r15,PACA_EXCRIT+EX_R15(r13)
3577230c564SBenjamin Herrenschmidt
3582d27cfd3SBenjamin Herrenschmidt#define PROLOG_ADDITION_2REGS_DBG(n)					    \
3592d27cfd3SBenjamin Herrenschmidt	std	r14,PACA_EXDBG+EX_R14(r13);				    \
3602d27cfd3SBenjamin Herrenschmidt	std	r15,PACA_EXDBG+EX_R15(r13)
3613d97a619SScott Wood
36231f71248SScott Wood#define PROLOG_ADDITION_2REGS_MC(n)					    \
36331f71248SScott Wood	std	r14,PACA_EXMC+EX_R14(r13);				    \
3647230c564SBenjamin Herrenschmidt	std	r15,PACA_EXMC+EX_R15(r13)
36553ecaa67SRohan McLure
36653ecaa67SRohan McLure/* Core exception code for all exceptions except TLB misses. */
3672d27cfd3SBenjamin Herrenschmidt#define EXCEPTION_COMMON_LVL(n, scratch, excf)				    \
3682d27cfd3SBenjamin Herrenschmidtexc_##n##_common:							    \
3695d75b264SHaren Myneni	SAVE_GPR(0, r1);		/* save r0 in stackframe */	    \
3705d75b264SHaren Myneni	SAVE_GPRS(2, 9, r1);		/* save r2 - r9 in stackframe */    \
3712d27cfd3SBenjamin Herrenschmidt	std	r10,_NIP(r1);		/* save SRR0 to stackframe */	    \
37231f71248SScott Wood	std	r11,_MSR(r1);		/* save SRR1 to stackframe */	    \
37353ecaa67SRohan McLure	beq	2f;			/* if from kernel mode */	    \
3748e93fb33SNicholas Piggin2:	ld	r3,excf+EX_R10(r13);	/* get back r10 */		    \
3752d27cfd3SBenjamin Herrenschmidt	ld	r4,excf+EX_R11(r13);	/* get back r11 */		    \
3762d27cfd3SBenjamin Herrenschmidt	mfspr	r5,scratch;		/* get back r13 */		    \
3772d27cfd3SBenjamin Herrenschmidt	SAVE_GPR(12, r1);		/* save r12 in stackframe */	    \
3782d27cfd3SBenjamin Herrenschmidt	LOAD_PACA_TOC();		/* get kernel TOC into r2 */	    \
3792d27cfd3SBenjamin Herrenschmidt	mflr	r6;			/* save LR in stackframe */	    \
3804e26bc4aSMadhavan Srinivasan	mfctr	r7;			/* save CTR in stackframe */	    \
38117773afdSNicholas Piggin	mfspr	r8,SPRN_XER;		/* save XER in stackframe */	    \
38253ecaa67SRohan McLure	ld	r9,excf+EX_R1(r13);	/* load orig r1 back from PACA */   \
3832d27cfd3SBenjamin Herrenschmidt	lwz	r10,excf+EX_CR(r13);	/* load orig CR back from PACA	*/  \
3842d27cfd3SBenjamin Herrenschmidt	lbz	r11,PACAIRQSOFTMASK(r13); /* get current IRQ softe */	    \
3852d27cfd3SBenjamin Herrenschmidt	LOAD_REG_IMMEDIATE(r12, STACK_FRAME_REGS_MARKER);		    \
3862d27cfd3SBenjamin Herrenschmidt	ZEROIZE_GPR(0);							    \
3872d27cfd3SBenjamin Herrenschmidt	std	r3,GPR10(r1);		/* save r10 to stackframe */	    \
3882d27cfd3SBenjamin Herrenschmidt	std	r4,GPR11(r1);		/* save r11 to stackframe */	    \
3894228b2c3SNicholas Piggin	std	r5,GPR13(r1);		/* save it to stackframe */	    \
3902d27cfd3SBenjamin Herrenschmidt	std	r6,_LINK(r1);						    \
3912d27cfd3SBenjamin Herrenschmidt	std	r7,_CTR(r1);						    \
3922d27cfd3SBenjamin Herrenschmidt	std	r8,_XER(r1);						    \
3932d27cfd3SBenjamin Herrenschmidt	li	r3,(n);			/* regs.trap vector */		    \
3942d27cfd3SBenjamin Herrenschmidt	std	r9,0(r1);		/* store stack frame back link */   \
3952d27cfd3SBenjamin Herrenschmidt	std	r10,_CCR(r1);		/* store orig CR in stackframe */   \
3964228b2c3SNicholas Piggin	std	r9,GPR1(r1);		/* store stack frame back link */   \
3974228b2c3SNicholas Piggin	std	r11,SOFTE(r1);		/* and save it to stackframe */     \
3982d27cfd3SBenjamin Herrenschmidt	std	r12,STACK_INT_FRAME_MARKER(r1); /* mark the frame */	    \
39931f71248SScott Wood	std	r3,_TRAP(r1);		/* set trap number		*/  \
40031f71248SScott Wood	std	r0,RESULT(r1);		/* clear regs->result */	    \
40131f71248SScott Wood	SAVE_NVGPRS(r1);						    \
40231f71248SScott Wood	SANITIZE_NVGPRS();		/* minimise speculation influence */
40331f71248SScott Wood
40431f71248SScott Wood#define EXCEPTION_COMMON(n) \
40531f71248SScott Wood	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_GEN_SCRATCH, PACA_EXGEN)
40631f71248SScott Wood#define EXCEPTION_COMMON_CRIT(n) \
40731f71248SScott Wood	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_CRIT_SCRATCH, PACA_EXCRIT)
4082d27cfd3SBenjamin Herrenschmidt#define EXCEPTION_COMMON_MC(n) \
4092d27cfd3SBenjamin Herrenschmidt	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_MC_SCRATCH, PACA_EXMC)
4102d27cfd3SBenjamin Herrenschmidt#define EXCEPTION_COMMON_DBG(n) \
4112d27cfd3SBenjamin Herrenschmidt	EXCEPTION_COMMON_LVL(n, SPRN_SPRG_DBG_SCRATCH, PACA_EXDBG)
4122d27cfd3SBenjamin Herrenschmidt
4132d27cfd3SBenjamin Herrenschmidt/* XXX FIXME: Restore r14/r15 when necessary */
4142d27cfd3SBenjamin Herrenschmidt#define BAD_STACK_TRAMPOLINE(n)						    \
415027dfac6SMichael Ellermanexc_##n##_bad_stack:							    \
416ff82c319SBenjamin Herrenschmidt	li	r1,(n);			/* get exception number */	    \
417ff82c319SBenjamin Herrenschmidt	sth	r1,PACA_TRAP_SAVE(r13);	/* store trap */		    \
418ff82c319SBenjamin Herrenschmidt	b	bad_stack_book3e;	/* bad stack error */
419ff82c319SBenjamin Herrenschmidt
420ff82c319SBenjamin Herrenschmidt/* WARNING: If you change the layout of this stub, make sure you check
4212d27cfd3SBenjamin Herrenschmidt	*   the debug exception handler which handles single stepping
4222d27cfd3SBenjamin Herrenschmidt	*   into exceptions from userspace, and the MM code in
4232d27cfd3SBenjamin Herrenschmidt	*   arch/powerpc/mm/tlb_nohash.c which patches the branch here
4242d27cfd3SBenjamin Herrenschmidt	*   and would need to be updated if that branch is moved
4252d27cfd3SBenjamin Herrenschmidt	*/
4262d27cfd3SBenjamin Herrenschmidt#define	EXCEPTION_STUB(loc, label)					\
4272d27cfd3SBenjamin Herrenschmidt	. = interrupt_base_book3e + loc;				\
4282d27cfd3SBenjamin Herrenschmidt	nop;	/* To make debug interrupts happy */			\
4292d27cfd3SBenjamin Herrenschmidt	b	exc_##label##_book3e;
4302d27cfd3SBenjamin Herrenschmidt
4312d27cfd3SBenjamin Herrenschmidt#define ACK_NONE(r)
4322d27cfd3SBenjamin Herrenschmidt#define ACK_DEC(r)							\
4332d27cfd3SBenjamin Herrenschmidt	lis	r,TSR_DIS@h;						\
43434d97e07SBenjamin Herrenschmidt	mtspr	SPRN_TSR,r
43534d97e07SBenjamin Herrenschmidt#define ACK_FIT(r)							\
43634d97e07SBenjamin Herrenschmidt	lis	r,TSR_FIS@h;						\
43734d97e07SBenjamin Herrenschmidt	mtspr	SPRN_TSR,r
43834d97e07SBenjamin Herrenschmidt
43934d97e07SBenjamin Herrenschmidt/* Used by asynchronous interrupt that may happen in the idle loop.
44034d97e07SBenjamin Herrenschmidt *
441c911d2e1SChristophe Leroy * This check if the thread was in the idle loop, and if yes, returns
44234d97e07SBenjamin Herrenschmidt * to the caller rather than the PC. This is to avoid a race if
44334d97e07SBenjamin Herrenschmidt * interrupts happen before the wait instruction.
44434d97e07SBenjamin Herrenschmidt */
44534d97e07SBenjamin Herrenschmidt#define CHECK_NAPPING()							\
44634d97e07SBenjamin Herrenschmidt	ld	r11, PACA_THREAD_INFO(r13);				\
44734d97e07SBenjamin Herrenschmidt	ld	r10,TI_LOCAL_FLAGS(r11);				\
44834d97e07SBenjamin Herrenschmidt	andi.	r9,r10,_TLF_NAPPING;					\
44934d97e07SBenjamin Herrenschmidt	beq+	1f;							\
45034d97e07SBenjamin Herrenschmidt	ld	r8,_LINK(r1);						\
45134d97e07SBenjamin Herrenschmidt	rlwinm	r7,r10,0,~_TLF_NAPPING;					\
452fecff0f7SMihai Caraman	std	r8,_NIP(r1);						\
4532d27cfd3SBenjamin Herrenschmidt	std	r7,TI_LOCAL_FLAGS(r11);					\
454fecff0f7SMihai Caraman1:
45531f71248SScott Wood
4562d27cfd3SBenjamin Herrenschmidt
45734d97e07SBenjamin Herrenschmidt#define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)		\
4582d27cfd3SBenjamin Herrenschmidt	START_EXCEPTION(label);						\
4592d27cfd3SBenjamin Herrenschmidt	NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
4600c2472deSNicholas Piggin	EXCEPTION_COMMON(trapnum)					\
4612d27cfd3SBenjamin Herrenschmidt	ack(r8);							\
4622d27cfd3SBenjamin Herrenschmidt	CHECK_NAPPING();						\
4632d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS;				\
4642d27cfd3SBenjamin Herrenschmidt	bl	hdlr;							\
4652d27cfd3SBenjamin Herrenschmidt	b	interrupt_return
4662d27cfd3SBenjamin Herrenschmidt
4672d27cfd3SBenjamin Herrenschmidt/*
4682d27cfd3SBenjamin Herrenschmidt * And here we have the exception vectors !
4692d27cfd3SBenjamin Herrenschmidt */
470c4787d1eSScott Wood
471c4787d1eSScott Wood	.text
4722d27cfd3SBenjamin Herrenschmidt	.balign	0x1000
4732d27cfd3SBenjamin Herrenschmidt	.globl interrupt_base_book3e
4742d27cfd3SBenjamin Herrenschmidtinterrupt_base_book3e:					/* fake trap */
4752d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x000, machine_check)
4762d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x020, critical_input)		/* 0x0100 */
4772d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x040, debug_crit)		/* 0x0d00 */
4782d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x060, data_storage)		/* 0x0300 */
4792d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x080, instruction_storage)	/* 0x0400 */
4802d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x0a0, external_input)		/* 0x0500 */
4812d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x0c0, alignment)		/* 0x0600 */
4822d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x0e0, program)			/* 0x0700 */
4832d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x100, fp_unavailable)		/* 0x0800 */
4842d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x120, system_call)		/* 0x0c00 */
4852d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x140, ap_unavailable)		/* 0x0f20 */
486c4787d1eSScott Wood	EXCEPTION_STUB(0x160, decrementer)		/* 0x0900 */
487c4787d1eSScott Wood	EXCEPTION_STUB(0x180, fixed_interval)		/* 0x0980 */
4883a6e9bd7SScott Wood	EXCEPTION_STUB(0x1a0, watchdog)			/* 0x09f0 */
48989c81797SBenjamin Herrenschmidt	EXCEPTION_STUB(0x1c0, data_tlb_miss)
49089c81797SBenjamin Herrenschmidt	EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
4913a6e9bd7SScott Wood	EXCEPTION_STUB(0x200, altivec_unavailable)
4923a6e9bd7SScott Wood	EXCEPTION_STUB(0x220, altivec_assist)
4933a6e9bd7SScott Wood	EXCEPTION_STUB(0x260, perfmon)
4943a6e9bd7SScott Wood	EXCEPTION_STUB(0x280, doorbell)
495228b1a47SMihai Caraman	EXCEPTION_STUB(0x2a0, doorbell_crit)
4962d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x2c0, guest_doorbell)
49768d10140STiejun Chen	EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
49868d10140STiejun Chen	EXCEPTION_STUB(0x300, hypercall)
4992d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x320, ehpriv)
5002d27cfd3SBenjamin Herrenschmidt	EXCEPTION_STUB(0x340, lrat_error)
5012d27cfd3SBenjamin Herrenschmidt
502fecff0f7SMihai Caraman	.globl __end_interrupts
503fecff0f7SMihai Caraman__end_interrupts:
504609af38fSScott Wood
505609af38fSScott Wood/* Critical Input Interrupt */
506609af38fSScott Wood	START_EXCEPTION(critical_input);
507609af38fSScott Wood	CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
5083db8aa10SNicholas Piggin			      PROLOG_ADDITION_NONE)
509609af38fSScott Wood	EXCEPTION_COMMON_CRIT(0x100)
5102d27cfd3SBenjamin Herrenschmidt	bl	special_reg_save
5112d27cfd3SBenjamin Herrenschmidt	CHECK_NAPPING();
5122d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
513c4787d1eSScott Wood	bl	unknown_nmi_exception
514fecff0f7SMihai Caraman	b	ret_from_crit_except
515609af38fSScott Wood
516609af38fSScott Wood/* Machine Check Interrupt */
517609af38fSScott Wood	START_EXCEPTION(machine_check);
518609af38fSScott Wood	MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
519b1576fecSAnton Blanchard			    PROLOG_ADDITION_NONE)
520609af38fSScott Wood	EXCEPTION_COMMON_MC(0x000)
5212d27cfd3SBenjamin Herrenschmidt	bl	special_reg_save
5222d27cfd3SBenjamin Herrenschmidt	CHECK_NAPPING();
5232d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
524fecff0f7SMihai Caraman	bl	machine_check_exception
525fecff0f7SMihai Caraman	b	ret_from_mc_except
5262d27cfd3SBenjamin Herrenschmidt
5272d27cfd3SBenjamin Herrenschmidt/* Data Storage Interrupt */
528d9db6e42SXiongwei Song	START_EXCEPTION(data_storage)
529cfa47772SXiongwei Song	NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
530c6ac667bSNicholas Piggin				PROLOG_ADDITION_2REGS)
531c6ac667bSNicholas Piggin	mfspr	r14,SPRN_DEAR
53231f71248SScott Wood	mfspr	r15,SPRN_ESR
5332d27cfd3SBenjamin Herrenschmidt	std	r14,_DEAR(r1)
5342d27cfd3SBenjamin Herrenschmidt	std	r15,_ESR(r1)
5352d27cfd3SBenjamin Herrenschmidt	ld	r14,PACA_EXGEN+EX_R14(r13)
5362d27cfd3SBenjamin Herrenschmidt	ld	r15,PACA_EXGEN+EX_R15(r13)
537fecff0f7SMihai Caraman	EXCEPTION_COMMON(0x300)
538fecff0f7SMihai Caraman	b	storage_fault_common
5392d27cfd3SBenjamin Herrenschmidt
5402d27cfd3SBenjamin Herrenschmidt/* Instruction Storage Interrupt */
541d9db6e42SXiongwei Song	START_EXCEPTION(instruction_storage);
542cfa47772SXiongwei Song	NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
543c6ac667bSNicholas Piggin				PROLOG_ADDITION_2REGS)
544c6ac667bSNicholas Piggin	li	r15,0
54531f71248SScott Wood	mr	r14,r10
5462d27cfd3SBenjamin Herrenschmidt	std	r14,_DEAR(r1)
5472d27cfd3SBenjamin Herrenschmidt	std	r15,_ESR(r1)
5482d27cfd3SBenjamin Herrenschmidt	ld	r14,PACA_EXGEN+EX_R14(r13)
549fecff0f7SMihai Caraman	ld	r15,PACA_EXGEN+EX_R15(r13)
55035425501SAnton Blanchard	EXCEPTION_COMMON(0x400)
5512d27cfd3SBenjamin Herrenschmidt	b	storage_fault_common
5522d27cfd3SBenjamin Herrenschmidt
5532d27cfd3SBenjamin Herrenschmidt/* External Input Interrupt */
554fecff0f7SMihai Caraman	MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
555fecff0f7SMihai Caraman			   external_input, do_IRQ, ACK_NONE)
5562d27cfd3SBenjamin Herrenschmidt
5572d27cfd3SBenjamin Herrenschmidt/* Alignment */
558d9db6e42SXiongwei Song	START_EXCEPTION(alignment);
559cfa47772SXiongwei Song	NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
560c6ac667bSNicholas Piggin				PROLOG_ADDITION_2REGS)
561c6ac667bSNicholas Piggin	mfspr	r14,SPRN_DEAR
56231f71248SScott Wood	mfspr	r15,SPRN_ESR
5632d27cfd3SBenjamin Herrenschmidt	std	r14,_DEAR(r1)
5642d27cfd3SBenjamin Herrenschmidt	std	r15,_ESR(r1)
5652d27cfd3SBenjamin Herrenschmidt	ld	r14,PACA_EXGEN+EX_R14(r13)
5662d27cfd3SBenjamin Herrenschmidt	ld	r15,PACA_EXGEN+EX_R15(r13)
567fecff0f7SMihai Caraman	EXCEPTION_COMMON(0x600)
568fecff0f7SMihai Caraman	b	alignment_more	/* no room, go out of line */
5692d27cfd3SBenjamin Herrenschmidt
570cfa47772SXiongwei Song/* Program Interrupt */
5712d27cfd3SBenjamin Herrenschmidt	START_EXCEPTION(program);
572c6ac667bSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
573c6ac667bSNicholas Piggin				PROLOG_ADDITION_1REG)
574b1576fecSAnton Blanchard	mfspr	r14,SPRN_ESR
5750c2472deSNicholas Piggin	std	r14,_ESR(r1)
5760c2472deSNicholas Piggin	ld	r14,PACA_EXGEN+EX_R14(r13)
5772d27cfd3SBenjamin Herrenschmidt	EXCEPTION_COMMON(0x700)
5782d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
5792d27cfd3SBenjamin Herrenschmidt	bl	program_check_exception
580fecff0f7SMihai Caraman	REST_NVGPRS(r1)
581fecff0f7SMihai Caraman	b	interrupt_return
5822d27cfd3SBenjamin Herrenschmidt
58331f71248SScott Wood/* Floating Point Unavailable Interrupt */
5849424fabfSBenjamin Herrenschmidt	START_EXCEPTION(fp_unavailable);
5859424fabfSBenjamin Herrenschmidt	NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
5869424fabfSBenjamin Herrenschmidt				PROLOG_ADDITION_NONE)
587b1576fecSAnton Blanchard	/* we can probably do a shorter exception entry for that one... */
5880c2472deSNicholas Piggin	EXCEPTION_COMMON(0x800)
589097157e1SNicholas Piggin	ld	r12,_MSR(r1)
590b1576fecSAnton Blanchard	andi.	r0,r12,MSR_PR;
5910c2472deSNicholas Piggin	beq-	1f
5922d27cfd3SBenjamin Herrenschmidt	bl	load_up_fpu
593cd66cc2eSKumar Gala	b	fast_interrupt_return
594cd66cc2eSKumar Gala1:	addi	r3,r1,STACK_INT_FRAME_REGS
5952b2695a8SMihai Caraman	bl	kernel_fp_unavailable_exception
596cd66cc2eSKumar Gala	b	interrupt_return
597cd66cc2eSKumar Gala
59831f71248SScott Wood/* Altivec Unavailable Interrupt */
599cd66cc2eSKumar Gala	START_EXCEPTION(altivec_unavailable);
600cd66cc2eSKumar Gala	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_ALTIVEC_UNAVAIL,
601cd66cc2eSKumar Gala				PROLOG_ADDITION_NONE)
602cd66cc2eSKumar Gala	/* we can probably do a shorter exception entry for that one... */
603cd66cc2eSKumar Gala	EXCEPTION_COMMON(0x200)
604b1576fecSAnton Blanchard#ifdef CONFIG_ALTIVEC
6050c2472deSNicholas PigginBEGIN_FTR_SECTION
606cd66cc2eSKumar Gala	ld	r12,_MSR(r1)
607cd66cc2eSKumar Gala	andi.	r0,r12,MSR_PR;
608cd66cc2eSKumar Gala	beq-	1f
609cd66cc2eSKumar Gala	bl	load_up_altivec
610b1576fecSAnton Blanchard	b	fast_interrupt_return
6110c2472deSNicholas Piggin1:
612cd66cc2eSKumar GalaEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
613cd66cc2eSKumar Gala#endif
614cd66cc2eSKumar Gala	addi	r3,r1,STACK_INT_FRAME_REGS
6156b310fc5SMihai Caraman	bl	altivec_unavailable_exception
6162b2695a8SMihai Caraman	b	interrupt_return
617cd66cc2eSKumar Gala
61831f71248SScott Wood/* AltiVec Assist */
619cd66cc2eSKumar Gala	START_EXCEPTION(altivec_assist);
620cd66cc2eSKumar Gala	NORMAL_EXCEPTION_PROLOG(0x220,
621cd66cc2eSKumar Gala				BOOKE_INTERRUPT_ALTIVEC_ASSIST,
622b1576fecSAnton Blanchard				PROLOG_ADDITION_NONE)
623cd66cc2eSKumar Gala	EXCEPTION_COMMON(0x220)
6240c2472deSNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
625cd66cc2eSKumar Gala#ifdef CONFIG_ALTIVEC
626b1576fecSAnton BlanchardBEGIN_FTR_SECTION
627cd66cc2eSKumar Gala	bl	altivec_assist_exception
6280c2472deSNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
629cd66cc2eSKumar Gala	REST_NVGPRS(r1)
630cd66cc2eSKumar Gala#else
6312d27cfd3SBenjamin Herrenschmidt	bl	unknown_exception
632fecff0f7SMihai Caraman#endif
63335425501SAnton Blanchard	b	interrupt_return
6342d27cfd3SBenjamin Herrenschmidt
6352d27cfd3SBenjamin Herrenschmidt
636fecff0f7SMihai Caraman/* Decrementer Interrupt */
63735425501SAnton Blanchard	MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
6382d27cfd3SBenjamin Herrenschmidt			   decrementer, timer_interrupt, ACK_DEC)
6392d27cfd3SBenjamin Herrenschmidt
6402d27cfd3SBenjamin Herrenschmidt/* Fixed Interval Timer Interrupt */
641fecff0f7SMihai Caraman	MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
642fecff0f7SMihai Caraman			   fixed_interval, unknown_exception, ACK_FIT)
643609af38fSScott Wood
644609af38fSScott Wood/* Watchdog Timer Interrupt */
645609af38fSScott Wood	START_EXCEPTION(watchdog);
646609af38fSScott Wood	CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
647609af38fSScott Wood			      PROLOG_ADDITION_NONE)
648b1576fecSAnton Blanchard	EXCEPTION_COMMON_CRIT(0x9f0)
649609af38fSScott Wood	bl	special_reg_save
6503db8aa10SNicholas Piggin	CHECK_NAPPING();
651609af38fSScott Wood	addi	r3,r1,STACK_INT_FRAME_REGS
652609af38fSScott Wood#ifdef CONFIG_BOOKE_WDT
6532d27cfd3SBenjamin Herrenschmidt	bl	WatchdogException
6542d27cfd3SBenjamin Herrenschmidt#else
6552d27cfd3SBenjamin Herrenschmidt	bl	unknown_nmi_exception
6562d27cfd3SBenjamin Herrenschmidt#endif
6572d27cfd3SBenjamin Herrenschmidt	b	ret_from_crit_except
6582d27cfd3SBenjamin Herrenschmidt
6592d27cfd3SBenjamin Herrenschmidt/* System Call Interrupt */
6602d27cfd3SBenjamin Herrenschmidt	START_EXCEPTION(system_call)
6612d27cfd3SBenjamin Herrenschmidt	mr	r9,r13			/* keep a copy of userland r13 */
66225985edcSLucas De Marchi	mfspr	r11,SPRN_SRR0		/* get return address */
6632d27cfd3SBenjamin Herrenschmidt	mfspr	r12,SPRN_SRR1		/* get previous MSR */
664fecff0f7SMihai Caraman	mfspr	r13,SPRN_SPRG_PACA	/* get our PACA */
665fecff0f7SMihai Caraman	b	system_call_common
66631f71248SScott Wood
6679f2f79e3SBenjamin Herrenschmidt/* Auxiliary Processor Unavailable Interrupt */
668b1576fecSAnton Blanchard	START_EXCEPTION(ap_unavailable);
6690c2472deSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
6702d27cfd3SBenjamin Herrenschmidt				PROLOG_ADDITION_NONE)
6712d27cfd3SBenjamin Herrenschmidt	EXCEPTION_COMMON(0xf20)
6722d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
673fecff0f7SMihai Caraman	bl	unknown_exception
674fecff0f7SMihai Caraman	b	interrupt_return
6752d27cfd3SBenjamin Herrenschmidt
6762d27cfd3SBenjamin Herrenschmidt/* Debug exception as a critical interrupt*/
6772d27cfd3SBenjamin Herrenschmidt	START_EXCEPTION(debug_crit);
6782d27cfd3SBenjamin Herrenschmidt	CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
6792d27cfd3SBenjamin Herrenschmidt			      PROLOG_ADDITION_2REGS)
6802d27cfd3SBenjamin Herrenschmidt
6812d27cfd3SBenjamin Herrenschmidt	/*
6822d27cfd3SBenjamin Herrenschmidt	 * If there is a single step or branch-taken exception in an
6832d27cfd3SBenjamin Herrenschmidt	 * exception entry sequence, it was probably meant to apply to
6842d27cfd3SBenjamin Herrenschmidt	 * the code where the exception occurred (since exception entry
6852d27cfd3SBenjamin Herrenschmidt	 * doesn't turn off DE automatically).  We simulate the effect
6866cecf76bSScott Wood	 * of turning off DE on entry to an exception handler by turning
6872d27cfd3SBenjamin Herrenschmidt	 * off DE in the CSRR1 value and clearing the debug status.
6882d27cfd3SBenjamin Herrenschmidt	 */
689fd615f69SLiuHailong
6908e93fb33SNicholas Piggin	mfspr	r14,SPRN_DBSR		/* check single-step/branch taken */
6913569d84bSNicholas Piggin	andis.	r15,r14,(DBSR_IC|DBSR_BT)@h
6923569d84bSNicholas Piggin	beq+	1f
6932d27cfd3SBenjamin Herrenschmidt
6942d27cfd3SBenjamin Herrenschmidt#ifdef CONFIG_RELOCATABLE
695d7fb5b18SChristophe Leroy	__LOAD_PACA_TOC(r15)
696d7fb5b18SChristophe Leroy	LOAD_REG_ADDR_ALTTOC(r14, r15, interrupt_base_book3e)
697d7fb5b18SChristophe Leroy	LOAD_REG_ADDR_ALTTOC(r15, r15, __end_interrupts)
698d7fb5b18SChristophe Leroy	cmpld	cr0,r10,r14
699d7fb5b18SChristophe Leroy	cmpld	cr1,r10,r15
700d7fb5b18SChristophe Leroy#else
7012d27cfd3SBenjamin Herrenschmidt	LOAD_REG_IMMEDIATE_SYM(r14, r15, interrupt_base_book3e)
7022d27cfd3SBenjamin Herrenschmidt	cmpld	cr0, r10, r14
7032d27cfd3SBenjamin Herrenschmidt	LOAD_REG_IMMEDIATE_SYM(r14, r15, __end_interrupts)
7042d27cfd3SBenjamin Herrenschmidt	cmpld	cr1, r10, r14
7056cecf76bSScott Wood#endif
7062d27cfd3SBenjamin Herrenschmidt	blt+	cr0,1f
7072d27cfd3SBenjamin Herrenschmidt	bge+	cr1,1f
7082d27cfd3SBenjamin Herrenschmidt
7092d27cfd3SBenjamin Herrenschmidt	/* here it looks like we got an inappropriate debug exception. */
7102d27cfd3SBenjamin Herrenschmidt	lis	r14,(DBSR_IC|DBSR_BT)@h		/* clear the event */
7112d27cfd3SBenjamin Herrenschmidt	rlwinm	r11,r11,0,~MSR_DE	/* clear DE in the CSRR1 value */
7122d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_DBSR,r14
7132d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_CSRR1,r11
7142d27cfd3SBenjamin Herrenschmidt	lwz	r10,PACA_EXCRIT+EX_CR(r13)	/* restore registers */
7152d27cfd3SBenjamin Herrenschmidt	ld	r1,PACA_EXCRIT+EX_R1(r13)
7169d378dfaSScott Wood	ld	r14,PACA_EXCRIT+EX_R14(r13)
7172d27cfd3SBenjamin Herrenschmidt	ld	r15,PACA_EXCRIT+EX_R15(r13)
7182d27cfd3SBenjamin Herrenschmidt	mtcr	r10
7192d27cfd3SBenjamin Herrenschmidt	ld	r10,PACA_EXCRIT+EX_R10(r13)	/* restore registers */
7202d27cfd3SBenjamin Herrenschmidt	ld	r11,PACA_EXCRIT+EX_R11(r13)
7212d27cfd3SBenjamin Herrenschmidt	mfspr	r13,SPRN_SPRG_CRIT_SCRATCH
7222d27cfd3SBenjamin Herrenschmidt	rfci
7232d27cfd3SBenjamin Herrenschmidt
7242d27cfd3SBenjamin Herrenschmidt	/* Normal debug exception */
7252d27cfd3SBenjamin Herrenschmidt	/* XXX We only handle coming from userspace for now since we can't
7262d27cfd3SBenjamin Herrenschmidt	 *     quite save properly an interrupted kernel state yet
7272d27cfd3SBenjamin Herrenschmidt	 */
7282d27cfd3SBenjamin Herrenschmidt1:	andi.	r14,r11,MSR_PR;		/* check for userspace again */
7292d27cfd3SBenjamin Herrenschmidt	beq	kernel_dbg_exc;		/* if from kernel mode */
7302d27cfd3SBenjamin Herrenschmidt
7312d27cfd3SBenjamin Herrenschmidt	/* Now we mash up things to make it look like we are coming on a
7322d27cfd3SBenjamin Herrenschmidt	 * normal exception
733c6ac667bSNicholas Piggin	 */
734c6ac667bSNicholas Piggin	mfspr	r14,SPRN_DBSR
735b1576fecSAnton Blanchard	std	r14,_DSISR(r1)
7360c2472deSNicholas Piggin	ld	r14,PACA_EXCRIT+EX_R14(r13)
7370c2472deSNicholas Piggin	ld	r15,PACA_EXCRIT+EX_R15(r13)
7382d27cfd3SBenjamin Herrenschmidt	EXCEPTION_COMMON_CRIT(0xd00)
7392d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
7402d27cfd3SBenjamin Herrenschmidt	bl	DebugException
7412d27cfd3SBenjamin Herrenschmidt	REST_NVGPRS(r1)
742d36b4c4fSKumar Gala	b	interrupt_return
743d36b4c4fSKumar Gala
744fecff0f7SMihai Caramankernel_dbg_exc:
745fecff0f7SMihai Caraman	b	.	/* NYI */
746d36b4c4fSKumar Gala
747d36b4c4fSKumar Gala/* Debug exception as a debug interrupt*/
748d36b4c4fSKumar Gala	START_EXCEPTION(debug_debug);
749d36b4c4fSKumar Gala	DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
750d36b4c4fSKumar Gala						 PROLOG_ADDITION_2REGS)
751d36b4c4fSKumar Gala
752d36b4c4fSKumar Gala	/*
753d36b4c4fSKumar Gala	 * If there is a single step or branch-taken exception in an
754d36b4c4fSKumar Gala	 * exception entry sequence, it was probably meant to apply to
755d36b4c4fSKumar Gala	 * the code where the exception occurred (since exception entry
756d36b4c4fSKumar Gala	 * doesn't turn off DE automatically).  We simulate the effect
7576cecf76bSScott Wood	 * of turning off DE on entry to an exception handler by turning
758d36b4c4fSKumar Gala	 * off DE in the DSRR1 value and clearing the debug status.
759d36b4c4fSKumar Gala	 */
760fd615f69SLiuHailong
7618e93fb33SNicholas Piggin	mfspr	r14,SPRN_DBSR		/* check single-step/branch taken */
7623569d84bSNicholas Piggin	andis.	r15,r14,(DBSR_IC|DBSR_BT)@h
7633569d84bSNicholas Piggin	beq+	1f
764d36b4c4fSKumar Gala
765d36b4c4fSKumar Gala#ifdef CONFIG_RELOCATABLE
766d7fb5b18SChristophe Leroy	__LOAD_PACA_TOC(r15)
767d7fb5b18SChristophe Leroy	LOAD_REG_ADDR_ALTTOC(r14, r15, interrupt_base_book3e)
768d7fb5b18SChristophe Leroy	LOAD_REG_ADDR_ALTTOC(r15, r15, __end_interrupts)
769d7fb5b18SChristophe Leroy	cmpld	cr0,r10,r14
770d7fb5b18SChristophe Leroy	cmpld	cr1,r10,r15
771d7fb5b18SChristophe Leroy#else
772d36b4c4fSKumar Gala	LOAD_REG_IMMEDIATE_SYM(r14, r15, interrupt_base_book3e)
773d36b4c4fSKumar Gala	cmpld	cr0, r10, r14
774d36b4c4fSKumar Gala	LOAD_REG_IMMEDIATE_SYM(r14, r15,__end_interrupts)
775d36b4c4fSKumar Gala	cmpld	cr1, r10, r14
7766cecf76bSScott Wood#endif
777d36b4c4fSKumar Gala	blt+	cr0,1f
778d36b4c4fSKumar Gala	bge+	cr1,1f
779d36b4c4fSKumar Gala
780d36b4c4fSKumar Gala	/* here it looks like we got an inappropriate debug exception. */
781d36b4c4fSKumar Gala	lis	r14,(DBSR_IC|DBSR_BT)@h		/* clear the event */
782d36b4c4fSKumar Gala	rlwinm	r11,r11,0,~MSR_DE	/* clear DE in the DSRR1 value */
783d36b4c4fSKumar Gala	mtspr	SPRN_DBSR,r14
784d36b4c4fSKumar Gala	mtspr	SPRN_DSRR1,r11
785d36b4c4fSKumar Gala	lwz	r10,PACA_EXDBG+EX_CR(r13)	/* restore registers */
786d36b4c4fSKumar Gala	ld	r1,PACA_EXDBG+EX_R1(r13)
787d36b4c4fSKumar Gala	ld	r14,PACA_EXDBG+EX_R14(r13)
788d36b4c4fSKumar Gala	ld	r15,PACA_EXDBG+EX_R15(r13)
789d36b4c4fSKumar Gala	mtcr	r10
790d36b4c4fSKumar Gala	ld	r10,PACA_EXDBG+EX_R10(r13)	/* restore registers */
791d36b4c4fSKumar Gala	ld	r11,PACA_EXDBG+EX_R11(r13)
792d36b4c4fSKumar Gala	mfspr	r13,SPRN_SPRG_DBG_SCRATCH
793d36b4c4fSKumar Gala	rfdi
794d36b4c4fSKumar Gala
795d36b4c4fSKumar Gala	/* Normal debug exception */
796d36b4c4fSKumar Gala	/* XXX We only handle coming from userspace for now since we can't
797d36b4c4fSKumar Gala	 *     quite save properly an interrupted kernel state yet
798d36b4c4fSKumar Gala	 */
799d36b4c4fSKumar Gala1:	andi.	r14,r11,MSR_PR;		/* check for userspace again */
800d36b4c4fSKumar Gala	beq	kernel_dbg_exc;		/* if from kernel mode */
801d36b4c4fSKumar Gala
802d36b4c4fSKumar Gala	/* Now we mash up things to make it look like we are coming on a
803d36b4c4fSKumar Gala	 * normal exception
804c6ac667bSNicholas Piggin	 */
805c6ac667bSNicholas Piggin	mfspr	r14,SPRN_DBSR
806b1576fecSAnton Blanchard	std	r14,_DSISR(r1)
8070c2472deSNicholas Piggin	ld	r14,PACA_EXDBG+EX_R14(r13)
8080c2472deSNicholas Piggin	ld	r15,PACA_EXDBG+EX_R15(r13)
809d36b4c4fSKumar Gala	EXCEPTION_COMMON_DBG(0xd08)
8107230c564SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
811fecff0f7SMihai Caraman	bl	DebugException
812fecff0f7SMihai Caraman	REST_NVGPRS(r1)
81331f71248SScott Wood	b	interrupt_return
814e4867336SKevin Hao
8157230c564SBenjamin Herrenschmidt	START_EXCEPTION(perfmon);
816*a073672eSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
817*a073672eSNicholas Piggin				PROLOG_ADDITION_NONE)
818*a073672eSNicholas Piggin	EXCEPTION_COMMON(0x260)
819*a073672eSNicholas Piggin	CHECK_NAPPING()
820*a073672eSNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
821*a073672eSNicholas Piggin	/*
822*a073672eSNicholas Piggin	 * XXX: Returning from performance_monitor_exception taken as a
823b1576fecSAnton Blanchard	 * soft-NMI (Linux irqs disabled) may be risky to use interrupt_return
8240c2472deSNicholas Piggin	 * and could cause bugs in return or elsewhere. That case should just
8253a6e9bd7SScott Wood	 * restore registers and return. There is a workaround for one known
82689c81797SBenjamin Herrenschmidt	 * problem in interrupt_exit_kernel_prepare().
827fecff0f7SMihai Caraman	 */
82835425501SAnton Blanchard	bl	performance_monitor_exception
82989c81797SBenjamin Herrenschmidt	b	interrupt_return
83089c81797SBenjamin Herrenschmidt
83189c81797SBenjamin Herrenschmidt/* Doorbell interrupt */
832fecff0f7SMihai Caraman	MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
833fecff0f7SMihai Caraman			   doorbell, doorbell_exception, ACK_NONE)
834609af38fSScott Wood
835609af38fSScott Wood/* Doorbell critical Interrupt */
836609af38fSScott Wood	START_EXCEPTION(doorbell_crit);
837609af38fSScott Wood	CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
8383db8aa10SNicholas Piggin			      PROLOG_ADDITION_NONE)
839609af38fSScott Wood	EXCEPTION_COMMON_CRIT(0x2a0)
84089c81797SBenjamin Herrenschmidt	bl	special_reg_save
8415473eb1cSMihai Caraman	CHECK_NAPPING();
8425473eb1cSMihai Caraman	addi	r3,r1,STACK_INT_FRAME_REGS
8435473eb1cSMihai Caraman	bl	unknown_nmi_exception
8445473eb1cSMihai Caraman	b	ret_from_crit_except
8455473eb1cSMihai Caraman
846fecff0f7SMihai Caraman/*
847fecff0f7SMihai Caraman *	Guest doorbell interrupt
84831f71248SScott Wood *	This general exception use GSRRx save/restore registers
8495473eb1cSMihai Caraman */
850b1576fecSAnton Blanchard	START_EXCEPTION(guest_doorbell);
8510c2472deSNicholas Piggin	GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
8523a6e9bd7SScott Wood			        PROLOG_ADDITION_NONE)
8537230c564SBenjamin Herrenschmidt	EXCEPTION_COMMON(0x2c0)
8547230c564SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
855fecff0f7SMihai Caraman	bl	unknown_exception
856fecff0f7SMihai Caraman	b	interrupt_return
857609af38fSScott Wood
858609af38fSScott Wood/* Guest Doorbell critical Interrupt */
859609af38fSScott Wood	START_EXCEPTION(guest_doorbell_crit);
860609af38fSScott Wood	CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
8613db8aa10SNicholas Piggin			      PROLOG_ADDITION_NONE)
862609af38fSScott Wood	EXCEPTION_COMMON_CRIT(0x2e0)
8637230c564SBenjamin Herrenschmidt	bl	special_reg_save
8647230c564SBenjamin Herrenschmidt	CHECK_NAPPING();
8657230c564SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
866fecff0f7SMihai Caraman	bl	unknown_nmi_exception
867fecff0f7SMihai Caraman	b	ret_from_crit_except
86831f71248SScott Wood
8697230c564SBenjamin Herrenschmidt/* Hypervisor call */
870b1576fecSAnton Blanchard	START_EXCEPTION(hypercall);
8710c2472deSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
8727230c564SBenjamin Herrenschmidt			        PROLOG_ADDITION_NONE)
8737230c564SBenjamin Herrenschmidt	EXCEPTION_COMMON(0x310)
8747230c564SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
875fecff0f7SMihai Caraman	bl	unknown_exception
876fecff0f7SMihai Caraman	b	interrupt_return
87731f71248SScott Wood
8787230c564SBenjamin Herrenschmidt/* Embedded Hypervisor priviledged  */
879b1576fecSAnton Blanchard	START_EXCEPTION(ehpriv);
8800c2472deSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
8812d27cfd3SBenjamin Herrenschmidt			        PROLOG_ADDITION_NONE)
882228b1a47SMihai Caraman	EXCEPTION_COMMON(0x320)
883228b1a47SMihai Caraman	addi	r3,r1,STACK_INT_FRAME_REGS
884228b1a47SMihai Caraman	bl	unknown_exception
885228b1a47SMihai Caraman	b	interrupt_return
88631f71248SScott Wood
887228b1a47SMihai Caraman/* LRAT Error interrupt */
888ae88f7b9SNicholas Piggin	START_EXCEPTION(lrat_error);
8890c2472deSNicholas Piggin	NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
890228b1a47SMihai Caraman			        PROLOG_ADDITION_NONE)
891f23699c9SNicholas Piggin	EXCEPTION_COMMON(0x340)
892fce01acfSNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
8938e93fb33SNicholas Piggin	bl	unknown_exception
8943569d84bSNicholas Piggin	b	interrupt_return
8953569d84bSNicholas Piggin
896fce01acfSNicholas Piggin.macro SEARCH_RESTART_TABLE
897f23699c9SNicholas Piggin#ifdef CONFIG_RELOCATABLE
898f23699c9SNicholas Piggin	__LOAD_PACA_TOC(r11)
899fce01acfSNicholas Piggin	LOAD_REG_ADDR_ALTTOC(r14, r11, __start___restart_table)
900f23699c9SNicholas Piggin	LOAD_REG_ADDR_ALTTOC(r15, r11, __stop___restart_table)
901f23699c9SNicholas Piggin#else
902f23699c9SNicholas Piggin	LOAD_REG_IMMEDIATE_SYM(r14, r11, __start___restart_table)
903f23699c9SNicholas Piggin	LOAD_REG_IMMEDIATE_SYM(r15, r11, __stop___restart_table)
904f23699c9SNicholas Piggin#endif
905f23699c9SNicholas Piggin300:
906f23699c9SNicholas Piggin	cmpd	r14,r15
907f23699c9SNicholas Piggin	beq	302f
908f23699c9SNicholas Piggin	ld	r11,0(r14)
909f23699c9SNicholas Piggin	cmpld	r10,r11
910f23699c9SNicholas Piggin	blt	301f
911f23699c9SNicholas Piggin	ld	r11,8(r14)
912f23699c9SNicholas Piggin	cmpld	r10,r11
913f23699c9SNicholas Piggin	bge	301f
914f23699c9SNicholas Piggin	ld	r11,16(r14)
915f23699c9SNicholas Piggin	b	303f
916f23699c9SNicholas Piggin301:
917f23699c9SNicholas Piggin	addi	r14,r14,24
918f23699c9SNicholas Piggin	b	300b
9192d27cfd3SBenjamin Herrenschmidt302:
9207230c564SBenjamin Herrenschmidt	li	r11,0
9217230c564SBenjamin Herrenschmidt303:
9226cc3f91bSNicholas Piggin.endm
9236cc3f91bSNicholas Piggin
9242d27cfd3SBenjamin Herrenschmidt/*
9253d97a619SScott Wood * An interrupt came in while soft-disabled; We mark paca->irq_happened
92679b5c8dbSMihai Caraman * accordingly and if the interrupt is level sensitive, we hard disable
927f23699c9SNicholas Piggin * hard disable (full_mask) corresponds to PACA_IRQ_MUST_HARD_MASK, so
928f23699c9SNicholas Piggin * keep these in synch.
929f23699c9SNicholas Piggin */
9307230c564SBenjamin Herrenschmidt
9319b81c021SNicholas Piggin.macro masked_interrupt_book3e paca_irq full_mask
9329b81c021SNicholas Piggin	std	r14,PACA_EXGEN+EX_R14(r13)
9339b81c021SNicholas Piggin	std	r15,PACA_EXGEN+EX_R15(r13)
93479b5c8dbSMihai Caraman
9359b81c021SNicholas Piggin	lbz	r10,PACAIRQHAPPENED(r13)
9367230c564SBenjamin Herrenschmidt	.if \full_mask == 1
93779b5c8dbSMihai Caraman	ori	r10,r10,\paca_irq | PACA_IRQ_HARD_DIS
93879b5c8dbSMihai Caraman	.else
939f23699c9SNicholas Piggin	ori	r10,r10,\paca_irq
94079b5c8dbSMihai Caraman	.endif
94179b5c8dbSMihai Caraman	stb	r10,PACAIRQHAPPENED(r13)
94279b5c8dbSMihai Caraman
943f23699c9SNicholas Piggin	.if \full_mask == 1
944f23699c9SNicholas Piggin	xori	r11,r11,MSR_EE		/* clear MSR_EE */
945f23699c9SNicholas Piggin	mtspr	SPRN_SRR1,r11
946f23699c9SNicholas Piggin	.endif
947f23699c9SNicholas Piggin
948f23699c9SNicholas Piggin	mfspr	r10,SPRN_SRR0
949f23699c9SNicholas Piggin	SEARCH_RESTART_TABLE
95079b5c8dbSMihai Caraman	cmpdi	r11,0
95179b5c8dbSMihai Caraman	beq	1f
95279b5c8dbSMihai Caraman	mtspr	SPRN_SRR0,r11		/* return to restart address */
95379b5c8dbSMihai Caraman1:
954f23699c9SNicholas Piggin
955f23699c9SNicholas Piggin	lwz	r11,PACA_EXGEN+EX_CR(r13)
95679b5c8dbSMihai Caraman	mtcr	r11
9572d27cfd3SBenjamin Herrenschmidt	ld	r10,PACA_EXGEN+EX_R10(r13)
9582d27cfd3SBenjamin Herrenschmidt	ld	r11,PACA_EXGEN+EX_R11(r13)
95979b5c8dbSMihai Caraman	ld	r14,PACA_EXGEN+EX_R14(r13)
96079b5c8dbSMihai Caraman	ld	r15,PACA_EXGEN+EX_R15(r13)
96179b5c8dbSMihai Caraman	mfspr	r13,SPRN_SPRG_GEN_SCRATCH
96279b5c8dbSMihai Caraman	rfi
96379b5c8dbSMihai Caraman	b	.
96479b5c8dbSMihai Caraman.endm
96579b5c8dbSMihai Caraman
96679b5c8dbSMihai Caramanmasked_interrupt_book3e_0x500:
96779b5c8dbSMihai Caraman	masked_interrupt_book3e PACA_IRQ_EE 1
96879b5c8dbSMihai Caraman
96979b5c8dbSMihai Caramanmasked_interrupt_book3e_0x900:
97079b5c8dbSMihai Caraman	ACK_DEC(r10);
97179b5c8dbSMihai Caraman	masked_interrupt_book3e PACA_IRQ_DEC 0
97279b5c8dbSMihai Caraman
97379b5c8dbSMihai Caramanmasked_interrupt_book3e_0x980:
97479b5c8dbSMihai Caraman	ACK_FIT(r10);
97579b5c8dbSMihai Caraman	masked_interrupt_book3e PACA_IRQ_DEC 0
9767230c564SBenjamin Herrenschmidt
9772d27cfd3SBenjamin Herrenschmidtmasked_interrupt_book3e_0x280:
9782d27cfd3SBenjamin Herrenschmidtmasked_interrupt_book3e_0x2c0:
9792d27cfd3SBenjamin Herrenschmidt	masked_interrupt_book3e PACA_IRQ_DBELL 0
9802d27cfd3SBenjamin Herrenschmidt
9812d27cfd3SBenjamin Herrenschmidt/*
9822d27cfd3SBenjamin Herrenschmidt * This is called from 0x300 and 0x400 handlers after the prologs with
983b1576fecSAnton Blanchard * r14 and r15 containing the fault address and error code, with the
9840c2472deSNicholas Piggin * original values stashed away in the PACA
9852d27cfd3SBenjamin Herrenschmidt */
9862d27cfd3SBenjamin HerrenschmidtSYM_CODE_START_LOCAL(storage_fault_common)
9872d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
9882d27cfd3SBenjamin Herrenschmidt	bl	do_page_fault
9892d27cfd3SBenjamin Herrenschmidt	b	interrupt_return
9902d27cfd3SBenjamin HerrenschmidtSYM_CODE_END(storage_fault_common)
9912d27cfd3SBenjamin Herrenschmidt
992b1576fecSAnton Blanchard/*
9936cc0c16dSNicholas Piggin * Alignment exception doesn't fit entirely in the 0x100 bytes so it
9940c2472deSNicholas Piggin * continues here.
9956cc0c16dSNicholas Piggin */
9966cc0c16dSNicholas PigginSYM_CODE_START_LOCAL(alignment_more)
9972d27cfd3SBenjamin Herrenschmidt	addi	r3,r1,STACK_INT_FRAME_REGS
9982d27cfd3SBenjamin Herrenschmidt	bl	alignment_exception
9992d27cfd3SBenjamin Herrenschmidt	REST_NVGPRS(r1)
10002d27cfd3SBenjamin Herrenschmidt	b	interrupt_return
10012d27cfd3SBenjamin HerrenschmidtSYM_CODE_END(alignment_more)
10022d27cfd3SBenjamin Herrenschmidt
10032d27cfd3SBenjamin Herrenschmidt/*
10042d27cfd3SBenjamin Herrenschmidt * Trampolines used when spotting a bad kernel stack pointer in
10052d27cfd3SBenjamin Herrenschmidt * the exception entry code.
1006cd66cc2eSKumar Gala *
10073a6e9bd7SScott Wood * TODO: move some bits like SRR0 read to trampoline, pass PACA
10087230c564SBenjamin Herrenschmidt * index around, etc... to handle crit & mcheck
10097230c564SBenjamin Herrenschmidt */
10103a6e9bd7SScott WoodBAD_STACK_TRAMPOLINE(0x000)
10113a6e9bd7SScott WoodBAD_STACK_TRAMPOLINE(0x100)
10122d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x200)
10133a6e9bd7SScott WoodBAD_STACK_TRAMPOLINE(0x220)
10143a6e9bd7SScott WoodBAD_STACK_TRAMPOLINE(0x260)
1015228b1a47SMihai CaramanBAD_STACK_TRAMPOLINE(0x280)
10162d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x2a0)
10172d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x2c0)
10182d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x2e0)
10192d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x300)
10202d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x310)
10212d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x320)
10222d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x340)
10232d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x400)
10242d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x500)
10252d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x600)
10262d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x700)
10272d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x800)
10287230c564SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x900)
10292d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x980)
10302d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0x9f0)
10312d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xa00)
10322d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xb00)
10332d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xc00)
10342d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xd00)
10352d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xd08)
10362d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xe00)
10372d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xf00)
10382d27cfd3SBenjamin HerrenschmidtBAD_STACK_TRAMPOLINE(0xf20)
10392d27cfd3SBenjamin Herrenschmidt
10402d27cfd3SBenjamin Herrenschmidt_GLOBAL(bad_stack_book3e)
10412d27cfd3SBenjamin Herrenschmidt	/* XXX: Needs to make SPRN_SPRG_GEN depend on exception type */
10422d27cfd3SBenjamin Herrenschmidt	mfspr	r10,SPRN_SRR0;		  /* read SRR0 before touching stack */
10432d27cfd3SBenjamin Herrenschmidt	ld	r1,PACAEMERGSP(r13)
10442d27cfd3SBenjamin Herrenschmidt	subi	r1,r1,64+INT_FRAME_SIZE
10452d27cfd3SBenjamin Herrenschmidt	std	r10,_NIP(r1)
10462d27cfd3SBenjamin Herrenschmidt	std	r11,_MSR(r1)
1047d9db6e42SXiongwei Song	ld	r10,PACA_EXGEN+EX_R1(r13) /* FIXME for crit & mcheck */
1048cfa47772SXiongwei Song	lwz	r11,PACA_EXGEN+EX_CR(r13) /* FIXME for crit & mcheck */
104953ecaa67SRohan McLure	std	r10,GPR1(r1)
105053ecaa67SRohan McLure	std	r11,_CCR(r1)
10512d27cfd3SBenjamin Herrenschmidt	mfspr	r10,SPRN_DEAR
10522d27cfd3SBenjamin Herrenschmidt	mfspr	r11,SPRN_ESR
10532d27cfd3SBenjamin Herrenschmidt	std	r10,_DEAR(r1)
10542d27cfd3SBenjamin Herrenschmidt	std	r11,_ESR(r1)
10552d27cfd3SBenjamin Herrenschmidt	SAVE_GPR(0, r1);		/* save r0 in stackframe */	    \
105653ecaa67SRohan McLure	SAVE_GPRS(2, 9, r1);		/* save r2 - r9 in stackframe */    \
10572d27cfd3SBenjamin Herrenschmidt	ld	r3,PACA_EXGEN+EX_R10(r13);/* get back r10 */		    \
10582d27cfd3SBenjamin Herrenschmidt	ld	r4,PACA_EXGEN+EX_R11(r13);/* get back r11 */		    \
10592d27cfd3SBenjamin Herrenschmidt	mfspr	r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 XXX can be wrong */ \
10602d27cfd3SBenjamin Herrenschmidt	std	r3,GPR10(r1);		/* save r10 to stackframe */	    \
10612d27cfd3SBenjamin Herrenschmidt	std	r4,GPR11(r1);		/* save r11 to stackframe */	    \
10622d27cfd3SBenjamin Herrenschmidt	SAVE_GPR(12, r1);		/* save r12 in stackframe */	    \
10632d27cfd3SBenjamin Herrenschmidt	std	r5,GPR13(r1);		/* save it to stackframe */	    \
106453ecaa67SRohan McLure	mflr	r10
10652d27cfd3SBenjamin Herrenschmidt	mfctr	r11
10662d27cfd3SBenjamin Herrenschmidt	mfxer	r12
10672d27cfd3SBenjamin Herrenschmidt	std	r10,_LINK(r1)
10682d27cfd3SBenjamin Herrenschmidt	std	r11,_CTR(r1)
106953ecaa67SRohan McLure	std	r12,_XER(r1)
10702d27cfd3SBenjamin Herrenschmidt	SAVE_NVGPRS(r1)
10718e93fb33SNicholas Piggin	lhz	r12,PACA_TRAP_SAVE(r13)
10722d27cfd3SBenjamin Herrenschmidt	std	r12,_TRAP(r1)
1073b1576fecSAnton Blanchard	addi	r11,r1,INT_FRAME_SIZE
10742d27cfd3SBenjamin Herrenschmidt	std	r11,0(r1)
10752d27cfd3SBenjamin Herrenschmidt	ZEROIZE_GPR(12)
10762d27cfd3SBenjamin Herrenschmidt	std	r12,0(r11)
10772d27cfd3SBenjamin Herrenschmidt	LOAD_PACA_TOC()
10782d27cfd3SBenjamin Herrenschmidt1:	addi	r3,r1,STACK_INT_FRAME_REGS
10792d27cfd3SBenjamin Herrenschmidt	bl	kernel_bad_stack
10802d27cfd3SBenjamin Herrenschmidt	b	1b
10812d27cfd3SBenjamin Herrenschmidt
10822d27cfd3SBenjamin Herrenschmidt/*
1083bb1af71eSKumar Gala * Setup the initial TLB for a core. This current implementation
1084bb1af71eSKumar Gala * assume that whatever we are running off will not conflict with
1085bb1af71eSKumar Gala * the new mapping at PAGE_OFFSET.
1086bb1af71eSKumar Gala */
1087bb1af71eSKumar Gala_GLOBAL(initial_tlb_book3e)
1088bb1af71eSKumar Gala
1089bb1af71eSKumar Gala	/* Look for the first TLB with IPROT set */
1090bb1af71eSKumar Gala	mfspr	r4,SPRN_TLB0CFG
1091bb1af71eSKumar Gala	andi.	r3,r4,TLBnCFG_IPROT
1092bb1af71eSKumar Gala	lis	r3,MAS0_TLBSEL(0)@h
1093bb1af71eSKumar Gala	bne	found_iprot
1094bb1af71eSKumar Gala
1095bb1af71eSKumar Gala	mfspr	r4,SPRN_TLB1CFG
1096bb1af71eSKumar Gala	andi.	r3,r4,TLBnCFG_IPROT
1097bb1af71eSKumar Gala	lis	r3,MAS0_TLBSEL(1)@h
1098bb1af71eSKumar Gala	bne	found_iprot
1099bb1af71eSKumar Gala
1100bb1af71eSKumar Gala	mfspr	r4,SPRN_TLB2CFG
1101bb1af71eSKumar Gala	andi.	r3,r4,TLBnCFG_IPROT
1102bb1af71eSKumar Gala	lis	r3,MAS0_TLBSEL(2)@h
1103bb1af71eSKumar Gala	bne	found_iprot
1104bb1af71eSKumar Gala
1105bb1af71eSKumar Gala	lis	r3,MAS0_TLBSEL(3)@h
1106bb1af71eSKumar Gala	mfspr	r4,SPRN_TLB3CFG
1107bb1af71eSKumar Gala	/* fall through */
1108bb1af71eSKumar Gala
1109bb1af71eSKumar Galafound_iprot:
1110bb1af71eSKumar Gala	andi.	r5,r4,TLBnCFG_HES
1111bb1af71eSKumar Gala	bne	have_hes
1112bb1af71eSKumar Gala
1113f5007dbfSChristophe Leroy	mflr	r8				/* save LR */
1114bb1af71eSKumar Gala/* 1. Find the index of the entry we're executing in
1115bb1af71eSKumar Gala *
1116bb1af71eSKumar Gala * r3 = MAS0_TLBSEL (for the iprot array)
1117bb1af71eSKumar Gala * r4 = SPRN_TLBnCFG
1118bb1af71eSKumar Gala */
1119bb1af71eSKumar Gala	bcl	20,31,$+4			/* Find our address */
1120bb1af71eSKumar Galainvstr:	mflr	r6				/* Make it accessible */
1121bb1af71eSKumar Gala	mfmsr	r7
1122bb1af71eSKumar Gala	rlwinm	r5,r7,27,31,31			/* extract MSR[IS] */
1123bb1af71eSKumar Gala	mfspr	r7,SPRN_PID
1124bb1af71eSKumar Gala	slwi	r7,r7,16
1125bb1af71eSKumar Gala	or	r7,r7,r5
1126bb1af71eSKumar Gala	mtspr	SPRN_MAS6,r7
1127bb1af71eSKumar Gala	tlbsx	0,r6				/* search MSR[IS], SPID=PID */
1128bb1af71eSKumar Gala
1129bb1af71eSKumar Gala	mfspr	r3,SPRN_MAS0
1130bb1af71eSKumar Gala	rlwinm	r5,r3,16,20,31			/* Extract MAS0(Entry) */
1131bb1af71eSKumar Gala
1132bb1af71eSKumar Gala	mfspr	r7,SPRN_MAS1			/* Insure IPROT set */
1133bb1af71eSKumar Gala	oris	r7,r7,MAS1_IPROT@h
1134bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r7
1135bb1af71eSKumar Gala	tlbwe
1136bb1af71eSKumar Gala
1137bb1af71eSKumar Gala/* 2. Invalidate all entries except the entry we're executing in
1138bb1af71eSKumar Gala *
1139bb1af71eSKumar Gala * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
1140bb1af71eSKumar Gala * r4 = SPRN_TLBnCFG
1141bb1af71eSKumar Gala * r5 = ESEL of entry we are running in
1142bb1af71eSKumar Gala */
1143bb1af71eSKumar Gala	andi.	r4,r4,TLBnCFG_N_ENTRY		/* Extract # entries */
1144bb1af71eSKumar Gala	li	r6,0				/* Set Entry counter to 0 */
1145bb1af71eSKumar Gala1:	mr	r7,r3				/* Set MAS0(TLBSEL) */
1146bb1af71eSKumar Gala	rlwimi	r7,r6,16,4,15			/* Setup MAS0 = TLBSEL | ESEL(r6) */
1147bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r7
1148bb1af71eSKumar Gala	tlbre
1149bb1af71eSKumar Gala	mfspr	r7,SPRN_MAS1
1150bb1af71eSKumar Gala	rlwinm	r7,r7,0,2,31			/* Clear MAS1 Valid and IPROT */
1151bb1af71eSKumar Gala	cmpw	r5,r6
1152bb1af71eSKumar Gala	beq	skpinv				/* Dont update the current execution TLB */
1153bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r7
1154bb1af71eSKumar Gala	tlbwe
1155962cffbdSMichael Neuling	isync
1156bb1af71eSKumar Galaskpinv:	addi	r6,r6,1				/* Increment */
1157bb1af71eSKumar Gala	cmpw	r6,r4				/* Are we done? */
1158bb1af71eSKumar Gala	bne	1b				/* If not, repeat */
1159bb1af71eSKumar Gala
1160bb1af71eSKumar Gala	/* Invalidate all TLBs */
1161bb1af71eSKumar Gala	PPC_TLBILX_ALL(0,R0)
1162bb1af71eSKumar Gala	sync
1163bb1af71eSKumar Gala	isync
1164bb1af71eSKumar Gala
1165bb1af71eSKumar Gala/* 3. Setup a temp mapping and jump to it
1166bb1af71eSKumar Gala *
1167bb1af71eSKumar Gala * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
1168bb1af71eSKumar Gala * r5 = ESEL of entry we are running in
1169bb1af71eSKumar Gala */
1170bb1af71eSKumar Gala	andi.	r7,r5,0x1	/* Find an entry not used and is non-zero */
1171bb1af71eSKumar Gala	addi	r7,r7,0x1
1172bb1af71eSKumar Gala	mr	r4,r3		/* Set MAS0(TLBSEL) = 1 */
1173bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r4
1174bb1af71eSKumar Gala	tlbre
1175bb1af71eSKumar Gala
1176bb1af71eSKumar Gala	rlwimi	r4,r7,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r7) */
1177bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r4
1178bb1af71eSKumar Gala
1179bb1af71eSKumar Gala	mfspr	r7,SPRN_MAS1
1180bb1af71eSKumar Gala	xori	r6,r7,MAS1_TS		/* Setup TMP mapping in the other Address space */
1181bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r6
1182f5007dbfSChristophe Leroy
1183bb1af71eSKumar Gala	tlbwe
1184bb1af71eSKumar Gala
1185bb1af71eSKumar Gala	mfmsr	r6
1186bb1af71eSKumar Gala	xori	r6,r6,MSR_IS
1187bb1af71eSKumar Gala	mtspr	SPRN_SRR1,r6
1188bb1af71eSKumar Gala	bcl	20,31,$+4	/* Find our address */
1189bb1af71eSKumar Gala1:	mflr	r6
1190bb1af71eSKumar Gala	addi	r6,r6,(2f - 1b)
1191bb1af71eSKumar Gala	mtspr	SPRN_SRR0,r6
1192bb1af71eSKumar Gala	rfi
1193bb1af71eSKumar Gala2:
1194bb1af71eSKumar Gala
1195bb1af71eSKumar Gala/* 4. Clear out PIDs & Search info
1196bb1af71eSKumar Gala *
1197bb1af71eSKumar Gala * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1198bb1af71eSKumar Gala * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1199bb1af71eSKumar Gala * r5 = MAS3
1200bb1af71eSKumar Gala */
1201bb1af71eSKumar Gala	li	r6,0
1202bb1af71eSKumar Gala	mtspr   SPRN_MAS6,r6
1203bb1af71eSKumar Gala	mtspr	SPRN_PID,r6
1204bb1af71eSKumar Gala
1205bb1af71eSKumar Gala/* 5. Invalidate mapping we started in
1206bb1af71eSKumar Gala *
1207bb1af71eSKumar Gala * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1208ed2ddc56SDiana Craciun * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1209bb1af71eSKumar Gala * r5 = MAS3
1210bb1af71eSKumar Gala */
1211bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r3
1212bb1af71eSKumar Gala	tlbre
1213bb1af71eSKumar Gala	mfspr	r6,SPRN_MAS1
1214bb1af71eSKumar Gala	rlwinm	r6,r6,0,2,31	/* clear IPROT and VALID */
1215bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r6
1216bb1af71eSKumar Gala	tlbwe
1217bb1af71eSKumar Gala	sync
1218bb1af71eSKumar Gala	isync
1219bb1af71eSKumar Gala
1220bb1af71eSKumar Gala/* 6. Setup KERNELBASE mapping in TLB[0]
1221bb1af71eSKumar Gala *
1222bb1af71eSKumar Gala * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1223bb1af71eSKumar Gala * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1224bb1af71eSKumar Gala * r5 = MAS3
1225bb1af71eSKumar Gala */
12268054df05SJason Yan	rlwinm	r3,r3,0,16,3	/* clear ESEL */
1227bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r3
1228bb1af71eSKumar Gala	lis	r6,(MAS1_VALID|MAS1_IPROT)@h
1229bb1af71eSKumar Gala	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
1230bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r6
1231bb1af71eSKumar Gala
1232bb1af71eSKumar Gala	LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | MAS2_M_IF_NEEDED)
1233bb1af71eSKumar Gala	mtspr	SPRN_MAS2,r6
1234bb1af71eSKumar Gala
1235bb1af71eSKumar Gala	rlwinm	r5,r5,0,0,25
1236bb1af71eSKumar Gala	ori	r5,r5,MAS3_SR | MAS3_SW | MAS3_SX
1237bb1af71eSKumar Gala	mtspr	SPRN_MAS3,r5
1238bb1af71eSKumar Gala	li	r5,-1
1239bb1af71eSKumar Gala	rlwinm	r5,r5,0,0,25
1240bb1af71eSKumar Gala
1241bb1af71eSKumar Gala	tlbwe
1242f5007dbfSChristophe Leroy
12431cb6e064STiejun Chen/* 7. Jump to KERNELBASE mapping
12441cb6e064STiejun Chen *
12451cb6e064STiejun Chen * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1246bb1af71eSKumar Gala */
1247bb1af71eSKumar Gala	/* Now we branch the new virtual address mapped by this entry */
1248bb1af71eSKumar Gala	bcl	20,31,$+4	/* Find our address */
1249bb1af71eSKumar Gala1:	mflr	r6
1250bb1af71eSKumar Gala	addi	r6,r6,(2f - 1b)
1251bb1af71eSKumar Gala	tovirt(r6,r6)
1252bb1af71eSKumar Gala	lis	r7,MSR_KERNEL@h
1253bb1af71eSKumar Gala	ori	r7,r7,MSR_KERNEL@l
1254bb1af71eSKumar Gala	mtspr	SPRN_SRR0,r6
1255bb1af71eSKumar Gala	mtspr	SPRN_SRR1,r7
1256bb1af71eSKumar Gala	rfi				/* start execution out of TLB1[0] entry */
1257bb1af71eSKumar Gala2:
1258bb1af71eSKumar Gala
1259bb1af71eSKumar Gala/* 8. Clear out the temp mapping
1260ed2ddc56SDiana Craciun *
1261bb1af71eSKumar Gala * r4 = MAS0 w/TLBSEL & ESEL for the entry we are running in
1262bb1af71eSKumar Gala */
1263bb1af71eSKumar Gala	mtspr	SPRN_MAS0,r4
1264bb1af71eSKumar Gala	tlbre
1265bb1af71eSKumar Gala	mfspr	r5,SPRN_MAS1
1266bb1af71eSKumar Gala	rlwinm	r5,r5,0,2,31	/* clear IPROT and VALID */
1267bb1af71eSKumar Gala	mtspr	SPRN_MAS1,r5
1268bb1af71eSKumar Gala	tlbwe
1269bb1af71eSKumar Gala	sync
1270bb1af71eSKumar Gala	isync
1271bb1af71eSKumar Gala
12722d27cfd3SBenjamin Herrenschmidt	/* We translate LR and return */
12732d27cfd3SBenjamin Herrenschmidt	tovirt(r8,r8)
12742d27cfd3SBenjamin Herrenschmidt	mtlr	r8
12752d27cfd3SBenjamin Herrenschmidt	blr
12762d27cfd3SBenjamin Herrenschmidt
1277a1d0d98dSDavid Gibsonhave_hes:
1278a1d0d98dSDavid Gibson	/* Setup MAS 0,1,2,3 and 7 for tlbwe of a 1G entry that maps the
1279a1d0d98dSDavid Gibson	 * kernel linear mapping. We also set MAS8 once for all here though
1280a1d0d98dSDavid Gibson	 * that will have to be made dependent on whether we are running under
1281a1d0d98dSDavid Gibson	 * a hypervisor I suppose.
1282a1d0d98dSDavid Gibson	 */
1283a1d0d98dSDavid Gibson
1284a1d0d98dSDavid Gibson	/* BEWARE, MAGIC
1285a1d0d98dSDavid Gibson	 * This code is called as an ordinary function on the boot CPU. But to
1286a1d0d98dSDavid Gibson	 * avoid duplication, this code is also used in SCOM bringup of
1287a1d0d98dSDavid Gibson	 * secondary CPUs. We read the code between the initial_tlb_code_start
1288a1d0d98dSDavid Gibson	 * and initial_tlb_code_end labels one instruction at a time and RAM it
1289a1d0d98dSDavid Gibson	 * into the new core via SCOM. That doesn't process branches, so there
1290a1d0d98dSDavid Gibson	 * must be none between those two labels. It also means if this code
12911a51dde1SBenjamin Herrenschmidt	 * ever takes any parameters, the SCOM code must also be updated to
12921a51dde1SBenjamin Herrenschmidt	 * provide them.
12931a51dde1SBenjamin Herrenschmidt	 */
12942d27cfd3SBenjamin Herrenschmidt_GLOBAL(a2_tlbinit_code_start)
12952d27cfd3SBenjamin Herrenschmidt
12962d27cfd3SBenjamin Herrenschmidt	ori	r11,r3,MAS0_WQ_ALLWAYS
12972d27cfd3SBenjamin Herrenschmidt	oris	r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */
12982d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_MAS0,r11
12992d27cfd3SBenjamin Herrenschmidt	lis	r3,(MAS1_VALID | MAS1_IPROT)@h
13002d27cfd3SBenjamin Herrenschmidt	ori	r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
13012d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_MAS1,r3
13022d27cfd3SBenjamin Herrenschmidt	LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET | MAS2_M)
13032d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_MAS2,r3
13042d27cfd3SBenjamin Herrenschmidt	li	r3,MAS3_SR | MAS3_SW | MAS3_SX
13052d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_MAS7_MAS3,r3
13062d27cfd3SBenjamin Herrenschmidt	li	r3,0
1307a1d0d98dSDavid Gibson	mtspr	SPRN_MAS8,r3
1308a1d0d98dSDavid Gibson
1309a1d0d98dSDavid Gibson	/* Write the TLB entry */
13102d27cfd3SBenjamin Herrenschmidt	tlbwe
1311fce01acfSNicholas Piggin
13128e93fb33SNicholas Piggin	.globl a2_tlbinit_after_linear_map
13133569d84bSNicholas Piggina2_tlbinit_after_linear_map:
1314fce01acfSNicholas Piggin
1315d7fb5b18SChristophe Leroy	/* Now we branch the new virtual address mapped by this entry */
1316fce01acfSNicholas Piggin#ifdef CONFIG_RELOCATABLE
13172d27cfd3SBenjamin Herrenschmidt	__LOAD_PACA_TOC(r5)
13182d27cfd3SBenjamin Herrenschmidt	LOAD_REG_ADDR_ALTTOC(r3, r5, 1f)
13192d27cfd3SBenjamin Herrenschmidt#else
13202d27cfd3SBenjamin Herrenschmidt	LOAD_REG_IMMEDIATE_SYM(r3, r5, 1f)
1321f0aae323SJack Miller#endif
1322f0aae323SJack Miller	mtctr	r3
1323f0aae323SJack Miller	bctr
13242d27cfd3SBenjamin Herrenschmidt
1325f0aae323SJack Miller1:	/* We are now running at PAGE_OFFSET, clean the TLB of everything
1326f0aae323SJack Miller	 * else (including IPROTed things left by firmware)
1327f0aae323SJack Miller	 * r4 = TLBnCFG
1328f0aae323SJack Miller	 * r3 = current address (more or less)
1329f0aae323SJack Miller	 */
1330f0aae323SJack Miller
1331f0aae323SJack Miller	li	r5,0
1332f0aae323SJack Miller	mtspr	SPRN_MAS6,r5
1333f0aae323SJack Miller	tlbsx	0,r3
1334f0aae323SJack Miller
1335f0aae323SJack Miller	rlwinm	r9,r4,0,TLBnCFG_N_ENTRY
1336f0aae323SJack Miller	rlwinm	r10,r4,8,0xff
1337f0aae323SJack Miller	addi	r10,r10,-1	/* Get inner loop mask */
1338f0aae323SJack Miller
1339f0aae323SJack Miller	li	r3,1
1340f0aae323SJack Miller
1341f0aae323SJack Miller	mfspr	r5,SPRN_MAS1
1342f0aae323SJack Miller	rlwinm	r5,r5,0,(~(MAS1_VALID|MAS1_IPROT))
1343f0aae323SJack Miller
1344f0aae323SJack Miller	mfspr	r6,SPRN_MAS2
1345f0aae323SJack Miller	rldicr	r6,r6,0,51		/* Extract EPN */
1346f0aae323SJack Miller
1347f0aae323SJack Miller	mfspr	r7,SPRN_MAS0
1348f0aae323SJack Miller	rlwinm	r7,r7,0,0xffff0fff	/* Clear HES and WQ */
1349f0aae323SJack Miller
1350f0aae323SJack Miller	rlwinm	r8,r7,16,0xfff		/* Extract ESEL */
1351f0aae323SJack Miller
1352f0aae323SJack Miller2:	add	r4,r3,r8
1353f0aae323SJack Miller	and	r4,r4,r10
1354f0aae323SJack Miller
1355f0aae323SJack Miller	rlwimi	r7,r4,16,MAS0_ESEL_MASK
1356f0aae323SJack Miller
1357f0aae323SJack Miller	mtspr	SPRN_MAS0,r7
1358f0aae323SJack Miller	mtspr	SPRN_MAS1,r5
1359f0aae323SJack Miller	mtspr	SPRN_MAS2,r6
1360f0aae323SJack Miller	tlbwe
1361f0aae323SJack Miller
1362f0aae323SJack Miller	addi	r3,r3,1
1363f0aae323SJack Miller	and.	r4,r3,r10
1364f0aae323SJack Miller
1365f0aae323SJack Miller	bne	3f
1366a1d0d98dSDavid Gibson	addis	r6,r6,(1<<30)@h
1367a1d0d98dSDavid Gibson3:
1368a1d0d98dSDavid Gibson	cmpw	r3,r9
1369962cffbdSMichael Neuling	blt	2b
13702d27cfd3SBenjamin Herrenschmidt
13712d27cfd3SBenjamin Herrenschmidt	.globl  a2_tlbinit_after_iprot_flush
13722d27cfd3SBenjamin Herrenschmidta2_tlbinit_after_iprot_flush:
1373a1d0d98dSDavid Gibson
1374a1d0d98dSDavid Gibson	PPC_TLBILX(0,0,R0)
1375a1d0d98dSDavid Gibson	sync
13762d27cfd3SBenjamin Herrenschmidt	isync
13772d27cfd3SBenjamin Herrenschmidt
13782d27cfd3SBenjamin Herrenschmidt	.globl a2_tlbinit_code_end
13792d27cfd3SBenjamin Herrenschmidta2_tlbinit_code_end:
13802d27cfd3SBenjamin Herrenschmidt
13812d27cfd3SBenjamin Herrenschmidt	/* We translate LR and return */
13822d27cfd3SBenjamin Herrenschmidt	mflr	r3
13832d27cfd3SBenjamin Herrenschmidt	tovirt(r3,r3)
13842d27cfd3SBenjamin Herrenschmidt	mtlr	r3
13852d27cfd3SBenjamin Herrenschmidt	blr
13862d27cfd3SBenjamin Herrenschmidt
13872d27cfd3SBenjamin Herrenschmidt/*
13882d27cfd3SBenjamin Herrenschmidt * Main entry (boot CPU, thread 0)
13892d27cfd3SBenjamin Herrenschmidt *
13902d27cfd3SBenjamin Herrenschmidt * We enter here from head_64.S, possibly after the prom_init trampoline
13912d27cfd3SBenjamin Herrenschmidt * with r3 and r4 already saved to r31 and 30 respectively and in 64 bits
13922d27cfd3SBenjamin Herrenschmidt * mode. Anything else is as it was left by the bootloader
13932d27cfd3SBenjamin Herrenschmidt *
13942d27cfd3SBenjamin Herrenschmidt * Initial requirements of this port:
13952d27cfd3SBenjamin Herrenschmidt *
13962d27cfd3SBenjamin Herrenschmidt * - Kernel loaded at 0 physical
13972d27cfd3SBenjamin Herrenschmidt * - A good lump of memory mapped 0:0 by UTLB entry 0
13982d27cfd3SBenjamin Herrenschmidt * - MSR:IS & MSR:DS set to 0
13992d27cfd3SBenjamin Herrenschmidt *
14002d27cfd3SBenjamin Herrenschmidt * Note that some of the above requirements will be relaxed in the future
14012d27cfd3SBenjamin Herrenschmidt * as the kernel becomes smarter at dealing with different initial conditions
14022d27cfd3SBenjamin Herrenschmidt * but for now you have to be careful
14032d27cfd3SBenjamin Herrenschmidt */
14042d27cfd3SBenjamin Herrenschmidt_GLOBAL(start_initialization_book3e)
14052d27cfd3SBenjamin Herrenschmidt	mflr	r28
14062d27cfd3SBenjamin Herrenschmidt
1407b1576fecSAnton Blanchard	/* First, we need to setup some initial TLBs to map the kernel
14082d27cfd3SBenjamin Herrenschmidt	 * text, data and bss at PAGE_OFFSET. We don't have a real mode
14092d27cfd3SBenjamin Herrenschmidt	 * and always use AS 0, so we just set it up to match our link
1410b1576fecSAnton Blanchard	 * address and never use 0 based addresses.
14112d27cfd3SBenjamin Herrenschmidt	 */
14122d27cfd3SBenjamin Herrenschmidt	bl	initial_tlb_book3e
1413b1576fecSAnton Blanchard
14142d27cfd3SBenjamin Herrenschmidt	/* Init global core bits */
14152d27cfd3SBenjamin Herrenschmidt	bl	init_core_book3e
14162d27cfd3SBenjamin Herrenschmidt
14172d27cfd3SBenjamin Herrenschmidt	/* Init per-thread bits */
14182d27cfd3SBenjamin Herrenschmidt	bl	init_thread_book3e
14192d27cfd3SBenjamin Herrenschmidt
14202d27cfd3SBenjamin Herrenschmidt	/* Return to common init code */
14212d27cfd3SBenjamin Herrenschmidt	tovirt(r28,r28)
14222d27cfd3SBenjamin Herrenschmidt	mtlr	r28
14232d27cfd3SBenjamin Herrenschmidt	blr
14242d27cfd3SBenjamin Herrenschmidt
14252d27cfd3SBenjamin Herrenschmidt
14262d27cfd3SBenjamin Herrenschmidt/*
14272d27cfd3SBenjamin Herrenschmidt * Secondary core/processor entry
14282d27cfd3SBenjamin Herrenschmidt *
14292d27cfd3SBenjamin Herrenschmidt * This is entered for thread 0 of a secondary core, all other threads
14302d27cfd3SBenjamin Herrenschmidt * are expected to be stopped. It's similar to start_initialization_book3e
14312d27cfd3SBenjamin Herrenschmidt * except that it's generally entered from the holding loop in head_64.S
14322d27cfd3SBenjamin Herrenschmidt * after CPUs have been gathered by Open Firmware.
14332d27cfd3SBenjamin Herrenschmidt *
1434b1576fecSAnton Blanchard * We assume we are in 32 bits mode running with whatever TLB entry was
14352d27cfd3SBenjamin Herrenschmidt * set for us by the firmware or POR engine.
14362d27cfd3SBenjamin Herrenschmidt */
14372d27cfd3SBenjamin Herrenschmidt_GLOBAL(book3e_secondary_core_init_tlb_set)
14382d27cfd3SBenjamin Herrenschmidt	li	r4,1
14392d27cfd3SBenjamin Herrenschmidt	b	generic_secondary_smp_init
14402d27cfd3SBenjamin Herrenschmidt
14412d27cfd3SBenjamin Herrenschmidt_GLOBAL(book3e_secondary_core_init)
14422d27cfd3SBenjamin Herrenschmidt	mflr	r28
14432d27cfd3SBenjamin Herrenschmidt
1444b1576fecSAnton Blanchard	/* Do we need to setup initial TLB entry ? */
14452d27cfd3SBenjamin Herrenschmidt	cmplwi	r4,0
14462d27cfd3SBenjamin Herrenschmidt	bne	2f
14472d27cfd3SBenjamin Herrenschmidt
14482d27cfd3SBenjamin Herrenschmidt	/* Setup TLB for this core */
1449b1576fecSAnton Blanchard	bl	initial_tlb_book3e
14502d27cfd3SBenjamin Herrenschmidt
14512d27cfd3SBenjamin Herrenschmidt	/* We can return from the above running at a different
1452b1576fecSAnton Blanchard	 * address, so recalculate r2 (TOC)
14532d27cfd3SBenjamin Herrenschmidt	 */
14542d27cfd3SBenjamin Herrenschmidt	bl	relative_toc
1455b1576fecSAnton Blanchard
14562d27cfd3SBenjamin Herrenschmidt	/* Init global core bits */
14572d27cfd3SBenjamin Herrenschmidt2:	bl	init_core_book3e
14582d27cfd3SBenjamin Herrenschmidt
14592d27cfd3SBenjamin Herrenschmidt	/* Init per-thread bits */
14602d27cfd3SBenjamin Herrenschmidt3:	bl	init_thread_book3e
14612d27cfd3SBenjamin Herrenschmidt
14622d27cfd3SBenjamin Herrenschmidt	/* Return to common init code at proper virtual address.
14632d27cfd3SBenjamin Herrenschmidt	 *
14642d27cfd3SBenjamin Herrenschmidt	 * Due to various previous assumptions, we know we entered this
14652d27cfd3SBenjamin Herrenschmidt	 * function at either the final PAGE_OFFSET mapping or using a
14662d27cfd3SBenjamin Herrenschmidt	 * 1:1 mapping at 0, so we don't bother doing a complicated check
14672d27cfd3SBenjamin Herrenschmidt	 * here, we just ensure the return address has the right top bits.
14682d27cfd3SBenjamin Herrenschmidt	 *
14692d27cfd3SBenjamin Herrenschmidt	 * Note that if we ever want to be smarter about where we can be
14702d27cfd3SBenjamin Herrenschmidt	 * started from, we have to be careful that by the time we reach
14712d27cfd3SBenjamin Herrenschmidt	 * the code below we may already be running at a different location
14722d27cfd3SBenjamin Herrenschmidt	 * than the one we were called from since initial_tlb_book3e can
14732d27cfd3SBenjamin Herrenschmidt	 * have moved us already.
14742d27cfd3SBenjamin Herrenschmidt	 */
14752d27cfd3SBenjamin Herrenschmidt	cmpdi	cr0,r28,0
14762d27cfd3SBenjamin Herrenschmidt	blt	1f
14772d27cfd3SBenjamin Herrenschmidt	lis	r3,PAGE_OFFSET@highest
14782d27cfd3SBenjamin Herrenschmidt	sldi	r3,r3,32
14792d27cfd3SBenjamin Herrenschmidt	or	r28,r28,r3
14802d27cfd3SBenjamin Herrenschmidt1:	mtlr	r28
14812d27cfd3SBenjamin Herrenschmidt	blr
14821cb6e064STiejun Chen
14836a3bab90SAnton Blanchard_GLOBAL(book3e_secondary_thread_init)
14842d27cfd3SBenjamin Herrenschmidt	mflr	r28
14851cb6e064STiejun Chen	b	3b
14861cb6e064STiejun Chen
14872d27cfd3SBenjamin Herrenschmidt_GLOBAL(init_core_book3e)
14882d27cfd3SBenjamin Herrenschmidt	/* Establish the interrupt vector base */
14892d27cfd3SBenjamin Herrenschmidt	tovirt(r2,r2)
14902d27cfd3SBenjamin Herrenschmidt	LOAD_REG_ADDR(r3, interrupt_base_book3e)
14916a3bab90SAnton Blanchard	mtspr	SPRN_IVPR,r3
14922d27cfd3SBenjamin Herrenschmidt	sync
14932d27cfd3SBenjamin Herrenschmidt	blr
14942d27cfd3SBenjamin Herrenschmidt
14952d27cfd3SBenjamin HerrenschmidtSYM_CODE_START_LOCAL(init_thread_book3e)
14962d27cfd3SBenjamin Herrenschmidt	lis	r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h
14972d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_EPCR,r3
14986c188829SKumar Gala
14996c188829SKumar Gala	/* Make sure interrupts are off */
15002d27cfd3SBenjamin Herrenschmidt	wrteei	0
15016c188829SKumar Gala
15026c188829SKumar Gala	/* disable all timers and clear out status */
15032d27cfd3SBenjamin Herrenschmidt	li	r3,0
15042d27cfd3SBenjamin Herrenschmidt	mtspr	SPRN_TCR,r3
15052d27cfd3SBenjamin Herrenschmidt	mfspr	r3,SPRN_TSR
15064b98d9e7SKumar Gala	mtspr	SPRN_TSR,r3
15074b98d9e7SKumar Gala
15084b98d9e7SKumar Gala	blr
15094b98d9e7SKumar GalaSYM_CODE_END(init_thread_book3e)
15104b98d9e7SKumar Gala
15114b98d9e7SKumar Gala_GLOBAL(__setup_base_ivors)
15124b98d9e7SKumar Gala	SET_IVOR(0, 0x020) /* Critical Input */
15134b98d9e7SKumar Gala	SET_IVOR(1, 0x000) /* Machine Check */
15144b98d9e7SKumar Gala	SET_IVOR(2, 0x060) /* Data Storage */
15154b98d9e7SKumar Gala	SET_IVOR(3, 0x080) /* Instruction Storage */
15164b98d9e7SKumar Gala	SET_IVOR(4, 0x0a0) /* External Input */
15174b98d9e7SKumar Gala	SET_IVOR(5, 0x0c0) /* Alignment */
15184b98d9e7SKumar Gala	SET_IVOR(6, 0x0e0) /* Program */
15194b98d9e7SKumar Gala	SET_IVOR(7, 0x100) /* FP Unavailable */
15204b98d9e7SKumar Gala	SET_IVOR(8, 0x120) /* System Call */
15214b98d9e7SKumar Gala	SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
15224b98d9e7SKumar Gala	SET_IVOR(10, 0x160) /* Decrementer */
15232d27cfd3SBenjamin Herrenschmidt	SET_IVOR(11, 0x180) /* Fixed Interval Timer */
15244b98d9e7SKumar Gala	SET_IVOR(12, 0x1a0) /* Watchdog Timer */
15252d27cfd3SBenjamin Herrenschmidt	SET_IVOR(13, 0x1c0) /* Data TLB Error */
15264b98d9e7SKumar Gala	SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
15273a6e9bd7SScott Wood	SET_IVOR(15, 0x040) /* Debug */
1528cd66cc2eSKumar Gala
1529cd66cc2eSKumar Gala	sync
1530cd66cc2eSKumar Gala
1531cd66cc2eSKumar Gala	blr
1532cd66cc2eSKumar Gala
15333a6e9bd7SScott Wood_GLOBAL(setup_altivec_ivors)
15343a6e9bd7SScott Wood	SET_IVOR(32, 0x200) /* AltiVec Unavailable */
15353a6e9bd7SScott Wood	SET_IVOR(33, 0x220) /* AltiVec Assist */
15363a6e9bd7SScott Wood	blr
15373a6e9bd7SScott Wood
15383a6e9bd7SScott Wood_GLOBAL(setup_perfmon_ivor)
15393a6e9bd7SScott Wood	SET_IVOR(35, 0x260) /* Performance Monitor */
15403a6e9bd7SScott Wood	blr
15413a6e9bd7SScott Wood
15423a6e9bd7SScott Wood_GLOBAL(setup_doorbell_ivors)
15433a6e9bd7SScott Wood	SET_IVOR(36, 0x280) /* Processor Doorbell */
15443a6e9bd7SScott Wood	SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
15450778407fSVarun Sethi	blr
15460778407fSVarun Sethi
15473a6e9bd7SScott Wood_GLOBAL(setup_ehv_ivors)
1548228b1a47SMihai Caraman	SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
1549228b1a47SMihai Caraman	SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
1550228b1a47SMihai Caraman	SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
1551228b1a47SMihai Caraman	SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
1552	blr
1553
1554_GLOBAL(setup_lrat_ivor)
1555	SET_IVOR(42, 0x340) /* LRAT Error */
1556	blr
1557