1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_X86_IRQ_STACK_H 3 #define _ASM_X86_IRQ_STACK_H 4 5 #include <linux/ptrace.h> 6 7 #include <asm/processor.h> 8 9 #ifdef CONFIG_X86_64 10 static __always_inline bool irqstack_active(void) 11 { 12 return __this_cpu_read(irq_count) != -1; 13 } 14 15 void asm_call_on_stack(void *sp, void *func, void *arg); 16 17 static __always_inline void __run_on_irqstack(void *func, void *arg) 18 { 19 void *tos = __this_cpu_read(hardirq_stack_ptr); 20 21 __this_cpu_add(irq_count, 1); 22 asm_call_on_stack(tos - 8, func, arg); 23 __this_cpu_sub(irq_count, 1); 24 } 25 26 #else /* CONFIG_X86_64 */ 27 static inline bool irqstack_active(void) { return false; } 28 static inline void __run_on_irqstack(void *func, void *arg) { } 29 #endif /* !CONFIG_X86_64 */ 30 31 static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs) 32 { 33 if (IS_ENABLED(CONFIG_X86_32)) 34 return false; 35 if (!regs) 36 return !irqstack_active(); 37 return !user_mode(regs) && !irqstack_active(); 38 } 39 40 static __always_inline void run_on_irqstack_cond(void *func, void *arg, 41 struct pt_regs *regs) 42 { 43 void (*__func)(void *arg) = func; 44 45 lockdep_assert_irqs_disabled(); 46 47 if (irq_needs_irq_stack(regs)) 48 __run_on_irqstack(__func, arg); 49 else 50 __func(arg); 51 } 52 53 #endif 54