1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef _ASM_POWERPC_INTERRUPT_H
3 #define _ASM_POWERPC_INTERRUPT_H
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>
12 static inline void nap_adjust_return(struct pt_regs *regs)
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;
23 struct interrupt_state {
24 #ifdef CONFIG_PPC_BOOK3E_64
25 enum ctx_state ctx_state;
29 static inline void booke_restore_dbcr0(void)
31 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
32 unsigned long dbcr0 = current->thread.debug.dbcr0;
34 if (IS_ENABLED(CONFIG_PPC32) && unlikely(dbcr0 & DBCR0_IDM)) {
36 mtspr(SPRN_DBCR0, global_dbcr0[smp_processor_id()]);
41 static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
44 if (!arch_irq_disabled_regs(regs))
47 if (user_mode(regs)) {
49 account_cpu_user_entry();
51 kuap_save_and_lock(regs);
55 * Book3E reconciles irq soft mask in asm
57 #ifdef CONFIG_PPC_BOOK3S_64
58 if (irq_soft_mask_set_return(IRQS_ALL_DISABLED) == IRQS_ENABLED)
60 local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
62 if (user_mode(regs)) {
63 CT_WARN_ON(ct_state() != CONTEXT_USER);
66 account_cpu_user_entry();
67 account_stolen_time();
70 * CT_WARN_ON comes here via program_check_exception,
73 if (TRAP(regs) != 0x700)
74 CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
78 #ifdef CONFIG_PPC_BOOK3E_64
79 state->ctx_state = exception_enter();
81 account_cpu_user_entry();
84 booke_restore_dbcr0();
88 * Care should be taken to note that interrupt_exit_prepare and
89 * interrupt_async_exit_prepare do not necessarily return immediately to
90 * regs context (e.g., if regs is usermode, we don't necessarily return to
91 * user mode). Other interrupts might be taken between here and return,
92 * context switch / preemption may occur in the exit path after this, or a
93 * signal may be delivered, etc.
95 * The real interrupt exit code is platform specific, e.g.,
96 * interrupt_exit_user_prepare / interrupt_exit_kernel_prepare for 64s.
98 * However interrupt_nmi_exit_prepare does return directly to regs, because
99 * NMIs do not do "exit work" or replay soft-masked interrupts.
101 static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
103 #ifdef CONFIG_PPC_BOOK3E_64
104 exception_exit(state->ctx_state);
110 * Book3S exits to user via interrupt_exit_user_prepare(), which does
111 * context tracking, which is a cleaner way to handle PREEMPT=y
112 * and avoid context entry/exit in e.g., preempt_schedule_irq()),
113 * which is likely to be where the core code wants to end up.
115 * The above comment explains why we can't do the
117 * if (user_mode(regs))
118 * user_exit_irqoff();
124 static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
126 #ifdef CONFIG_PPC_BOOK3S_64
127 if (cpu_has_feature(CPU_FTR_CTRL) &&
128 !test_thread_local_flags(_TLF_RUNLATCH))
129 __ppc64_runlatch_on();
132 interrupt_enter_prepare(regs, state);
136 static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
139 * Adjust at exit so the main handler sees the true NIA. This must
140 * come before irq_exit() because irq_exit can enable interrupts, and
141 * if another interrupt is taken before nap_adjust_return has run
142 * here, then that interrupt would return directly to idle nap return.
144 nap_adjust_return(regs);
147 interrupt_exit_prepare(regs, state);
150 struct interrupt_nmi_state {
152 #ifdef CONFIG_PPC_BOOK3S_64
160 static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
163 #ifdef CONFIG_PPC_BOOK3S_64
164 state->irq_soft_mask = local_paca->irq_soft_mask;
165 state->irq_happened = local_paca->irq_happened;
168 * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
169 * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
170 * because that goes through irq tracing which we don't want in NMI.
172 local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
173 local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
175 /* Don't do any per-CPU operations until interrupt state is fixed */
177 /* Allow DEC and PMI to be traced when they are soft-NMI */
178 if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260) {
179 state->ftrace_enabled = this_cpu_get_ftrace_enabled();
180 this_cpu_set_ftrace_enabled(0);
185 * Do not use nmi_enter() for pseries hash guest taking a real-mode
186 * NMI because not everything it touches is within the RMA limit.
188 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
189 !firmware_has_feature(FW_FEATURE_LPAR) ||
190 radix_enabled() || (mfmsr() & MSR_DR))
194 static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
196 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
197 !firmware_has_feature(FW_FEATURE_LPAR) ||
198 radix_enabled() || (mfmsr() & MSR_DR))
202 * nmi does not call nap_adjust_return because nmi should not create
203 * new work to do (must use irq_work for that).
207 if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260)
208 this_cpu_set_ftrace_enabled(state->ftrace_enabled);
210 #ifdef CONFIG_PPC_BOOK3S_64
211 /* Check we didn't change the pending interrupt mask. */
212 WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
213 local_paca->irq_happened = state->irq_happened;
214 local_paca->irq_soft_mask = state->irq_soft_mask;
220 * Don't use noinstr here like x86, but rather add NOKPROBE_SYMBOL to each
221 * function definition. The reason for this is the noinstr section is placed
222 * after the main text section, i.e., very far away from the interrupt entry
223 * asm. That creates problems with fitting linker stubs when building large
226 #define interrupt_handler __visible noinline notrace __no_kcsan __no_sanitize_address
229 * DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function
230 * @func: Function name of the entry point
231 * @returns: Returns a value back to asm caller
233 #define DECLARE_INTERRUPT_HANDLER_RAW(func) \
234 __visible long func(struct pt_regs *regs)
237 * DEFINE_INTERRUPT_HANDLER_RAW - Define raw interrupt handler function
238 * @func: Function name of the entry point
239 * @returns: Returns a value back to asm caller
241 * @func is called from ASM entry code.
243 * This is a plain function which does no tracing, reconciling, etc.
244 * The macro is written so it acts as function definition. Append the
245 * body with a pair of curly brackets.
247 * raw interrupt handlers must not enable or disable interrupts, or
248 * schedule, tracing and instrumentation (ftrace, lockdep, etc) would
249 * not be advisable either, although may be possible in a pinch, the
250 * trace will look odd at least.
252 * A raw handler may call one of the other interrupt handler functions
253 * to be converted into that interrupt context without these restrictions.
255 * On PPC64, _RAW handlers may return with fast_interrupt_return.
257 * Specific handlers may have additional restrictions.
259 #define DEFINE_INTERRUPT_HANDLER_RAW(func) \
260 static __always_inline long ____##func(struct pt_regs *regs); \
262 interrupt_handler long func(struct pt_regs *regs) \
266 ret = ____##func (regs); \
270 NOKPROBE_SYMBOL(func); \
272 static __always_inline long ____##func(struct pt_regs *regs)
275 * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function
276 * @func: Function name of the entry point
278 #define DECLARE_INTERRUPT_HANDLER(func) \
279 __visible void func(struct pt_regs *regs)
282 * DEFINE_INTERRUPT_HANDLER - Define synchronous interrupt handler function
283 * @func: Function name of the entry point
285 * @func is called from ASM entry code.
287 * The macro is written so it acts as function definition. Append the
288 * body with a pair of curly brackets.
290 #define DEFINE_INTERRUPT_HANDLER(func) \
291 static __always_inline void ____##func(struct pt_regs *regs); \
293 interrupt_handler void func(struct pt_regs *regs) \
295 struct interrupt_state state; \
297 interrupt_enter_prepare(regs, &state); \
301 interrupt_exit_prepare(regs, &state); \
303 NOKPROBE_SYMBOL(func); \
305 static __always_inline void ____##func(struct pt_regs *regs)
308 * DECLARE_INTERRUPT_HANDLER_RET - Declare synchronous interrupt handler function
309 * @func: Function name of the entry point
310 * @returns: Returns a value back to asm caller
312 #define DECLARE_INTERRUPT_HANDLER_RET(func) \
313 __visible long func(struct pt_regs *regs)
316 * DEFINE_INTERRUPT_HANDLER_RET - Define synchronous interrupt handler function
317 * @func: Function name of the entry point
318 * @returns: Returns a value back to asm caller
320 * @func is called from ASM entry code.
322 * The macro is written so it acts as function definition. Append the
323 * body with a pair of curly brackets.
325 #define DEFINE_INTERRUPT_HANDLER_RET(func) \
326 static __always_inline long ____##func(struct pt_regs *regs); \
328 interrupt_handler long func(struct pt_regs *regs) \
330 struct interrupt_state state; \
333 interrupt_enter_prepare(regs, &state); \
335 ret = ____##func (regs); \
337 interrupt_exit_prepare(regs, &state); \
341 NOKPROBE_SYMBOL(func); \
343 static __always_inline long ____##func(struct pt_regs *regs)
346 * DECLARE_INTERRUPT_HANDLER_ASYNC - Declare asynchronous interrupt handler function
347 * @func: Function name of the entry point
349 #define DECLARE_INTERRUPT_HANDLER_ASYNC(func) \
350 __visible void func(struct pt_regs *regs)
353 * DEFINE_INTERRUPT_HANDLER_ASYNC - Define asynchronous interrupt handler function
354 * @func: Function name of the entry point
356 * @func is called from ASM entry code.
358 * The macro is written so it acts as function definition. Append the
359 * body with a pair of curly brackets.
361 #define DEFINE_INTERRUPT_HANDLER_ASYNC(func) \
362 static __always_inline void ____##func(struct pt_regs *regs); \
364 interrupt_handler void func(struct pt_regs *regs) \
366 struct interrupt_state state; \
368 interrupt_async_enter_prepare(regs, &state); \
372 interrupt_async_exit_prepare(regs, &state); \
374 NOKPROBE_SYMBOL(func); \
376 static __always_inline void ____##func(struct pt_regs *regs)
379 * DECLARE_INTERRUPT_HANDLER_NMI - Declare NMI interrupt handler function
380 * @func: Function name of the entry point
381 * @returns: Returns a value back to asm caller
383 #define DECLARE_INTERRUPT_HANDLER_NMI(func) \
384 __visible long func(struct pt_regs *regs)
387 * DEFINE_INTERRUPT_HANDLER_NMI - Define NMI interrupt handler function
388 * @func: Function name of the entry point
389 * @returns: Returns a value back to asm caller
391 * @func is called from ASM entry code.
393 * The macro is written so it acts as function definition. Append the
394 * body with a pair of curly brackets.
396 #define DEFINE_INTERRUPT_HANDLER_NMI(func) \
397 static __always_inline long ____##func(struct pt_regs *regs); \
399 interrupt_handler long func(struct pt_regs *regs) \
401 struct interrupt_nmi_state state; \
404 interrupt_nmi_enter_prepare(regs, &state); \
406 ret = ____##func (regs); \
408 interrupt_nmi_exit_prepare(regs, &state); \
412 NOKPROBE_SYMBOL(func); \
414 static __always_inline long ____##func(struct pt_regs *regs)
417 /* Interrupt handlers */
419 DECLARE_INTERRUPT_HANDLER_NMI(system_reset_exception);
420 #ifdef CONFIG_PPC_BOOK3S_64
421 DECLARE_INTERRUPT_HANDLER_ASYNC(machine_check_exception);
423 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_exception);
425 DECLARE_INTERRUPT_HANDLER(SMIException);
426 DECLARE_INTERRUPT_HANDLER(handle_hmi_exception);
427 DECLARE_INTERRUPT_HANDLER(unknown_exception);
428 DECLARE_INTERRUPT_HANDLER_ASYNC(unknown_async_exception);
429 DECLARE_INTERRUPT_HANDLER(instruction_breakpoint_exception);
430 DECLARE_INTERRUPT_HANDLER(RunModeException);
431 DECLARE_INTERRUPT_HANDLER(single_step_exception);
432 DECLARE_INTERRUPT_HANDLER(program_check_exception);
433 DECLARE_INTERRUPT_HANDLER(emulation_assist_interrupt);
434 DECLARE_INTERRUPT_HANDLER(alignment_exception);
435 DECLARE_INTERRUPT_HANDLER(StackOverflow);
436 DECLARE_INTERRUPT_HANDLER(stack_overflow_exception);
437 DECLARE_INTERRUPT_HANDLER(kernel_fp_unavailable_exception);
438 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_exception);
439 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_exception);
440 DECLARE_INTERRUPT_HANDLER(facility_unavailable_exception);
441 DECLARE_INTERRUPT_HANDLER(fp_unavailable_tm);
442 DECLARE_INTERRUPT_HANDLER(altivec_unavailable_tm);
443 DECLARE_INTERRUPT_HANDLER(vsx_unavailable_tm);
444 DECLARE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi);
445 DECLARE_INTERRUPT_HANDLER_ASYNC(performance_monitor_exception_async);
446 DECLARE_INTERRUPT_HANDLER_RAW(performance_monitor_exception);
447 DECLARE_INTERRUPT_HANDLER(DebugException);
448 DECLARE_INTERRUPT_HANDLER(altivec_assist_exception);
449 DECLARE_INTERRUPT_HANDLER(CacheLockingException);
450 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointException);
451 DECLARE_INTERRUPT_HANDLER(SPEFloatingPointRoundException);
452 DECLARE_INTERRUPT_HANDLER(WatchdogException);
453 DECLARE_INTERRUPT_HANDLER(kernel_bad_stack);
456 DECLARE_INTERRUPT_HANDLER_RAW(do_slb_fault);
457 DECLARE_INTERRUPT_HANDLER(do_bad_slb_fault);
460 DECLARE_INTERRUPT_HANDLER_RAW(do_hash_fault);
463 DECLARE_INTERRUPT_HANDLER_RET(do_page_fault);
464 DECLARE_INTERRUPT_HANDLER(do_bad_page_fault_segv);
467 DECLARE_INTERRUPT_HANDLER(do_break);
470 DECLARE_INTERRUPT_HANDLER_ASYNC(timer_interrupt);
473 DECLARE_INTERRUPT_HANDLER_NMI(machine_check_early);
474 DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
476 DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
478 void __noreturn unrecoverable_exception(struct pt_regs *regs);
480 void replay_system_reset(void);
481 void replay_soft_interrupts(void);
483 static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
485 if (!arch_irq_disabled_regs(regs))
489 #endif /* _ASM_POWERPC_INTERRUPT_H */