18aa34ab8SBenjamin Herrenschmidt #ifndef _ASM_POWERPC_EXCEPTION_H
28aa34ab8SBenjamin Herrenschmidt #define _ASM_POWERPC_EXCEPTION_H
38aa34ab8SBenjamin Herrenschmidt /*
48aa34ab8SBenjamin Herrenschmidt  * Extracted from head_64.S
58aa34ab8SBenjamin Herrenschmidt  *
68aa34ab8SBenjamin Herrenschmidt  *  PowerPC version
78aa34ab8SBenjamin Herrenschmidt  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
88aa34ab8SBenjamin Herrenschmidt  *
98aa34ab8SBenjamin Herrenschmidt  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
108aa34ab8SBenjamin Herrenschmidt  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
118aa34ab8SBenjamin Herrenschmidt  *  Adapted for Power Macintosh by Paul Mackerras.
128aa34ab8SBenjamin Herrenschmidt  *  Low-level exception handlers and MMU support
138aa34ab8SBenjamin Herrenschmidt  *  rewritten by Paul Mackerras.
148aa34ab8SBenjamin Herrenschmidt  *    Copyright (C) 1996 Paul Mackerras.
158aa34ab8SBenjamin Herrenschmidt  *
168aa34ab8SBenjamin Herrenschmidt  *  Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
178aa34ab8SBenjamin Herrenschmidt  *    Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
188aa34ab8SBenjamin Herrenschmidt  *
198aa34ab8SBenjamin Herrenschmidt  *  This file contains the low-level support and setup for the
208aa34ab8SBenjamin Herrenschmidt  *  PowerPC-64 platform, including trap and interrupt dispatch.
218aa34ab8SBenjamin Herrenschmidt  *
228aa34ab8SBenjamin Herrenschmidt  *  This program is free software; you can redistribute it and/or
238aa34ab8SBenjamin Herrenschmidt  *  modify it under the terms of the GNU General Public License
248aa34ab8SBenjamin Herrenschmidt  *  as published by the Free Software Foundation; either version
258aa34ab8SBenjamin Herrenschmidt  *  2 of the License, or (at your option) any later version.
268aa34ab8SBenjamin Herrenschmidt  */
278aa34ab8SBenjamin Herrenschmidt /*
288aa34ab8SBenjamin Herrenschmidt  * The following macros define the code that appears as
298aa34ab8SBenjamin Herrenschmidt  * the prologue to each of the exception handlers.  They
308aa34ab8SBenjamin Herrenschmidt  * are split into two parts to allow a single kernel binary
318aa34ab8SBenjamin Herrenschmidt  * to be used for pSeries and iSeries.
328aa34ab8SBenjamin Herrenschmidt  *
338aa34ab8SBenjamin Herrenschmidt  * We make as much of the exception code common between native
348aa34ab8SBenjamin Herrenschmidt  * exception handlers (including pSeries LPAR) and iSeries LPAR
358aa34ab8SBenjamin Herrenschmidt  * implementations as possible.
368aa34ab8SBenjamin Herrenschmidt  */
37da2bc464SMichael Ellerman #include <asm/head-64.h>
382c86cd18SChristophe Leroy #include <asm/feature-fixups.h>
398aa34ab8SBenjamin Herrenschmidt 
408c388514SNicholas Piggin /* PACA save area offsets (exgen, exmc, etc) */
418aa34ab8SBenjamin Herrenschmidt #define EX_R9		0
428aa34ab8SBenjamin Herrenschmidt #define EX_R10		8
438aa34ab8SBenjamin Herrenschmidt #define EX_R11		16
448aa34ab8SBenjamin Herrenschmidt #define EX_R12		24
458aa34ab8SBenjamin Herrenschmidt #define EX_R13		32
4636670fcfSNicholas Piggin #define EX_DAR		40
4736670fcfSNicholas Piggin #define EX_DSISR	48
4836670fcfSNicholas Piggin #define EX_CCR		52
49635942aeSNicholas Piggin #define EX_CFAR		56
50635942aeSNicholas Piggin #define EX_PPR		64
518568f1e0SNicholas Piggin #if defined(CONFIG_RELOCATABLE)
52635942aeSNicholas Piggin #define EX_CTR		72
53635942aeSNicholas Piggin #define EX_SIZE		10	/* size in u64 units */
548568f1e0SNicholas Piggin #else
558568f1e0SNicholas Piggin #define EX_SIZE		9	/* size in u64 units */
568568f1e0SNicholas Piggin #endif
57dbeea1d6SNicholas Piggin 
58dbeea1d6SNicholas Piggin /*
59ba41e1e1SBalbir Singh  * maximum recursive depth of MCE exceptions
60ba41e1e1SBalbir Singh  */
61ba41e1e1SBalbir Singh #define MAX_MCE_DEPTH	4
62ba41e1e1SBalbir Singh 
63ba41e1e1SBalbir Singh /*
64635942aeSNicholas Piggin  * EX_R3 is only used by the bad_stack handler. bad_stack reloads and
65635942aeSNicholas Piggin  * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap
66635942aeSNicholas Piggin  * with EX_DAR.
67635942aeSNicholas Piggin  */
68635942aeSNicholas Piggin #define EX_R3		EX_DAR
69635942aeSNicholas Piggin 
70a048a07dSNicholas Piggin #define STF_ENTRY_BARRIER_SLOT						\
71a048a07dSNicholas Piggin 	STF_ENTRY_BARRIER_FIXUP_SECTION;				\
72a048a07dSNicholas Piggin 	nop;								\
73a048a07dSNicholas Piggin 	nop;								\
74a048a07dSNicholas Piggin 	nop
75a048a07dSNicholas Piggin 
76a048a07dSNicholas Piggin #define STF_EXIT_BARRIER_SLOT						\
77a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_FIXUP_SECTION;					\
78a048a07dSNicholas Piggin 	nop;								\
79a048a07dSNicholas Piggin 	nop;								\
80a048a07dSNicholas Piggin 	nop;								\
81a048a07dSNicholas Piggin 	nop;								\
82a048a07dSNicholas Piggin 	nop;								\
83a048a07dSNicholas Piggin 	nop
84a048a07dSNicholas Piggin 
85a048a07dSNicholas Piggin /*
86a048a07dSNicholas Piggin  * r10 must be free to use, r13 must be paca
87a048a07dSNicholas Piggin  */
88a048a07dSNicholas Piggin #define INTERRUPT_TO_KERNEL						\
89a048a07dSNicholas Piggin 	STF_ENTRY_BARRIER_SLOT
90a048a07dSNicholas Piggin 
91aa8a5e00SMichael Ellerman /*
92aa8a5e00SMichael Ellerman  * Macros for annotating the expected destination of (h)rfid
93aa8a5e00SMichael Ellerman  *
94aa8a5e00SMichael Ellerman  * The nop instructions allow us to insert one or more instructions to flush the
95aa8a5e00SMichael Ellerman  * L1-D cache when returning to userspace or a guest.
96aa8a5e00SMichael Ellerman  */
97aa8a5e00SMichael Ellerman #define RFI_FLUSH_SLOT							\
98aa8a5e00SMichael Ellerman 	RFI_FLUSH_FIXUP_SECTION;					\
99aa8a5e00SMichael Ellerman 	nop;								\
100aa8a5e00SMichael Ellerman 	nop;								\
101aa8a5e00SMichael Ellerman 	nop
10250e51c13SNicholas Piggin 
10350e51c13SNicholas Piggin #define RFI_TO_KERNEL							\
10450e51c13SNicholas Piggin 	rfid
10550e51c13SNicholas Piggin 
10650e51c13SNicholas Piggin #define RFI_TO_USER							\
107a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
108aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
109aa8a5e00SMichael Ellerman 	rfid;								\
110aa8a5e00SMichael Ellerman 	b	rfi_flush_fallback
11150e51c13SNicholas Piggin 
11250e51c13SNicholas Piggin #define RFI_TO_USER_OR_KERNEL						\
113a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
114aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
115aa8a5e00SMichael Ellerman 	rfid;								\
116aa8a5e00SMichael Ellerman 	b	rfi_flush_fallback
11750e51c13SNicholas Piggin 
11850e51c13SNicholas Piggin #define RFI_TO_GUEST							\
119a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
120aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
121aa8a5e00SMichael Ellerman 	rfid;								\
122aa8a5e00SMichael Ellerman 	b	rfi_flush_fallback
12350e51c13SNicholas Piggin 
12450e51c13SNicholas Piggin #define HRFI_TO_KERNEL							\
12550e51c13SNicholas Piggin 	hrfid
12650e51c13SNicholas Piggin 
12750e51c13SNicholas Piggin #define HRFI_TO_USER							\
128a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
129aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
130aa8a5e00SMichael Ellerman 	hrfid;								\
131aa8a5e00SMichael Ellerman 	b	hrfi_flush_fallback
13250e51c13SNicholas Piggin 
13350e51c13SNicholas Piggin #define HRFI_TO_USER_OR_KERNEL						\
134a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
135aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
136aa8a5e00SMichael Ellerman 	hrfid;								\
137aa8a5e00SMichael Ellerman 	b	hrfi_flush_fallback
13850e51c13SNicholas Piggin 
13950e51c13SNicholas Piggin #define HRFI_TO_GUEST							\
140a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
141aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
142aa8a5e00SMichael Ellerman 	hrfid;								\
143aa8a5e00SMichael Ellerman 	b	hrfi_flush_fallback
14450e51c13SNicholas Piggin 
14550e51c13SNicholas Piggin #define HRFI_TO_UNKNOWN							\
146a048a07dSNicholas Piggin 	STF_EXIT_BARRIER_SLOT;						\
147aa8a5e00SMichael Ellerman 	RFI_FLUSH_SLOT;							\
148aa8a5e00SMichael Ellerman 	hrfid;								\
149aa8a5e00SMichael Ellerman 	b	hrfi_flush_fallback
15050e51c13SNicholas Piggin 
1514700dfafSMichael Neuling #ifdef CONFIG_RELOCATABLE
1526ebb9397SMichael Ellerman #define __EXCEPTION_PROLOG_2_RELON(label, h)				\
1534700dfafSMichael Neuling 	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
1544700dfafSMichael Neuling 	LOAD_HANDLER(r12,label);					\
155bc2e6c6aSMichael Neuling 	mtctr	r12;							\
1564700dfafSMichael Neuling 	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
1574700dfafSMichael Neuling 	li	r10,MSR_RI;						\
1584700dfafSMichael Neuling 	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\
159bc2e6c6aSMichael Neuling 	bctr;
1604700dfafSMichael Neuling #else
1614700dfafSMichael Neuling /* If not relocatable, we can jump directly -- and save messing with LR */
1626ebb9397SMichael Ellerman #define __EXCEPTION_PROLOG_2_RELON(label, h)				\
1634700dfafSMichael Neuling 	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
1644700dfafSMichael Neuling 	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
1654700dfafSMichael Neuling 	li	r10,MSR_RI;						\
1664700dfafSMichael Neuling 	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\
1674700dfafSMichael Neuling 	b	label;
1684700dfafSMichael Neuling #endif
1696ebb9397SMichael Ellerman #define EXCEPTION_PROLOG_2_RELON(label, h)				\
1706ebb9397SMichael Ellerman 	__EXCEPTION_PROLOG_2_RELON(label, h)
1714700dfafSMichael Neuling 
1724700dfafSMichael Neuling /*
173bdf08e1dSMichael Ellerman  * As EXCEPTION_PROLOG(), except we've already got relocation on so no need to
174bdf08e1dSMichael Ellerman  * rfid. Save LR in case we're CONFIG_RELOCATABLE, in which case
175bdf08e1dSMichael Ellerman  * EXCEPTION_PROLOG_2_RELON will be using LR.
1764700dfafSMichael Neuling  */
177270373f1SMichael Ellerman #define EXCEPTION_RELON_PROLOG(area, label, h, extra, vec)		\
17892b6d65cSMichael Ellerman 	SET_SCRATCH0(r13);		/* save r13 */			\
1791707dd16SPaul Mackerras 	EXCEPTION_PROLOG_0(area);					\
1804700dfafSMichael Neuling 	EXCEPTION_PROLOG_1(area, extra, vec);				\
1816ebb9397SMichael Ellerman 	EXCEPTION_PROLOG_2_RELON(label, h)
1824700dfafSMichael Neuling 
1838aa34ab8SBenjamin Herrenschmidt /*
1848aa34ab8SBenjamin Herrenschmidt  * We're short on space and time in the exception prolog, so we can't
18527510235SMichael Ellerman  * use the normal LOAD_REG_IMMEDIATE macro to load the address of label.
18627510235SMichael Ellerman  * Instead we get the base of the kernel from paca->kernelbase and or in the low
18727510235SMichael Ellerman  * part of label. This requires that the label be within 64KB of kernelbase, and
18827510235SMichael Ellerman  * that kernelbase be 64K aligned.
1898aa34ab8SBenjamin Herrenschmidt  */
1908aa34ab8SBenjamin Herrenschmidt #define LOAD_HANDLER(reg, label)					\
191d8d42b05SMichael Ellerman 	ld	reg,PACAKBASE(r13);	/* get high part of &label */	\
1924b1f5cccSNicholas Piggin 	ori	reg,reg,FIXED_SYMBOL_ABS_ADDR(label)
1938aa34ab8SBenjamin Herrenschmidt 
194fb479e44SNicholas Piggin #define __LOAD_HANDLER(reg, label)					\
195fb479e44SNicholas Piggin 	ld	reg,PACAKBASE(r13);					\
1964b1f5cccSNicholas Piggin 	ori	reg,reg,(ABS_ADDR(label))@l
197fb479e44SNicholas Piggin 
198a97a65d5SNicholas Piggin /*
199a97a65d5SNicholas Piggin  * Branches from unrelocated code (e.g., interrupts) to labels outside
200a97a65d5SNicholas Piggin  * head-y require >64K offsets.
201a97a65d5SNicholas Piggin  */
202a97a65d5SNicholas Piggin #define __LOAD_FAR_HANDLER(reg, label)					\
203a97a65d5SNicholas Piggin 	ld	reg,PACAKBASE(r13);					\
204a97a65d5SNicholas Piggin 	ori	reg,reg,(ABS_ADDR(label))@l;				\
2054b1f5cccSNicholas Piggin 	addis	reg,reg,(ABS_ADDR(label))@h
206a97a65d5SNicholas Piggin 
207a5d4f3adSBenjamin Herrenschmidt /* Exception register prefixes */
208a5d4f3adSBenjamin Herrenschmidt #define EXC_HV	H
209a5d4f3adSBenjamin Herrenschmidt #define EXC_STD
210a5d4f3adSBenjamin Herrenschmidt 
2114700dfafSMichael Neuling #if defined(CONFIG_RELOCATABLE)
2124700dfafSMichael Neuling /*
213bc2e6c6aSMichael Neuling  * If we support interrupts with relocation on AND we're a relocatable kernel,
214bc2e6c6aSMichael Neuling  * we need to use CTR to get to the 2nd level handler.  So, save/restore it
215bc2e6c6aSMichael Neuling  * when required.
2164700dfafSMichael Neuling  */
217bc2e6c6aSMichael Neuling #define SAVE_CTR(reg, area)	mfctr	reg ; 	std	reg,area+EX_CTR(r13)
218bc2e6c6aSMichael Neuling #define GET_CTR(reg, area) 			ld	reg,area+EX_CTR(r13)
219bc2e6c6aSMichael Neuling #define RESTORE_CTR(reg, area)	ld	reg,area+EX_CTR(r13) ; mtctr reg
2204700dfafSMichael Neuling #else
221bc2e6c6aSMichael Neuling /* ...else CTR is unused and in register. */
222bc2e6c6aSMichael Neuling #define SAVE_CTR(reg, area)
223bc2e6c6aSMichael Neuling #define GET_CTR(reg, area) 	mfctr	reg
224bc2e6c6aSMichael Neuling #define RESTORE_CTR(reg, area)
2254700dfafSMichael Neuling #endif
2264700dfafSMichael Neuling 
22713e7a8e8SHaren Myneni /*
22813e7a8e8SHaren Myneni  * PPR save/restore macros used in exceptions_64s.S
22913e7a8e8SHaren Myneni  * Used for P7 or later processors
23013e7a8e8SHaren Myneni  */
2314c2de74cSNicholas Piggin #define SAVE_PPR(area, ra)						\
23213e7a8e8SHaren Myneni BEGIN_FTR_SECTION_NESTED(940)						\
2334c2de74cSNicholas Piggin 	ld	ra,area+EX_PPR(r13);	/* Read PPR from paca */	\
2344c2de74cSNicholas Piggin 	std	ra,_PPR(r1);						\
23513e7a8e8SHaren Myneni END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940)
23613e7a8e8SHaren Myneni 
23713e7a8e8SHaren Myneni #define RESTORE_PPR_PACA(area, ra)					\
23813e7a8e8SHaren Myneni BEGIN_FTR_SECTION_NESTED(941)						\
23913e7a8e8SHaren Myneni 	ld	ra,area+EX_PPR(r13);					\
24013e7a8e8SHaren Myneni 	mtspr	SPRN_PPR,ra;						\
24113e7a8e8SHaren Myneni END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,941)
24213e7a8e8SHaren Myneni 
24313e7a8e8SHaren Myneni /*
2441707dd16SPaul Mackerras  * Get an SPR into a register if the CPU has the given feature
24513e7a8e8SHaren Myneni  */
2461707dd16SPaul Mackerras #define OPT_GET_SPR(ra, spr, ftr)					\
24713e7a8e8SHaren Myneni BEGIN_FTR_SECTION_NESTED(943)						\
2481707dd16SPaul Mackerras 	mfspr	ra,spr;							\
2491707dd16SPaul Mackerras END_FTR_SECTION_NESTED(ftr,ftr,943)
25013e7a8e8SHaren Myneni 
2511707dd16SPaul Mackerras /*
252d410ae21SMahesh Salgaonkar  * Set an SPR from a register if the CPU has the given feature
253d410ae21SMahesh Salgaonkar  */
254d410ae21SMahesh Salgaonkar #define OPT_SET_SPR(ra, spr, ftr)					\
255d410ae21SMahesh Salgaonkar BEGIN_FTR_SECTION_NESTED(943)						\
256d410ae21SMahesh Salgaonkar 	mtspr	spr,ra;							\
257d410ae21SMahesh Salgaonkar END_FTR_SECTION_NESTED(ftr,ftr,943)
258d410ae21SMahesh Salgaonkar 
259d410ae21SMahesh Salgaonkar /*
2601707dd16SPaul Mackerras  * Save a register to the PACA if the CPU has the given feature
2611707dd16SPaul Mackerras  */
2621707dd16SPaul Mackerras #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr)				\
2631707dd16SPaul Mackerras BEGIN_FTR_SECTION_NESTED(943)						\
2641707dd16SPaul Mackerras 	std	ra,offset(r13);						\
2651707dd16SPaul Mackerras END_FTR_SECTION_NESTED(ftr,ftr,943)
2661707dd16SPaul Mackerras 
267544686caSNicholas Piggin #define EXCEPTION_PROLOG_0(area)					\
268544686caSNicholas Piggin 	GET_PACA(r13);							\
26944e9309fSHaren Myneni 	std	r9,area+EX_R9(r13);	/* save r9 */			\
2701707dd16SPaul Mackerras 	OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);			\
2711707dd16SPaul Mackerras 	HMT_MEDIUM;							\
27244e9309fSHaren Myneni 	std	r10,area+EX_R10(r13);	/* save r10 - r12 */		\
2731707dd16SPaul Mackerras 	OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
2741707dd16SPaul Mackerras 
275f14e953bSMadhavan Srinivasan #define __EXCEPTION_PROLOG_1_PRE(area)					\
2761707dd16SPaul Mackerras 	OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR);		\
2771707dd16SPaul Mackerras 	OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR);		\
278a048a07dSNicholas Piggin 	INTERRUPT_TO_KERNEL;						\
279bc2e6c6aSMichael Neuling 	SAVE_CTR(r10, area);						\
2804b1f5cccSNicholas Piggin 	mfcr	r9
281f14e953bSMadhavan Srinivasan 
282f14e953bSMadhavan Srinivasan #define __EXCEPTION_PROLOG_1_POST(area)					\
283b01c8b54SPaul Mackerras 	std	r11,area+EX_R11(r13);					\
284b01c8b54SPaul Mackerras 	std	r12,area+EX_R12(r13);					\
285b01c8b54SPaul Mackerras 	GET_SCRATCH0(r10);						\
286b01c8b54SPaul Mackerras 	std	r10,area+EX_R13(r13)
287f14e953bSMadhavan Srinivasan 
288f14e953bSMadhavan Srinivasan /*
289f14e953bSMadhavan Srinivasan  * This version of the EXCEPTION_PROLOG_1 will carry
290f14e953bSMadhavan Srinivasan  * addition parameter called "bitmask" to support
291f14e953bSMadhavan Srinivasan  * checking of the interrupt maskable level in the SOFTEN_TEST.
292f14e953bSMadhavan Srinivasan  * Intended to be used in MASKABLE_EXCPETION_* macros.
293f14e953bSMadhavan Srinivasan  */
294f14e953bSMadhavan Srinivasan #define MASKABLE_EXCEPTION_PROLOG_1(area, extra, vec, bitmask)			\
295f14e953bSMadhavan Srinivasan 	__EXCEPTION_PROLOG_1_PRE(area);					\
296f14e953bSMadhavan Srinivasan 	extra(vec, bitmask);						\
2974b1f5cccSNicholas Piggin 	__EXCEPTION_PROLOG_1_POST(area)
298f14e953bSMadhavan Srinivasan 
299f14e953bSMadhavan Srinivasan /*
300f14e953bSMadhavan Srinivasan  * This version of the EXCEPTION_PROLOG_1 is intended
301f14e953bSMadhavan Srinivasan  * to be used in STD_EXCEPTION* macros
302f14e953bSMadhavan Srinivasan  */
303f14e953bSMadhavan Srinivasan #define _EXCEPTION_PROLOG_1(area, extra, vec)				\
304f14e953bSMadhavan Srinivasan 	__EXCEPTION_PROLOG_1_PRE(area);					\
305f14e953bSMadhavan Srinivasan 	extra(vec);							\
3064b1f5cccSNicholas Piggin 	__EXCEPTION_PROLOG_1_POST(area)
307f14e953bSMadhavan Srinivasan 
308b01c8b54SPaul Mackerras #define EXCEPTION_PROLOG_1(area, extra, vec)				\
309f14e953bSMadhavan Srinivasan 	_EXCEPTION_PROLOG_1(area, extra, vec)
3108aa34ab8SBenjamin Herrenschmidt 
311cb58a4a4SMichael Ellerman #define __EXCEPTION_PROLOG_2(label, h)					\
3128aa34ab8SBenjamin Herrenschmidt 	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\
313a5d4f3adSBenjamin Herrenschmidt 	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
3144b1f5cccSNicholas Piggin 	LOAD_HANDLER(r12,label);					\
315a5d4f3adSBenjamin Herrenschmidt 	mtspr	SPRN_##h##SRR0,r12;					\
316a5d4f3adSBenjamin Herrenschmidt 	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
317a5d4f3adSBenjamin Herrenschmidt 	mtspr	SPRN_##h##SRR1,r10;					\
318222f20f1SNicholas Piggin 	h##RFI_TO_KERNEL;						\
3198aa34ab8SBenjamin Herrenschmidt 	b	.	/* prevent speculative execution */
320cb58a4a4SMichael Ellerman #define EXCEPTION_PROLOG_2(label, h)					\
321cb58a4a4SMichael Ellerman 	__EXCEPTION_PROLOG_2(label, h)
3228aa34ab8SBenjamin Herrenschmidt 
32383a980f7SNicholas Piggin /* _NORI variant keeps MSR_RI clear */
32494f3cc8eSMichael Ellerman #define __EXCEPTION_PROLOG_2_NORI(label, h)				\
32583a980f7SNicholas Piggin 	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\
32683a980f7SNicholas Piggin 	xori	r10,r10,MSR_RI;		/* Clear MSR_RI */		\
32783a980f7SNicholas Piggin 	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
3284b1f5cccSNicholas Piggin 	LOAD_HANDLER(r12,label);					\
32983a980f7SNicholas Piggin 	mtspr	SPRN_##h##SRR0,r12;					\
33083a980f7SNicholas Piggin 	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
33183a980f7SNicholas Piggin 	mtspr	SPRN_##h##SRR1,r10;					\
332222f20f1SNicholas Piggin 	h##RFI_TO_KERNEL;						\
33383a980f7SNicholas Piggin 	b	.	/* prevent speculative execution */
33483a980f7SNicholas Piggin 
33594f3cc8eSMichael Ellerman #define EXCEPTION_PROLOG_2_NORI(label, h)				\
33694f3cc8eSMichael Ellerman 	__EXCEPTION_PROLOG_2_NORI(label, h)
33783a980f7SNicholas Piggin 
338bdf08e1dSMichael Ellerman #define EXCEPTION_PROLOG(area, label, h, extra, vec)			\
3394a7a0a84SMichael Ellerman 	SET_SCRATCH0(r13);		/* save r13 */			\
3401707dd16SPaul Mackerras 	EXCEPTION_PROLOG_0(area);					\
341b01c8b54SPaul Mackerras 	EXCEPTION_PROLOG_1(area, extra, vec);				\
3424b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG_2(label, h)
343c5a8c0c9SBenjamin Herrenschmidt 
344da2bc464SMichael Ellerman #define __KVMTEST(h, n)							\
3453c42bf8aSPaul Mackerras 	lbz	r10,HSTATE_IN_GUEST(r13);				\
346b01c8b54SPaul Mackerras 	cmpwi	r10,0;							\
347da2bc464SMichael Ellerman 	bne	do_kvm_##h##n
348b01c8b54SPaul Mackerras 
349dd96b2c2SAneesh Kumar K.V #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
350dd96b2c2SAneesh Kumar K.V /*
351dd96b2c2SAneesh Kumar K.V  * If hv is possible, interrupts come into to the hv version
352dd96b2c2SAneesh Kumar K.V  * of the kvmppc_interrupt code, which then jumps to the PR handler,
353dd96b2c2SAneesh Kumar K.V  * kvmppc_interrupt_pr, if the guest is a PR guest.
354dd96b2c2SAneesh Kumar K.V  */
355dd96b2c2SAneesh Kumar K.V #define kvmppc_interrupt kvmppc_interrupt_hv
356dd96b2c2SAneesh Kumar K.V #else
357dd96b2c2SAneesh Kumar K.V #define kvmppc_interrupt kvmppc_interrupt_pr
358dd96b2c2SAneesh Kumar K.V #endif
359dd96b2c2SAneesh Kumar K.V 
360b51351e2SNicholas Piggin /*
361b51351e2SNicholas Piggin  * Branch to label using its 0xC000 address. This results in instruction
362b51351e2SNicholas Piggin  * address suitable for MSR[IR]=0 or 1, which allows relocation to be turned
363b51351e2SNicholas Piggin  * on using mtmsr rather than rfid.
364b51351e2SNicholas Piggin  *
365b51351e2SNicholas Piggin  * This could set the 0xc bits for !RELOCATABLE as an immediate, rather than
366b51351e2SNicholas Piggin  * load KBASE for a slight optimisation.
367b51351e2SNicholas Piggin  */
368b51351e2SNicholas Piggin #define BRANCH_TO_C000(reg, label)					\
369b51351e2SNicholas Piggin 	__LOAD_HANDLER(reg, label);					\
370b51351e2SNicholas Piggin 	mtctr	reg;							\
371b51351e2SNicholas Piggin 	bctr
372b51351e2SNicholas Piggin 
373fb479e44SNicholas Piggin #ifdef CONFIG_RELOCATABLE
374fb479e44SNicholas Piggin #define BRANCH_TO_COMMON(reg, label)					\
375fb479e44SNicholas Piggin 	__LOAD_HANDLER(reg, label);					\
376fb479e44SNicholas Piggin 	mtctr	reg;							\
377fb479e44SNicholas Piggin 	bctr
378fb479e44SNicholas Piggin 
379be5c5e84SMichael Ellerman #define BRANCH_LINK_TO_FAR(label)					\
380be5c5e84SMichael Ellerman 	__LOAD_FAR_HANDLER(r12, label);					\
381be5c5e84SMichael Ellerman 	mtctr	r12;							\
3822337d207SNicholas Piggin 	bctrl
3832337d207SNicholas Piggin 
384a97a65d5SNicholas Piggin /*
385a97a65d5SNicholas Piggin  * KVM requires __LOAD_FAR_HANDLER.
386a97a65d5SNicholas Piggin  *
387a97a65d5SNicholas Piggin  * __BRANCH_TO_KVM_EXIT branches are also a special case because they
388a97a65d5SNicholas Piggin  * explicitly use r9 then reload it from PACA before branching. Hence
389a97a65d5SNicholas Piggin  * the double-underscore.
390a97a65d5SNicholas Piggin  */
391a97a65d5SNicholas Piggin #define __BRANCH_TO_KVM_EXIT(area, label)				\
392a97a65d5SNicholas Piggin 	mfctr	r9;							\
393a97a65d5SNicholas Piggin 	std	r9,HSTATE_SCRATCH1(r13);				\
394a97a65d5SNicholas Piggin 	__LOAD_FAR_HANDLER(r9, label);					\
395a97a65d5SNicholas Piggin 	mtctr	r9;							\
396a97a65d5SNicholas Piggin 	ld	r9,area+EX_R9(r13);					\
397a97a65d5SNicholas Piggin 	bctr
398a97a65d5SNicholas Piggin 
399fb479e44SNicholas Piggin #else
400fb479e44SNicholas Piggin #define BRANCH_TO_COMMON(reg, label)					\
401fb479e44SNicholas Piggin 	b	label
402fb479e44SNicholas Piggin 
403be5c5e84SMichael Ellerman #define BRANCH_LINK_TO_FAR(label)					\
4042337d207SNicholas Piggin 	bl	label
4052337d207SNicholas Piggin 
406a97a65d5SNicholas Piggin #define __BRANCH_TO_KVM_EXIT(area, label)				\
407a97a65d5SNicholas Piggin 	ld	r9,area+EX_R9(r13);					\
408a97a65d5SNicholas Piggin 	b	label
409a97a65d5SNicholas Piggin 
410fb479e44SNicholas Piggin #endif
411fb479e44SNicholas Piggin 
412c4f3b52cSNicholas Piggin /* Do not enable RI */
41394f3cc8eSMichael Ellerman #define EXCEPTION_PROLOG_NORI(area, label, h, extra, vec)		\
414c4f3b52cSNicholas Piggin 	EXCEPTION_PROLOG_0(area);					\
415c4f3b52cSNicholas Piggin 	EXCEPTION_PROLOG_1(area, extra, vec);				\
4164b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG_2_NORI(label, h)
417c4f3b52cSNicholas Piggin 
418a97a65d5SNicholas Piggin 
419d3918e7fSNicholas Piggin #define __KVM_HANDLER(area, h, n)					\
4200acb9111SPaul Mackerras 	BEGIN_FTR_SECTION_NESTED(947)					\
4210acb9111SPaul Mackerras 	ld	r10,area+EX_CFAR(r13);					\
4220acb9111SPaul Mackerras 	std	r10,HSTATE_CFAR(r13);					\
4230acb9111SPaul Mackerras 	END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947);		\
4244b8473c9SPaul Mackerras 	BEGIN_FTR_SECTION_NESTED(948)					\
4254b8473c9SPaul Mackerras 	ld	r10,area+EX_PPR(r13);					\
4264b8473c9SPaul Mackerras 	std	r10,HSTATE_PPR(r13);					\
4274b8473c9SPaul Mackerras 	END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948);	\
428b01c8b54SPaul Mackerras 	ld	r10,area+EX_R10(r13);					\
4293c42bf8aSPaul Mackerras 	std	r12,HSTATE_SCRATCH0(r13);				\
430d3918e7fSNicholas Piggin 	sldi	r12,r9,32;						\
431d3918e7fSNicholas Piggin 	ori	r12,r12,(n);						\
432a97a65d5SNicholas Piggin 	/* This reloads r9 before branching to kvmppc_interrupt */	\
433a97a65d5SNicholas Piggin 	__BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt)
434b01c8b54SPaul Mackerras 
435b01c8b54SPaul Mackerras #define __KVM_HANDLER_SKIP(area, h, n)					\
436b01c8b54SPaul Mackerras 	cmpwi	r10,KVM_GUEST_MODE_SKIP;				\
437b01c8b54SPaul Mackerras 	beq	89f;							\
4384b8473c9SPaul Mackerras 	BEGIN_FTR_SECTION_NESTED(948)					\
439d3918e7fSNicholas Piggin 	ld	r10,area+EX_PPR(r13);					\
440d3918e7fSNicholas Piggin 	std	r10,HSTATE_PPR(r13);					\
4414b8473c9SPaul Mackerras 	END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948);	\
442d3918e7fSNicholas Piggin 	ld	r10,area+EX_R10(r13);					\
4433c42bf8aSPaul Mackerras 	std	r12,HSTATE_SCRATCH0(r13);				\
444d3918e7fSNicholas Piggin 	sldi	r12,r9,32;						\
445d3918e7fSNicholas Piggin 	ori	r12,r12,(n);						\
446a97a65d5SNicholas Piggin 	/* This reloads r9 before branching to kvmppc_interrupt */	\
447a97a65d5SNicholas Piggin 	__BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt);			\
448b01c8b54SPaul Mackerras 89:	mtocrf	0x80,r9;						\
449b01c8b54SPaul Mackerras 	ld	r9,area+EX_R9(r13);					\
450d3918e7fSNicholas Piggin 	ld	r10,area+EX_R10(r13);					\
451b01c8b54SPaul Mackerras 	b	kvmppc_skip_##h##interrupt
452b01c8b54SPaul Mackerras 
453b01c8b54SPaul Mackerras #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
454da2bc464SMichael Ellerman #define KVMTEST(h, n)			__KVMTEST(h, n)
455b01c8b54SPaul Mackerras #define KVM_HANDLER(area, h, n)		__KVM_HANDLER(area, h, n)
456b01c8b54SPaul Mackerras #define KVM_HANDLER_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n)
457b01c8b54SPaul Mackerras 
458b01c8b54SPaul Mackerras #else
459da2bc464SMichael Ellerman #define KVMTEST(h, n)
460b01c8b54SPaul Mackerras #define KVM_HANDLER(area, h, n)
461b01c8b54SPaul Mackerras #define KVM_HANDLER_SKIP(area, h, n)
462b01c8b54SPaul Mackerras #endif
463b01c8b54SPaul Mackerras 
464b01c8b54SPaul Mackerras #define NOTEST(n)
465b01c8b54SPaul Mackerras 
466a4087a4dSNicholas Piggin #define EXCEPTION_PROLOG_COMMON_1()					   \
467a4087a4dSNicholas Piggin 	std	r9,_CCR(r1);		/* save CR in stackframe	*/ \
468a4087a4dSNicholas Piggin 	std	r11,_NIP(r1);		/* save SRR0 in stackframe	*/ \
469a4087a4dSNicholas Piggin 	std	r12,_MSR(r1);		/* save SRR1 in stackframe	*/ \
470a4087a4dSNicholas Piggin 	std	r10,0(r1);		/* make stack chain pointer	*/ \
471a4087a4dSNicholas Piggin 	std	r0,GPR0(r1);		/* save r0 in stackframe	*/ \
472a4087a4dSNicholas Piggin 	std	r10,GPR1(r1);		/* save r1 in stackframe	*/ \
473a4087a4dSNicholas Piggin 
474a4087a4dSNicholas Piggin 
4758aa34ab8SBenjamin Herrenschmidt /*
4768aa34ab8SBenjamin Herrenschmidt  * The common exception prolog is used for all except a few exceptions
4778aa34ab8SBenjamin Herrenschmidt  * such as a segment miss on a kernel address.  We have to be prepared
4788aa34ab8SBenjamin Herrenschmidt  * to take another exception from the point where we first touch the
4798aa34ab8SBenjamin Herrenschmidt  * kernel stack onwards.
4808aa34ab8SBenjamin Herrenschmidt  *
4818aa34ab8SBenjamin Herrenschmidt  * On entry r13 points to the paca, r9-r13 are saved in the paca,
4828aa34ab8SBenjamin Herrenschmidt  * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and
4838aa34ab8SBenjamin Herrenschmidt  * SRR1, and relocation is on.
4848aa34ab8SBenjamin Herrenschmidt  */
4858aa34ab8SBenjamin Herrenschmidt #define EXCEPTION_PROLOG_COMMON(n, area)				   \
4868aa34ab8SBenjamin Herrenschmidt 	andi.	r10,r12,MSR_PR;		/* See if coming from user	*/ \
4878aa34ab8SBenjamin Herrenschmidt 	mr	r10,r1;			/* Save r1			*/ \
4888aa34ab8SBenjamin Herrenschmidt 	subi	r1,r1,INT_FRAME_SIZE;	/* alloc frame on kernel stack	*/ \
4898aa34ab8SBenjamin Herrenschmidt 	beq-	1f;							   \
4908aa34ab8SBenjamin Herrenschmidt 	ld	r1,PACAKSAVE(r13);	/* kernel stack to use		*/ \
49190ff5d68SMichael Neuling 1:	cmpdi	cr1,r1,-INT_FRAME_SIZE;	/* check if r1 is in userspace	*/ \
4921977b502SPaul Mackerras 	blt+	cr1,3f;			/* abort if it is		*/ \
4931977b502SPaul Mackerras 	li	r1,(n);			/* will be reloaded later	*/ \
4948aa34ab8SBenjamin Herrenschmidt 	sth	r1,PACA_TRAP_SAVE(r13);					   \
4951977b502SPaul Mackerras 	std	r3,area+EX_R3(r13);					   \
4961977b502SPaul Mackerras 	addi	r3,r13,area;		/* r3 -> where regs are saved*/	   \
497bc2e6c6aSMichael Neuling 	RESTORE_CTR(r1, area);						   \
4988aa34ab8SBenjamin Herrenschmidt 	b	bad_stack;						   \
499a4087a4dSNicholas Piggin 3:	EXCEPTION_PROLOG_COMMON_1();					   \
500890274c2SMichael Ellerman 	kuap_save_amr_and_lock r9, r10, cr1, cr0;			   \
5015d75b264SHaren Myneni 	beq	4f;			/* if from kernel mode		*/ \
502c223c903SChristophe Leroy 	ACCOUNT_CPU_USER_ENTRY(r13, r9, r10);				   \
5034c2de74cSNicholas Piggin 	SAVE_PPR(area, r9);						   \
504b14a7253SMahesh Salgaonkar 4:	EXCEPTION_PROLOG_COMMON_2(area)					   \
505b14a7253SMahesh Salgaonkar 	EXCEPTION_PROLOG_COMMON_3(n)					   \
506b14a7253SMahesh Salgaonkar 	ACCOUNT_STOLEN_TIME
507b14a7253SMahesh Salgaonkar 
508b14a7253SMahesh Salgaonkar /* Save original regs values from save area to stack frame. */
509b14a7253SMahesh Salgaonkar #define EXCEPTION_PROLOG_COMMON_2(area)					   \
5108aa34ab8SBenjamin Herrenschmidt 	ld	r9,area+EX_R9(r13);	/* move r9, r10 to stackframe	*/ \
5118aa34ab8SBenjamin Herrenschmidt 	ld	r10,area+EX_R10(r13);					   \
5128aa34ab8SBenjamin Herrenschmidt 	std	r9,GPR9(r1);						   \
5138aa34ab8SBenjamin Herrenschmidt 	std	r10,GPR10(r1);						   \
5148aa34ab8SBenjamin Herrenschmidt 	ld	r9,area+EX_R11(r13);	/* move r11 - r13 to stackframe	*/ \
5158aa34ab8SBenjamin Herrenschmidt 	ld	r10,area+EX_R12(r13);					   \
5168aa34ab8SBenjamin Herrenschmidt 	ld	r11,area+EX_R13(r13);					   \
5178aa34ab8SBenjamin Herrenschmidt 	std	r9,GPR11(r1);						   \
5188aa34ab8SBenjamin Herrenschmidt 	std	r10,GPR12(r1);						   \
5198aa34ab8SBenjamin Herrenschmidt 	std	r11,GPR13(r1);						   \
52048404f2eSPaul Mackerras 	BEGIN_FTR_SECTION_NESTED(66);					   \
52148404f2eSPaul Mackerras 	ld	r10,area+EX_CFAR(r13);					   \
52248404f2eSPaul Mackerras 	std	r10,ORIG_GPR3(r1);					   \
52348404f2eSPaul Mackerras 	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		   \
524b14a7253SMahesh Salgaonkar 	GET_CTR(r10, area);						   \
525b14a7253SMahesh Salgaonkar 	std	r10,_CTR(r1);
526b14a7253SMahesh Salgaonkar 
527b14a7253SMahesh Salgaonkar #define EXCEPTION_PROLOG_COMMON_3(n)					   \
528b14a7253SMahesh Salgaonkar 	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \
529b14a7253SMahesh Salgaonkar 	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe   */ \
530b14a7253SMahesh Salgaonkar 	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \
531bc2e6c6aSMichael Neuling 	mflr	r9;			/* Get LR, later save to stack	*/ \
5328aa34ab8SBenjamin Herrenschmidt 	ld	r2,PACATOC(r13);	/* get kernel TOC into r2	*/ \
5338aa34ab8SBenjamin Herrenschmidt 	std	r9,_LINK(r1);						   \
5344e26bc4aSMadhavan Srinivasan 	lbz	r10,PACAIRQSOFTMASK(r13);				   \
5358aa34ab8SBenjamin Herrenschmidt 	mfspr	r11,SPRN_XER;		/* save XER in stackframe	*/ \
5368aa34ab8SBenjamin Herrenschmidt 	std	r10,SOFTE(r1);						   \
5378aa34ab8SBenjamin Herrenschmidt 	std	r11,_XER(r1);						   \
5388aa34ab8SBenjamin Herrenschmidt 	li	r9,(n)+1;						   \
5398aa34ab8SBenjamin Herrenschmidt 	std	r9,_TRAP(r1);		/* set trap number		*/ \
5408aa34ab8SBenjamin Herrenschmidt 	li	r10,0;							   \
5418aa34ab8SBenjamin Herrenschmidt 	ld	r11,exception_marker@toc(r2);				   \
5428aa34ab8SBenjamin Herrenschmidt 	std	r10,RESULT(r1);		/* clear regs->result		*/ \
543b14a7253SMahesh Salgaonkar 	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/
5448aa34ab8SBenjamin Herrenschmidt 
5458aa34ab8SBenjamin Herrenschmidt /*
5468aa34ab8SBenjamin Herrenschmidt  * Exception vectors.
5478aa34ab8SBenjamin Herrenschmidt  */
548e899fce5SMichael Ellerman #define STD_EXCEPTION(vec, label)				\
549bdf08e1dSMichael Ellerman 	EXCEPTION_PROLOG(PACA_EXGEN, label, EXC_STD, KVMTEST_PR, vec);
5508aa34ab8SBenjamin Herrenschmidt 
5511707dd16SPaul Mackerras /* Version of above for when we have to branch out-of-line */
552da2bc464SMichael Ellerman #define __OOL_EXCEPTION(vec, label, hdlr)			\
5534b1f5cccSNicholas Piggin 	SET_SCRATCH0(r13);					\
5544b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG_0(PACA_EXGEN);				\
5554b1f5cccSNicholas Piggin 	b hdlr
556da2bc464SMichael Ellerman 
55775e8bef3SMichael Ellerman #define STD_EXCEPTION_OOL(vec, label)				\
558da2bc464SMichael Ellerman 	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec);	\
559cb58a4a4SMichael Ellerman 	EXCEPTION_PROLOG_2(label, EXC_STD)
5601707dd16SPaul Mackerras 
561b3e6b5dfSBenjamin Herrenschmidt #define STD_EXCEPTION_HV(loc, vec, label)			\
5624b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG(PACA_EXGEN, label, EXC_HV, KVMTEST_HV, vec)
5638aa34ab8SBenjamin Herrenschmidt 
5641707dd16SPaul Mackerras #define STD_EXCEPTION_HV_OOL(vec, label)			\
565da2bc464SMichael Ellerman 	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec);	\
566cb58a4a4SMichael Ellerman 	EXCEPTION_PROLOG_2(label, EXC_HV)
5671707dd16SPaul Mackerras 
568e42389c5SMichael Ellerman #define STD_RELON_EXCEPTION(loc, vec, label)		\
5694700dfafSMichael Neuling 	/* No guest interrupts come through here */	\
5704b1f5cccSNicholas Piggin 	EXCEPTION_RELON_PROLOG(PACA_EXGEN, label, EXC_STD, NOTEST, vec)
5714700dfafSMichael Neuling 
572b706f423SMichael Ellerman #define STD_RELON_EXCEPTION_OOL(vec, label)			\
573c9f69518SMichael Ellerman 	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\
5746ebb9397SMichael Ellerman 	EXCEPTION_PROLOG_2_RELON(label, EXC_STD)
5751707dd16SPaul Mackerras 
5764700dfafSMichael Neuling #define STD_RELON_EXCEPTION_HV(loc, vec, label)		\
5774b1f5cccSNicholas Piggin 	EXCEPTION_RELON_PROLOG(PACA_EXGEN, label, EXC_HV, KVMTEST_HV, vec)
5784700dfafSMichael Neuling 
5791707dd16SPaul Mackerras #define STD_RELON_EXCEPTION_HV_OOL(vec, label)			\
580bc355125SPaul Mackerras 	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec);	\
5816ebb9397SMichael Ellerman 	EXCEPTION_PROLOG_2_RELON(label, EXC_HV)
5821707dd16SPaul Mackerras 
5837230c564SBenjamin Herrenschmidt /* This associate vector numbers with bits in paca->irq_happened */
5847230c564SBenjamin Herrenschmidt #define SOFTEN_VALUE_0x500	PACA_IRQ_EE
5857230c564SBenjamin Herrenschmidt #define SOFTEN_VALUE_0x900	PACA_IRQ_DEC
586da2bc464SMichael Ellerman #define SOFTEN_VALUE_0x980	PACA_IRQ_DEC
5871dbdafecSIan Munsie #define SOFTEN_VALUE_0xa00	PACA_IRQ_DBELL
588655bb3f4SIan Munsie #define SOFTEN_VALUE_0xe80	PACA_IRQ_DBELL
5890869b6fdSMahesh Salgaonkar #define SOFTEN_VALUE_0xe60	PACA_IRQ_HMI
5909baaef0aSBenjamin Herrenschmidt #define SOFTEN_VALUE_0xea0	PACA_IRQ_EE
591f442d004SMadhavan Srinivasan #define SOFTEN_VALUE_0xf00	PACA_IRQ_PMI
5927230c564SBenjamin Herrenschmidt 
593f14e953bSMadhavan Srinivasan #define __SOFTEN_TEST(h, vec, bitmask)					\
5944e26bc4aSMadhavan Srinivasan 	lbz	r10,PACAIRQSOFTMASK(r13);				\
595f14e953bSMadhavan Srinivasan 	andi.	r10,r10,bitmask;					\
5967230c564SBenjamin Herrenschmidt 	li	r10,SOFTEN_VALUE_##vec;					\
59701417c6cSMadhavan Srinivasan 	bne	masked_##h##interrupt
598da2bc464SMichael Ellerman 
599f14e953bSMadhavan Srinivasan #define _SOFTEN_TEST(h, vec, bitmask)	__SOFTEN_TEST(h, vec, bitmask)
600b01c8b54SPaul Mackerras 
601f14e953bSMadhavan Srinivasan #define SOFTEN_TEST_PR(vec, bitmask)					\
602da2bc464SMichael Ellerman 	KVMTEST(EXC_STD, vec);						\
603f14e953bSMadhavan Srinivasan 	_SOFTEN_TEST(EXC_STD, vec, bitmask)
604b01c8b54SPaul Mackerras 
605f14e953bSMadhavan Srinivasan #define SOFTEN_TEST_HV(vec, bitmask)					\
606da2bc464SMichael Ellerman 	KVMTEST(EXC_HV, vec);						\
607f14e953bSMadhavan Srinivasan 	_SOFTEN_TEST(EXC_HV, vec, bitmask)
608b01c8b54SPaul Mackerras 
609da2bc464SMichael Ellerman #define KVMTEST_PR(vec)							\
610da2bc464SMichael Ellerman 	KVMTEST(EXC_STD, vec)
611da2bc464SMichael Ellerman 
612da2bc464SMichael Ellerman #define KVMTEST_HV(vec)							\
613da2bc464SMichael Ellerman 	KVMTEST(EXC_HV, vec)
614da2bc464SMichael Ellerman 
615f14e953bSMadhavan Srinivasan #define SOFTEN_NOTEST_PR(vec, bitmask)	_SOFTEN_TEST(EXC_STD, vec, bitmask)
616f14e953bSMadhavan Srinivasan #define SOFTEN_NOTEST_HV(vec, bitmask)	_SOFTEN_TEST(EXC_HV, vec, bitmask)
6174700dfafSMichael Neuling 
6180a55c241SMichael Ellerman #define __MASKABLE_EXCEPTION(vec, label, h, extra, bitmask)		\
619b01c8b54SPaul Mackerras 	SET_SCRATCH0(r13);    /* save r13 */				\
6201707dd16SPaul Mackerras 	EXCEPTION_PROLOG_0(PACA_EXGEN);					\
621f14e953bSMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec, bitmask);	\
6224b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG_2(label, h)
6231707dd16SPaul Mackerras 
624b536da7cSMichael Ellerman #define MASKABLE_EXCEPTION(vec, label, bitmask)				\
6250a55c241SMichael Ellerman 	__MASKABLE_EXCEPTION(vec, label, EXC_STD, SOFTEN_TEST_PR, bitmask)
626b3e6b5dfSBenjamin Herrenschmidt 
6270a55c241SMichael Ellerman #define MASKABLE_EXCEPTION_OOL(vec, label, bitmask)			\
628f14e953bSMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_PR, vec, bitmask);\
629cb58a4a4SMichael Ellerman 	EXCEPTION_PROLOG_2(label, EXC_STD)
630da2bc464SMichael Ellerman 
631b536da7cSMichael Ellerman #define MASKABLE_EXCEPTION_HV(vec, label, bitmask)			\
6320a55c241SMichael Ellerman 	__MASKABLE_EXCEPTION(vec, label, EXC_HV, SOFTEN_TEST_HV, bitmask)
6338aa34ab8SBenjamin Herrenschmidt 
634f14e953bSMadhavan Srinivasan #define MASKABLE_EXCEPTION_HV_OOL(vec, label, bitmask)			\
635f14e953bSMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec, bitmask);\
636cb58a4a4SMichael Ellerman 	EXCEPTION_PROLOG_2(label, EXC_HV)
6371707dd16SPaul Mackerras 
6380a55c241SMichael Ellerman #define __MASKABLE_RELON_EXCEPTION(vec, label, h, extra, bitmask)	\
6394700dfafSMichael Neuling 	SET_SCRATCH0(r13);    /* save r13 */				\
6401707dd16SPaul Mackerras 	EXCEPTION_PROLOG_0(PACA_EXGEN);					\
641f14e953bSMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec, bitmask);	\
6426ebb9397SMichael Ellerman 	EXCEPTION_PROLOG_2_RELON(label, h)
643da2bc464SMichael Ellerman 
644b536da7cSMichael Ellerman #define MASKABLE_RELON_EXCEPTION(vec, label, bitmask)			\
6450a55c241SMichael Ellerman 	__MASKABLE_RELON_EXCEPTION(vec, label, EXC_STD, SOFTEN_NOTEST_PR, bitmask)
6464700dfafSMichael Neuling 
6470a55c241SMichael Ellerman #define MASKABLE_RELON_EXCEPTION_OOL(vec, label, bitmask)		\
648f442d004SMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_PR, vec, bitmask);\
6494b1f5cccSNicholas Piggin 	EXCEPTION_PROLOG_2(label, EXC_STD)
650f442d004SMadhavan Srinivasan 
651b536da7cSMichael Ellerman #define MASKABLE_RELON_EXCEPTION_HV(vec, label, bitmask)		\
6520a55c241SMichael Ellerman 	__MASKABLE_RELON_EXCEPTION(vec, label, EXC_HV, SOFTEN_TEST_HV, bitmask)
6534700dfafSMichael Neuling 
654f14e953bSMadhavan Srinivasan #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label, bitmask)		\
6555c11d1e5SMadhavan Srinivasan 	MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec, bitmask);\
6566ebb9397SMichael Ellerman 	EXCEPTION_PROLOG_2_RELON(label, EXC_HV)
6571707dd16SPaul Mackerras 
6581b701179SBenjamin Herrenschmidt /*
6591b701179SBenjamin Herrenschmidt  * Our exception common code can be passed various "additions"
6601b701179SBenjamin Herrenschmidt  * to specify the behaviour of interrupts, whether to kick the
6611b701179SBenjamin Herrenschmidt  * runlatch, etc...
6621b701179SBenjamin Herrenschmidt  */
6631b701179SBenjamin Herrenschmidt 
6649daf112bSMichael Ellerman /*
6659daf112bSMichael Ellerman  * This addition reconciles our actual IRQ state with the various software
6669daf112bSMichael Ellerman  * flags that track it. This may call C code.
6679daf112bSMichael Ellerman  */
6689daf112bSMichael Ellerman #define ADD_RECONCILE	RECONCILE_IRQ_STATE(r10,r11)
6698aa34ab8SBenjamin Herrenschmidt 
670fe1952fcSBenjamin Herrenschmidt #define ADD_NVGPRS				\
671b1576fecSAnton Blanchard 	bl	save_nvgprs
672fe1952fcSBenjamin Herrenschmidt 
673fe1952fcSBenjamin Herrenschmidt #define RUNLATCH_ON				\
674fe1952fcSBenjamin Herrenschmidt BEGIN_FTR_SECTION				\
675c911d2e1SChristophe Leroy 	ld	r3, PACA_THREAD_INFO(r13);	\
676fe1952fcSBenjamin Herrenschmidt 	ld	r4,TI_LOCAL_FLAGS(r3);		\
677fe1952fcSBenjamin Herrenschmidt 	andi.	r0,r4,_TLF_RUNLATCH;		\
678fe1952fcSBenjamin Herrenschmidt 	beql	ppc64_runlatch_on_trampoline;	\
679fe1952fcSBenjamin Herrenschmidt END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
680fe1952fcSBenjamin Herrenschmidt 
681a3d96f70SNicholas Piggin #define EXCEPTION_COMMON(area, trap, label, hdlr, ret, additions) \
682a3d96f70SNicholas Piggin 	EXCEPTION_PROLOG_COMMON(trap, area);			\
683a1d711c5SMichael Ellerman 	/* Volatile regs are potentially clobbered here */	\
684fe1952fcSBenjamin Herrenschmidt 	additions;						\
6858aa34ab8SBenjamin Herrenschmidt 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
6868aa34ab8SBenjamin Herrenschmidt 	bl	hdlr;						\
687fe1952fcSBenjamin Herrenschmidt 	b	ret
688fe1952fcSBenjamin Herrenschmidt 
689b1ee8a3dSNicholas Piggin /*
690b1ee8a3dSNicholas Piggin  * Exception where stack is already set in r1, r1 is saved in r10, and it
691b1ee8a3dSNicholas Piggin  * continues rather than returns.
692b1ee8a3dSNicholas Piggin  */
693b1ee8a3dSNicholas Piggin #define EXCEPTION_COMMON_NORET_STACK(area, trap, label, hdlr, additions) \
694b1ee8a3dSNicholas Piggin 	EXCEPTION_PROLOG_COMMON_1();				\
695890274c2SMichael Ellerman 	kuap_save_amr_and_lock r9, r10, cr1;			\
696b1ee8a3dSNicholas Piggin 	EXCEPTION_PROLOG_COMMON_2(area);			\
697b1ee8a3dSNicholas Piggin 	EXCEPTION_PROLOG_COMMON_3(trap);			\
698b1ee8a3dSNicholas Piggin 	/* Volatile regs are potentially clobbered here */	\
699b1ee8a3dSNicholas Piggin 	additions;						\
700b1ee8a3dSNicholas Piggin 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
701b1ee8a3dSNicholas Piggin 	bl	hdlr
702b1ee8a3dSNicholas Piggin 
703fe1952fcSBenjamin Herrenschmidt #define STD_EXCEPTION_COMMON(trap, label, hdlr)			\
704a3d96f70SNicholas Piggin 	EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,		\
705a3d96f70SNicholas Piggin 		ret_from_except, ADD_NVGPRS;ADD_RECONCILE)
7068aa34ab8SBenjamin Herrenschmidt 
7078aa34ab8SBenjamin Herrenschmidt /*
7088aa34ab8SBenjamin Herrenschmidt  * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
7097450f6f0SBenjamin Herrenschmidt  * in the idle task and therefore need the special idle handling
7107450f6f0SBenjamin Herrenschmidt  * (finish nap and runlatch)
7118aa34ab8SBenjamin Herrenschmidt  */
7127450f6f0SBenjamin Herrenschmidt #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)		\
713a3d96f70SNicholas Piggin 	EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,		\
714a3d96f70SNicholas Piggin 		ret_from_except_lite, FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
7158aa34ab8SBenjamin Herrenschmidt 
7168aa34ab8SBenjamin Herrenschmidt /*
7178aa34ab8SBenjamin Herrenschmidt  * When the idle code in power4_idle puts the CPU into NAP mode,
7188aa34ab8SBenjamin Herrenschmidt  * it has to do so in a loop, and relies on the external interrupt
7198aa34ab8SBenjamin Herrenschmidt  * and decrementer interrupt entry code to get it out of the loop.
7208aa34ab8SBenjamin Herrenschmidt  * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags
7218aa34ab8SBenjamin Herrenschmidt  * to signal that it is in the loop and needs help to get out.
7228aa34ab8SBenjamin Herrenschmidt  */
7238aa34ab8SBenjamin Herrenschmidt #ifdef CONFIG_PPC_970_NAP
7248aa34ab8SBenjamin Herrenschmidt #define FINISH_NAP				\
7258aa34ab8SBenjamin Herrenschmidt BEGIN_FTR_SECTION				\
726c911d2e1SChristophe Leroy 	ld	r11, PACA_THREAD_INFO(r13);	\
7278aa34ab8SBenjamin Herrenschmidt 	ld	r9,TI_LOCAL_FLAGS(r11);		\
7288aa34ab8SBenjamin Herrenschmidt 	andi.	r10,r9,_TLF_NAPPING;		\
7298aa34ab8SBenjamin Herrenschmidt 	bnel	power4_fixup_nap;		\
7308aa34ab8SBenjamin Herrenschmidt END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
7318aa34ab8SBenjamin Herrenschmidt #else
7328aa34ab8SBenjamin Herrenschmidt #define FINISH_NAP
7338aa34ab8SBenjamin Herrenschmidt #endif
7348aa34ab8SBenjamin Herrenschmidt 
7358aa34ab8SBenjamin Herrenschmidt #endif	/* _ASM_POWERPC_EXCEPTION_H */
736