xref: /linux/arch/powerpc/include/asm/interrupt.h (revision 74205b3fc2effde821b219d955c70e727dc43cc6)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef _ASM_POWERPC_INTERRUPT_H
3 #define _ASM_POWERPC_INTERRUPT_H
4 
5 #include <linux/context_tracking.h>
6 #include <linux/hardirq.h>
7 #include <asm/cputime.h>
8 #include <asm/ftrace.h>
9 #include <asm/kprobes.h>
10 #include <asm/runlatch.h>
11 
12 static inline void nap_adjust_return(struct pt_regs *regs)
13 {
14 #ifdef CONFIG_PPC_970_NAP
15 	if (unlikely(test_thread_local_flags(_TLF_NAPPING))) {
16 		/* Can avoid a test-and-clear because NMIs do not call this */
17 		clear_thread_local_flags(_TLF_NAPPING);
18 		regs->nip = (unsigned long)power4_idle_nap_return;
19 	}
20 #endif
21 }
22 
23 struct interrupt_state {
24 };
25 
26 static inline void booke_restore_dbcr0(void)
27 {
28 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
29 	unsigned long dbcr0 = current->thread.debug.dbcr0;
30 
31 	if (IS_ENABLED(CONFIG_PPC32) && unlikely(dbcr0 & DBCR0_IDM)) {
32 		mtspr(SPRN_DBSR, -1);
33 		mtspr(SPRN_DBCR0, global_dbcr0[smp_processor_id()]);
34 	}
35 #endif
36 }
37 
38 static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
39 {
40 #ifdef CONFIG_PPC32
41 	if (!arch_irq_disabled_regs(regs))
42 		trace_hardirqs_off();
43 
44 	if (user_mode(regs)) {
45 		kuep_lock();
46 		account_cpu_user_entry();
47 	} else {
48 		kuap_save_and_lock(regs);
49 	}
50 #endif
51 
52 #ifdef CONFIG_PPC64
53 	if (irq_soft_mask_set_return(IRQS_ALL_DISABLED) == IRQS_ENABLED)
54 		trace_hardirqs_off();
55 	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
56 
57 	if (user_mode(regs)) {
58 		CT_WARN_ON(ct_state() != CONTEXT_USER);
59 		user_exit_irqoff();
60 
61 		account_cpu_user_entry();
62 		account_stolen_time();
63 	} else {
64 		/*
65 		 * CT_WARN_ON comes here via program_check_exception,
66 		 * so avoid recursion.
67 		 */
68 		if (TRAP(regs) != 0x700)
69 			CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
70 	}
71 #endif
72 
73 	booke_restore_dbcr0();
74 }
75 
76 /*
77  * Care should be taken to note that interrupt_exit_prepare and
78  * interrupt_async_exit_prepare do not necessarily return immediately to
79  * regs context (e.g., if regs is usermode, we don't necessarily return to
80  * user mode). Other interrupts might be taken between here and return,
81  * context switch / preemption may occur in the exit path after this, or a
82  * signal may be delivered, etc.
83  *
84  * The real interrupt exit code is platform specific, e.g.,
85  * interrupt_exit_user_prepare / interrupt_exit_kernel_prepare for 64s.
86  *
87  * However interrupt_nmi_exit_prepare does return directly to regs, because
88  * NMIs do not do "exit work" or replay soft-masked interrupts.
89  */
90 static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
91 {
92 	if (user_mode(regs))
93 		kuep_unlock();
94 }
95 
96 static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
97 {
98 #ifdef CONFIG_PPC_BOOK3S_64
99 	if (cpu_has_feature(CPU_FTR_CTRL) &&
100 	    !test_thread_local_flags(_TLF_RUNLATCH))
101 		__ppc64_runlatch_on();
102 #endif
103 
104 	interrupt_enter_prepare(regs, state);
105 	irq_enter();
106 }
107 
108 static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
109 {
110 	/*
111 	 * Adjust at exit so the main handler sees the true NIA. This must
112 	 * come before irq_exit() because irq_exit can enable interrupts, and
113 	 * if another interrupt is taken before nap_adjust_return has run
114 	 * here, then that interrupt would return directly to idle nap return.
115 	 */
116 	nap_adjust_return(regs);
117 
118 	irq_exit();
119 	interrupt_exit_prepare(regs, state);
120 }
121 
122 struct interrupt_nmi_state {
123 #ifdef CONFIG_PPC64
124 	u8 irq_soft_mask;
125 	u8 irq_happened;
126 	u8 ftrace_enabled;
127 #endif
128 };
129 
130 static inline bool nmi_disables_ftrace(struct pt_regs *regs)
131 {
132 	/* Allow DEC and PMI to be traced when they are soft-NMI */
133 	if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
134 		if (TRAP(regs) == 0x900)
135 		       return false;
136 		if (TRAP(regs) == 0xf00)
137 		       return false;
138 	}
139 	if (IS_ENABLED(CONFIG_PPC_BOOK3E)) {
140 		if (TRAP(regs) == 0x260)
141 			return false;
142 	}
143 
144 	return true;
145 }
146 
147 static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
148 {
149 #ifdef CONFIG_PPC64
150 	state->irq_soft_mask = local_paca->irq_soft_mask;
151 	state->irq_happened = local_paca->irq_happened;
152 
153 	/*
154 	 * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
155 	 * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
156 	 * because that goes through irq tracing which we don't want in NMI.
157 	 */
158 	local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
159 	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
160 
161 	/* Don't do any per-CPU operations until interrupt state is fixed */
162 
163 	if (nmi_disables_ftrace(regs)) {
164 		state->ftrace_enabled = this_cpu_get_ftrace_enabled();
165 		this_cpu_set_ftrace_enabled(0);
166 	}
167 #endif
168 
169 	/*
170 	 * Do not use nmi_enter() for pseries hash guest taking a real-mode
171 	 * NMI because not everything it touches is within the RMA limit.
172 	 */
173 	if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
174 			!firmware_has_feature(FW_FEATURE_LPAR) ||
175 			radix_enabled() || (mfmsr() & MSR_DR))
176 		nmi_enter();
177 }
178 
179 static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
180 {
181 	if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
182 			!firmware_has_feature(FW_FEATURE_LPAR) ||
183 			radix_enabled() || (mfmsr() & MSR_DR))
184 		nmi_exit();
185 
186 	/*
187 	 * nmi does not call nap_adjust_return because nmi should not create
188 	 * new work to do (must use irq_work for that).
189 	 */
190 
191 #ifdef CONFIG_PPC64
192 	if (nmi_disables_ftrace(regs))
193 		this_cpu_set_ftrace_enabled(state->ftrace_enabled);
194 
195 	/* Check we didn't change the pending interrupt mask. */
196 	WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
197 	local_paca->irq_happened = state->irq_happened;
198 	local_paca->irq_soft_mask = state->irq_soft_mask;
199 #endif
200 }
201 
202 /*
203  * Don't use noinstr here like x86, but rather add NOKPROBE_SYMBOL to each
204  * function definition. The reason for this is the noinstr section is placed
205  * after the main text section, i.e., very far away from the interrupt entry
206  * asm. That creates problems with fitting linker stubs when building large
207  * kernels.
208  */
209 #define interrupt_handler __visible noinline notrace __no_kcsan __no_sanitize_address
210 
211 /**
212  * DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function
213  * @func:	Function name of the entry point
214  * @returns:	Returns a value back to asm caller
215  */
216 #define DECLARE_INTERRUPT_HANDLER_RAW(func)				\
217 	__visible long func(struct pt_regs *regs)
218 
219 /**
220  * DEFINE_INTERRUPT_HANDLER_RAW - Define raw interrupt handler function
221  * @func:	Function name of the entry point
222  * @returns:	Returns a value back to asm caller
223  *
224  * @func is called from ASM entry code.
225  *
226  * This is a plain function which does no tracing, reconciling, etc.
227  * The macro is written so it acts as function definition. Append the
228  * body with a pair of curly brackets.
229  *
230  * raw interrupt handlers must not enable or disable interrupts, or
231  * schedule, tracing and instrumentation (ftrace, lockdep, etc) would
232  * not be advisable either, although may be possible in a pinch, the
233  * trace will look odd at least.
234  *
235  * A raw handler may call one of the other interrupt handler functions
236  * to be converted into that interrupt context without these restrictions.
237  *
238  * On PPC64, _RAW handlers may return with fast_interrupt_return.
239  *
240  * Specific handlers may have additional restrictions.
241  */
242 #define DEFINE_INTERRUPT_HANDLER_RAW(func)				\
243 static __always_inline long ____##func(struct pt_regs *regs);		\
244 									\
245 interrupt_handler long func(struct pt_regs *regs)			\
246 {									\
247 	long ret;							\
248 									\
249 	ret = ____##func (regs);					\
250 									\
251 	return ret;							\
252 }									\
253 NOKPROBE_SYMBOL(func);							\
254 									\
255 static __always_inline long ____##func(struct pt_regs *regs)
256 
257 /**
258  * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function
259  * @func:	Function name of the entry point
260  */
261 #define DECLARE_INTERRUPT_HANDLER(func)					\
262 	__visible void func(struct pt_regs *regs)
263 
264 /**
265  * DEFINE_INTERRUPT_HANDLER - Define synchronous interrupt handler function
266  * @func:	Function name of the entry point
267  *
268  * @func is called from ASM entry code.
269  *
270  * The macro is written so it acts as function definition. Append the
271  * body with a pair of curly brackets.
272  */
273 #define DEFINE_INTERRUPT_HANDLER(func)					\
274 static __always_inline void ____##func(struct pt_regs *regs);		\
275 									\
276 interrupt_handler void func(struct pt_regs *regs)			\
277 {									\
278 	struct interrupt_state state;					\
279 									\
280 	interrupt_enter_prepare(regs, &state);				\
281 									\
282 	____##func (regs);						\
283 									\
284 	interrupt_exit_prepare(regs, &state);				\
285 }									\
286 NOKPROBE_SYMBOL(func);							\
287 									\
288 static __always_inline void ____##func(struct pt_regs *regs)
289 
290 /**
291  * DECLARE_INTERRUPT_HANDLER_RET - Declare synchronous interrupt handler function
292  * @func:	Function name of the entry point
293  * @returns:	Returns a value back to asm caller
294  */
295 #define DECLARE_INTERRUPT_HANDLER_RET(func)				\
296 	__visible long func(struct pt_regs *regs)
297 
298 /**
299  * DEFINE_INTERRUPT_HANDLER_RET - Define synchronous interrupt handler function
300  * @func:	Function name of the entry point
301  * @returns:	Returns a value back to asm caller
302  *
303  * @func is called from ASM entry code.
304  *
305  * The macro is written so it acts as function definition. Append the
306  * body with a pair of curly brackets.
307  */
308 #define DEFINE_INTERRUPT_HANDLER_RET(func)				\
309 static __always_inline long ____##func(struct pt_regs *regs);		\
310 									\
311 interrupt_handler long func(struct pt_regs *regs)			\
312 {									\
313 	struct interrupt_state state;					\
314 	long ret;							\
315 									\
316 	interrupt_enter_prepare(regs, &state);				\
317 									\
318 	ret = ____##func (regs);					\
319 									\
320 	interrupt_exit_prepare(regs, &state);				\
321 									\
322 	return ret;							\
323 }									\
324 NOKPROBE_SYMBOL(func);							\
325 									\
326 static __always_inline long ____##func(struct pt_regs *regs)
327 
328 /**
329  * DECLARE_INTERRUPT_HANDLER_ASYNC - Declare asynchronous interrupt handler function
330  * @func:	Function name of the entry point
331  */
332 #define DECLARE_INTERRUPT_HANDLER_ASYNC(func)				\
333 	__visible void func(struct pt_regs *regs)
334 
335 /**
336  * DEFINE_INTERRUPT_HANDLER_ASYNC - Define asynchronous interrupt handler function
337  * @func:	Function name of the entry point
338  *
339  * @func is called from ASM entry code.
340  *
341  * The macro is written so it acts as function definition. Append the
342  * body with a pair of curly brackets.
343  */
344 #define DEFINE_INTERRUPT_HANDLER_ASYNC(func)				\
345 static __always_inline void ____##func(struct pt_regs *regs);		\
346 									\
347 interrupt_handler void func(struct pt_regs *regs)			\
348 {									\
349 	struct interrupt_state state;					\
350 									\
351 	interrupt_async_enter_prepare(regs, &state);			\
352 									\
353 	____##func (regs);						\
354 									\
355 	interrupt_async_exit_prepare(regs, &state);			\
356 }									\
357 NOKPROBE_SYMBOL(func);							\
358 									\
359 static __always_inline void ____##func(struct pt_regs *regs)
360 
361 /**
362  * DECLARE_INTERRUPT_HANDLER_NMI - Declare NMI interrupt handler function
363  * @func:	Function name of the entry point
364  * @returns:	Returns a value back to asm caller
365  */
366 #define DECLARE_INTERRUPT_HANDLER_NMI(func)				\
367 	__visible long func(struct pt_regs *regs)
368 
369 /**
370  * DEFINE_INTERRUPT_HANDLER_NMI - Define NMI interrupt handler function
371  * @func:	Function name of the entry point
372  * @returns:	Returns a value back to asm caller
373  *
374  * @func is called from ASM entry code.
375  *
376  * The macro is written so it acts as function definition. Append the
377  * body with a pair of curly brackets.
378  */
379 #define DEFINE_INTERRUPT_HANDLER_NMI(func)				\
380 static __always_inline long ____##func(struct pt_regs *regs);		\
381 									\
382 interrupt_handler long func(struct pt_regs *regs)			\
383 {									\
384 	struct interrupt_nmi_state state;				\
385 	long ret;							\
386 									\
387 	interrupt_nmi_enter_prepare(regs, &state);			\
388 									\
389 	ret = ____##func (regs);					\
390 									\
391 	interrupt_nmi_exit_prepare(regs, &state);			\
392 									\
393 	return ret;							\
394 }									\
395 NOKPROBE_SYMBOL(func);							\
396 									\
397 static __always_inline long ____##func(struct pt_regs *regs)
398 
399 
400 /* Interrupt handlers */
401 /* kernel/traps.c */
402 DECLARE_INTERRUPT_HANDLER_NMI(system_reset_exception);
403 #ifdef CONFIG_PPC_BOOK3S_64
404 DECLARE_INTERRUPT_HANDLER_ASYNC(machine_check_exception);
405 #else
406 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_exception);
407 #endif
408 DECLARE_INTERRUPT_HANDLER(SMIException);
409 DECLARE_INTERRUPT_HANDLER(handle_hmi_exception);
410 DECLARE_INTERRUPT_HANDLER(unknown_exception);
411 DECLARE_INTERRUPT_HANDLER_ASYNC(unknown_async_exception);
412 DECLARE_INTERRUPT_HANDLER_NMI(unknown_nmi_exception);
413 DECLARE_INTERRUPT_HANDLER(instruction_breakpoint_exception);
414 DECLARE_INTERRUPT_HANDLER(RunModeException);
415 DECLARE_INTERRUPT_HANDLER(single_step_exception);
416 DECLARE_INTERRUPT_HANDLER(program_check_exception);
417 DECLARE_INTERRUPT_HANDLER(emulation_assist_interrupt);
418 DECLARE_INTERRUPT_HANDLER(alignment_exception);
419 DECLARE_INTERRUPT_HANDLER(StackOverflow);
420 DECLARE_INTERRUPT_HANDLER(stack_overflow_exception);
421 DECLARE_INTERRUPT_HANDLER(kernel_fp_unavailable_exception);
422 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_exception);
423 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_exception);
424 DECLARE_INTERRUPT_HANDLER(facility_unavailable_exception);
425 DECLARE_INTERRUPT_HANDLER(fp_unavailable_tm);
426 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_tm);
427 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_tm);
428 DECLARE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi);
429 DECLARE_INTERRUPT_HANDLER_ASYNC(performance_monitor_exception_async);
430 DECLARE_INTERRUPT_HANDLER_RAW(performance_monitor_exception);
431 DECLARE_INTERRUPT_HANDLER(DebugException);
432 DECLARE_INTERRUPT_HANDLER(altivec_assist_exception);
433 DECLARE_INTERRUPT_HANDLER(CacheLockingException);
434 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointException);
435 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointRoundException);
436 DECLARE_INTERRUPT_HANDLER_NMI(WatchdogException);
437 DECLARE_INTERRUPT_HANDLER(kernel_bad_stack);
438 
439 /* slb.c */
440 DECLARE_INTERRUPT_HANDLER_RAW(do_slb_fault);
441 DECLARE_INTERRUPT_HANDLER(do_bad_slb_fault);
442 
443 /* hash_utils.c */
444 DECLARE_INTERRUPT_HANDLER_RAW(do_hash_fault);
445 
446 /* fault.c */
447 DECLARE_INTERRUPT_HANDLER(do_page_fault);
448 DECLARE_INTERRUPT_HANDLER(do_bad_page_fault_segv);
449 
450 /* process.c */
451 DECLARE_INTERRUPT_HANDLER(do_break);
452 
453 /* time.c */
454 DECLARE_INTERRUPT_HANDLER_ASYNC(timer_interrupt);
455 
456 /* mce.c */
457 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_early);
458 DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
459 
460 DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
461 
462 void __noreturn unrecoverable_exception(struct pt_regs *regs);
463 
464 void replay_system_reset(void);
465 void replay_soft_interrupts(void);
466 
467 static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
468 {
469 	if (!arch_irq_disabled_regs(regs))
470 		local_irq_enable();
471 }
472 
473 #endif /* _ASM_POWERPC_INTERRUPT_H */
474