xref: /linux/arch/powerpc/include/asm/interrupt.h (revision 5b0764a53235d3c77e1ed674e836e1b3fe1a4b1f)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef _ASM_POWERPC_INTERRUPT_H
3 #define _ASM_POWERPC_INTERRUPT_H
4 
5 /* BookE/4xx */
6 #define INTERRUPT_CRITICAL_INPUT  0x100
7 
8 /* BookE */
9 #define INTERRUPT_DEBUG           0xd00
10 #ifdef CONFIG_BOOKE
11 #define INTERRUPT_PERFMON         0x260
12 #define INTERRUPT_DOORBELL        0x280
13 #endif
14 
15 /* BookS/4xx/8xx */
16 #define INTERRUPT_MACHINE_CHECK   0x200
17 
18 /* BookS/8xx */
19 #define INTERRUPT_SYSTEM_RESET    0x100
20 
21 /* BookS */
22 #define INTERRUPT_DATA_SEGMENT    0x380
23 #define INTERRUPT_INST_SEGMENT    0x480
24 #define INTERRUPT_TRACE           0xd00
25 #define INTERRUPT_H_DATA_STORAGE  0xe00
26 #define INTERRUPT_HMI			0xe60
27 #define INTERRUPT_H_FAC_UNAVAIL   0xf80
28 #ifdef CONFIG_PPC_BOOK3S
29 #define INTERRUPT_DOORBELL        0xa00
30 #define INTERRUPT_PERFMON         0xf00
31 #define INTERRUPT_ALTIVEC_UNAVAIL	0xf20
32 #endif
33 
34 /* BookE/BookS/4xx/8xx */
35 #define INTERRUPT_DATA_STORAGE    0x300
36 #define INTERRUPT_INST_STORAGE    0x400
37 #define INTERRUPT_EXTERNAL		0x500
38 #define INTERRUPT_ALIGNMENT       0x600
39 #define INTERRUPT_PROGRAM         0x700
40 #define INTERRUPT_SYSCALL         0xc00
41 #define INTERRUPT_TRACE			0xd00
42 
43 /* BookE/BookS/44x */
44 #define INTERRUPT_FP_UNAVAIL      0x800
45 
46 /* BookE/BookS/44x/8xx */
47 #define INTERRUPT_DECREMENTER     0x900
48 
49 #ifndef INTERRUPT_PERFMON
50 #define INTERRUPT_PERFMON         0x0
51 #endif
52 
53 /* 8xx */
54 #define INTERRUPT_SOFT_EMU_8xx		0x1000
55 #define INTERRUPT_INST_TLB_MISS_8xx	0x1100
56 #define INTERRUPT_DATA_TLB_MISS_8xx	0x1200
57 #define INTERRUPT_INST_TLB_ERROR_8xx	0x1300
58 #define INTERRUPT_DATA_TLB_ERROR_8xx	0x1400
59 #define INTERRUPT_DATA_BREAKPOINT_8xx	0x1c00
60 #define INTERRUPT_INST_BREAKPOINT_8xx	0x1d00
61 
62 /* 603 */
63 #define INTERRUPT_INST_TLB_MISS_603		0x1000
64 #define INTERRUPT_DATA_LOAD_TLB_MISS_603	0x1100
65 #define INTERRUPT_DATA_STORE_TLB_MISS_603	0x1200
66 
67 #ifndef __ASSEMBLER__
68 
69 #include <linux/sched/debug.h> /* for show_regs */
70 #include <linux/irq-entry-common.h>
71 
72 #include <asm/kprobes.h>
73 #include <asm/mmu.h>
74 #include <asm/runlatch.h>
75 
76 #ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
77 /*
78  * WARN/BUG is handled with a program interrupt so minimise checks here to
79  * avoid recursion and maximise the chance of getting the first oops handled.
80  */
81 #define INT_SOFT_MASK_BUG_ON(regs, cond)				\
82 do {									\
83 	if ((user_mode(regs) || (TRAP(regs) != INTERRUPT_PROGRAM)))	\
84 		BUG_ON(cond);						\
85 } while (0)
86 #else
87 #define INT_SOFT_MASK_BUG_ON(regs, cond)
88 #endif
89 
90 /*
91  * Don't use noinstr here like x86, but rather add NOKPROBE_SYMBOL to each
92  * function definition. The reason for this is the noinstr section is placed
93  * after the main text section, i.e., very far away from the interrupt entry
94  * asm. That creates problems with fitting linker stubs when building large
95  * kernels.
96  */
97 #define interrupt_handler __visible noinline notrace __no_kcsan __no_sanitize_address
98 
99 /**
100  * DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function
101  * @func:	Function name of the entry point
102  * @returns:	Returns a value back to asm caller
103  */
104 #define DECLARE_INTERRUPT_HANDLER_RAW(func)				\
105 	__visible long func(struct pt_regs *regs)
106 
107 /**
108  * DEFINE_INTERRUPT_HANDLER_RAW - Define raw interrupt handler function
109  * @func:	Function name of the entry point
110  * @returns:	Returns a value back to asm caller
111  *
112  * @func is called from ASM entry code.
113  *
114  * This is a plain function which does no tracing, reconciling, etc.
115  * The macro is written so it acts as function definition. Append the
116  * body with a pair of curly brackets.
117  *
118  * raw interrupt handlers must not enable or disable interrupts, or
119  * schedule, tracing and instrumentation (ftrace, lockdep, etc) would
120  * not be advisable either, although may be possible in a pinch, the
121  * trace will look odd at least.
122  *
123  * A raw handler may call one of the other interrupt handler functions
124  * to be converted into that interrupt context without these restrictions.
125  *
126  * On PPC64, _RAW handlers may return with fast_interrupt_return.
127  *
128  * Specific handlers may have additional restrictions.
129  */
130 #define DEFINE_INTERRUPT_HANDLER_RAW(func)				\
131 static __always_inline __no_sanitize_address __no_kcsan long		\
132 ____##func(struct pt_regs *regs);					\
133 									\
134 interrupt_handler long func(struct pt_regs *regs)			\
135 {									\
136 	long ret;							\
137 									\
138 	__hard_RI_enable();						\
139 									\
140 	ret = ____##func (regs);					\
141 									\
142 	return ret;							\
143 }									\
144 NOKPROBE_SYMBOL(func);							\
145 									\
146 static __always_inline __no_sanitize_address __no_kcsan long		\
147 ____##func(struct pt_regs *regs)
148 
149 /**
150  * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function
151  * @func:	Function name of the entry point
152  */
153 #define DECLARE_INTERRUPT_HANDLER(func)					\
154 	__visible void func(struct pt_regs *regs)
155 
156 /**
157  * DEFINE_INTERRUPT_HANDLER - Define synchronous interrupt handler function
158  * @func:	Function name of the entry point
159  *
160  * @func is called from ASM entry code.
161  *
162  * The macro is written so it acts as function definition. Append the
163  * body with a pair of curly brackets.
164  */
165 #define DEFINE_INTERRUPT_HANDLER(func)					\
166 static __always_inline void ____##func(struct pt_regs *regs);		\
167 									\
168 interrupt_handler void func(struct pt_regs *regs)			\
169 {									\
170 	irqentry_state_t state;						\
171 	arch_interrupt_enter_prepare(regs);				\
172 	state = irqentry_enter(regs);					\
173 	instrumentation_begin();					\
174 	____##func (regs);						\
175 	instrumentation_end();						\
176 	arch_interrupt_exit_prepare(regs);				\
177 	irqentry_exit(regs, state);					\
178 }									\
179 NOKPROBE_SYMBOL(func);							\
180 									\
181 static __always_inline void ____##func(struct pt_regs *regs)
182 
183 /**
184  * DECLARE_INTERRUPT_HANDLER_RET - Declare synchronous interrupt handler function
185  * @func:	Function name of the entry point
186  * @returns:	Returns a value back to asm caller
187  */
188 #define DECLARE_INTERRUPT_HANDLER_RET(func)				\
189 	__visible long func(struct pt_regs *regs)
190 
191 /**
192  * DEFINE_INTERRUPT_HANDLER_RET - Define synchronous interrupt handler function
193  * @func:	Function name of the entry point
194  * @returns:	Returns a value back to asm caller
195  *
196  * @func is called from ASM entry code.
197  *
198  * The macro is written so it acts as function definition. Append the
199  * body with a pair of curly brackets.
200  */
201 #define DEFINE_INTERRUPT_HANDLER_RET(func)				\
202 static __always_inline long ____##func(struct pt_regs *regs);		\
203 									\
204 interrupt_handler long func(struct pt_regs *regs)			\
205 {									\
206 	long ret;							\
207 	irqentry_state_t state;						\
208 									\
209 	arch_interrupt_enter_prepare(regs);				\
210 	state = irqentry_enter(regs);					\
211 	instrumentation_begin();					\
212 	ret = ____##func (regs);					\
213 	instrumentation_end();						\
214 	arch_interrupt_exit_prepare(regs);				\
215 	irqentry_exit(regs, state);					\
216 									\
217 	return ret;							\
218 }									\
219 NOKPROBE_SYMBOL(func);							\
220 									\
221 static __always_inline long ____##func(struct pt_regs *regs)
222 
223 /**
224  * DECLARE_INTERRUPT_HANDLER_ASYNC - Declare asynchronous interrupt handler function
225  * @func:	Function name of the entry point
226  */
227 #define DECLARE_INTERRUPT_HANDLER_ASYNC(func)				\
228 	__visible void func(struct pt_regs *regs)
229 
230 /**
231  * DEFINE_INTERRUPT_HANDLER_ASYNC - Define asynchronous interrupt handler function
232  * @func:	Function name of the entry point
233  *
234  * @func is called from ASM entry code.
235  *
236  * The macro is written so it acts as function definition. Append the
237  * body with a pair of curly brackets.
238  */
239 #define DEFINE_INTERRUPT_HANDLER_ASYNC(func)				\
240 static __always_inline void ____##func(struct pt_regs *regs);		\
241 									\
242 interrupt_handler void func(struct pt_regs *regs)			\
243 {									\
244 	irqentry_state_t state;						\
245 	arch_interrupt_async_enter_prepare(regs);			\
246 	state = irqentry_enter(regs);					\
247 	instrumentation_begin();					\
248 	irq_enter_rcu();						\
249 	____##func (regs);						\
250 	nap_adjust_return(regs);					\
251 	irq_exit_rcu();							\
252 	instrumentation_end();						\
253 	arch_interrupt_async_exit_prepare(regs);			\
254 	irqentry_exit(regs, state);					\
255 }									\
256 NOKPROBE_SYMBOL(func);							\
257 									\
258 static __always_inline void ____##func(struct pt_regs *regs)
259 
260 /**
261  * DECLARE_INTERRUPT_HANDLER_NMI - Declare NMI interrupt handler function
262  * @func:	Function name of the entry point
263  * @returns:	Returns a value back to asm caller
264  */
265 #define DECLARE_INTERRUPT_HANDLER_NMI(func)				\
266 	__visible long func(struct pt_regs *regs)
267 
268 /**
269  * DEFINE_INTERRUPT_HANDLER_NMI - Define NMI interrupt handler function
270  * @func:	Function name of the entry point
271  * @returns:	Returns a value back to asm caller
272  *
273  * @func is called from ASM entry code.
274  *
275  * The macro is written so it acts as function definition. Append the
276  * body with a pair of curly brackets.
277  */
278 #define DEFINE_INTERRUPT_HANDLER_NMI(func)				\
279 static __always_inline __no_sanitize_address __no_kcsan long		\
280 ____##func(struct pt_regs *regs);					\
281 									\
282 interrupt_handler long func(struct pt_regs *regs)			\
283 {									\
284 	irqentry_state_t state;						\
285 	struct interrupt_nmi_state nmi_state;				\
286 	long ret;							\
287 									\
288 	arch_interrupt_nmi_enter_prepare(regs, &nmi_state);		\
289 	if (mfmsr() & MSR_DR) {						\
290 		/* nmi_entry if relocations are on */			\
291 		state = irqentry_nmi_enter(regs);			\
292 	} else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&			\
293 		   firmware_has_feature(FW_FEATURE_LPAR) &&		\
294 		   !early_radix_enabled()) {				\
295 		/* no nmi_entry for a pseries hash guest		\
296 		 * taking a real mode exception */			\
297 	} else if (IS_ENABLED(CONFIG_KASAN)) {				\
298 		/* no nmi_entry for KASAN in real mode */		\
299 	} else if (percpu_first_chunk_is_paged) {			\
300 		/* no nmi_entry if percpu first chunk is not embedded */\
301 	} else {							\
302 		state = irqentry_nmi_enter(regs);			\
303 	}								\
304 	ret = ____##func (regs);					\
305 	if (mfmsr() & MSR_DR) {						\
306 		/* nmi_exit if relocations are on */			\
307 		irqentry_nmi_exit(regs, state);				\
308 	} else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&			\
309 		   firmware_has_feature(FW_FEATURE_LPAR) &&		\
310 		   !early_radix_enabled()) {				\
311 		/* no nmi_exit for a pseries hash guest			\
312 		 * taking a real mode exception */			\
313 	} else if (IS_ENABLED(CONFIG_KASAN)) {				\
314 		/* no nmi_exit for KASAN in real mode */		\
315 	} else if (percpu_first_chunk_is_paged) {			\
316 		/* no nmi_exit if percpu first chunk is not embedded */	\
317 	} else {							\
318 		irqentry_nmi_exit(regs, state);				\
319 	}								\
320 	arch_interrupt_nmi_exit_prepare(regs, &nmi_state);		\
321 									\
322 	return ret;							\
323 }									\
324 NOKPROBE_SYMBOL(func);							\
325 									\
326 static __always_inline  __no_sanitize_address __no_kcsan long		\
327 ____##func(struct pt_regs *regs)
328 
329 
330 /* Interrupt handlers */
331 /* kernel/traps.c */
332 DECLARE_INTERRUPT_HANDLER_NMI(system_reset_exception);
333 #ifdef CONFIG_PPC_BOOK3S_64
334 DECLARE_INTERRUPT_HANDLER_RAW(machine_check_early_boot);
335 DECLARE_INTERRUPT_HANDLER_ASYNC(machine_check_exception_async);
336 #endif
337 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_exception);
338 DECLARE_INTERRUPT_HANDLER(SMIException);
339 DECLARE_INTERRUPT_HANDLER(handle_hmi_exception);
340 DECLARE_INTERRUPT_HANDLER(unknown_exception);
341 DECLARE_INTERRUPT_HANDLER_ASYNC(unknown_async_exception);
342 DECLARE_INTERRUPT_HANDLER_NMI(unknown_nmi_exception);
343 DECLARE_INTERRUPT_HANDLER(instruction_breakpoint_exception);
344 DECLARE_INTERRUPT_HANDLER(RunModeException);
345 DECLARE_INTERRUPT_HANDLER(single_step_exception);
346 DECLARE_INTERRUPT_HANDLER(program_check_exception);
347 DECLARE_INTERRUPT_HANDLER(emulation_assist_interrupt);
348 DECLARE_INTERRUPT_HANDLER(alignment_exception);
349 DECLARE_INTERRUPT_HANDLER(StackOverflow);
350 DECLARE_INTERRUPT_HANDLER(stack_overflow_exception);
351 DECLARE_INTERRUPT_HANDLER(kernel_fp_unavailable_exception);
352 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_exception);
353 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_exception);
354 DECLARE_INTERRUPT_HANDLER(facility_unavailable_exception);
355 DECLARE_INTERRUPT_HANDLER(fp_unavailable_tm);
356 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_tm);
357 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_tm);
358 DECLARE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi);
359 DECLARE_INTERRUPT_HANDLER_ASYNC(performance_monitor_exception_async);
360 DECLARE_INTERRUPT_HANDLER_RAW(performance_monitor_exception);
361 DECLARE_INTERRUPT_HANDLER(DebugException);
362 DECLARE_INTERRUPT_HANDLER(altivec_assist_exception);
363 DECLARE_INTERRUPT_HANDLER(CacheLockingException);
364 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointException);
365 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointRoundException);
366 DECLARE_INTERRUPT_HANDLER_NMI(WatchdogException);
367 DECLARE_INTERRUPT_HANDLER(kernel_bad_stack);
368 
369 /* slb.c */
370 DECLARE_INTERRUPT_HANDLER_RAW(do_slb_fault);
371 DECLARE_INTERRUPT_HANDLER(do_bad_segment_interrupt);
372 
373 /* hash_utils.c */
374 DECLARE_INTERRUPT_HANDLER(do_hash_fault);
375 
376 /* fault.c */
377 DECLARE_INTERRUPT_HANDLER(do_page_fault);
378 DECLARE_INTERRUPT_HANDLER(do_bad_page_fault_segv);
379 
380 /* process.c */
381 DECLARE_INTERRUPT_HANDLER(do_break);
382 
383 /* time.c */
384 DECLARE_INTERRUPT_HANDLER_ASYNC(timer_interrupt);
385 
386 /* mce.c */
387 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_early);
388 DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
389 
390 DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
391 
392 /* irq.c */
393 DECLARE_INTERRUPT_HANDLER_ASYNC(do_IRQ);
394 
395 void __noreturn unrecoverable_exception(struct pt_regs *regs);
396 
397 void replay_system_reset(void);
398 void replay_soft_interrupts(void);
399 
400 static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
401 {
402 	if (!regs_irqs_disabled(regs))
403 		local_irq_enable();
404 }
405 
406 long system_call_exception(struct pt_regs *regs, unsigned long r0);
407 notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv);
408 notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs);
409 notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs);
410 #ifdef CONFIG_PPC64
411 unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs);
412 unsigned long interrupt_exit_user_restart(struct pt_regs *regs);
413 unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs);
414 #endif
415 
416 #endif /* __ASSEMBLER__ */
417 
418 #endif /* _ASM_POWERPC_INTERRUPT_H */
419