Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/irq: Move irq stacks to percpu hot section

No functional change.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Uros Bizjak <ubizjak@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250303165246.2175811-8-brgerst@gmail.com

authored by

Brian Gerst and committed by
Ingo Molnar
c6a09180 c8f1ac2b

+30 -24
-6
arch/x86/include/asm/current.h
··· 15 15 struct pcpu_hot { 16 16 struct task_struct *current_task; 17 17 unsigned long top_of_stack; 18 - void *hardirq_stack_ptr; 19 - #ifdef CONFIG_X86_64 20 - bool hardirq_stack_inuse; 21 - #else 22 - void *softirq_stack_ptr; 23 - #endif 24 18 }; 25 19 26 20 DECLARE_PER_CPU_CACHE_HOT(struct pcpu_hot, pcpu_hot);
+6 -6
arch/x86/include/asm/irq_stack.h
··· 116 116 ASM_CALL_ARG2 117 117 118 118 #define call_on_irqstack(func, asm_call, argconstr...) \ 119 - call_on_stack(__this_cpu_read(pcpu_hot.hardirq_stack_ptr), \ 119 + call_on_stack(__this_cpu_read(hardirq_stack_ptr), \ 120 120 func, asm_call, argconstr) 121 121 122 122 /* Macros to assert type correctness for run_*_on_irqstack macros */ ··· 135 135 * User mode entry and interrupt on the irq stack do not \ 136 136 * switch stacks. If from user mode the task stack is empty. \ 137 137 */ \ 138 - if (user_mode(regs) || __this_cpu_read(pcpu_hot.hardirq_stack_inuse)) { \ 138 + if (user_mode(regs) || __this_cpu_read(hardirq_stack_inuse)) { \ 139 139 irq_enter_rcu(); \ 140 140 func(c_args); \ 141 141 irq_exit_rcu(); \ ··· 146 146 * places. Invoke the stack switch macro with the call \ 147 147 * sequence which matches the above direct invocation. \ 148 148 */ \ 149 - __this_cpu_write(pcpu_hot.hardirq_stack_inuse, true); \ 149 + __this_cpu_write(hardirq_stack_inuse, true); \ 150 150 call_on_irqstack(func, asm_call, constr); \ 151 - __this_cpu_write(pcpu_hot.hardirq_stack_inuse, false); \ 151 + __this_cpu_write(hardirq_stack_inuse, false); \ 152 152 } \ 153 153 } 154 154 ··· 212 212 */ 213 213 #define do_softirq_own_stack() \ 214 214 { \ 215 - __this_cpu_write(pcpu_hot.hardirq_stack_inuse, true); \ 215 + __this_cpu_write(hardirq_stack_inuse, true); \ 216 216 call_on_irqstack(__do_softirq, ASM_CALL_ARG0); \ 217 - __this_cpu_write(pcpu_hot.hardirq_stack_inuse, false); \ 217 + __this_cpu_write(hardirq_stack_inuse, false); \ 218 218 } 219 219 220 220 #endif
+7
arch/x86/include/asm/processor.h
··· 415 415 char stack[IRQ_STACK_SIZE]; 416 416 } __aligned(IRQ_STACK_SIZE); 417 417 418 + DECLARE_PER_CPU_CACHE_HOT(struct irq_stack *, hardirq_stack_ptr); 419 + #ifdef CONFIG_X86_64 420 + DECLARE_PER_CPU_CACHE_HOT(bool, hardirq_stack_inuse); 421 + #else 422 + DECLARE_PER_CPU_CACHE_HOT(struct irq_stack *, softirq_stack_ptr); 423 + #endif 424 + 418 425 #ifdef CONFIG_X86_64 419 426 static inline unsigned long cpu_kernelmode_gs_base(int cpu) 420 427 {
+2 -2
arch/x86/kernel/dumpstack_32.c
··· 37 37 38 38 static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info) 39 39 { 40 - unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.hardirq_stack_ptr); 40 + unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack_ptr); 41 41 unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); 42 42 43 43 /* ··· 62 62 63 63 static bool in_softirq_stack(unsigned long *stack, struct stack_info *info) 64 64 { 65 - unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.softirq_stack_ptr); 65 + unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack_ptr); 66 66 unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); 67 67 68 68 /*
+1 -1
arch/x86/kernel/dumpstack_64.c
··· 134 134 135 135 static __always_inline bool in_irq_stack(unsigned long *stack, struct stack_info *info) 136 136 { 137 - unsigned long *end = (unsigned long *)this_cpu_read(pcpu_hot.hardirq_stack_ptr); 137 + unsigned long *end = (unsigned long *)this_cpu_read(hardirq_stack_ptr); 138 138 unsigned long *begin; 139 139 140 140 /*
+2
arch/x86/kernel/irq.c
··· 36 36 DEFINE_PER_CPU_CACHE_HOT(u16, __softirq_pending); 37 37 EXPORT_PER_CPU_SYMBOL(__softirq_pending); 38 38 39 + DEFINE_PER_CPU_CACHE_HOT(struct irq_stack *, hardirq_stack_ptr); 40 + 39 41 atomic_t irq_err_count; 40 42 41 43 /*
+7 -5
arch/x86/kernel/irq_32.c
··· 49 49 static inline void print_stack_overflow(void) { } 50 50 #endif 51 51 52 + DEFINE_PER_CPU_CACHE_HOT(struct irq_stack *, softirq_stack_ptr); 53 + 52 54 static void call_on_stack(void *func, void *stack) 53 55 { 54 56 asm volatile("xchgl %[sp], %%esp\n" ··· 72 70 u32 *isp, *prev_esp; 73 71 74 72 curstk = (struct irq_stack *) current_stack(); 75 - irqstk = __this_cpu_read(pcpu_hot.hardirq_stack_ptr); 73 + irqstk = __this_cpu_read(hardirq_stack_ptr); 76 74 77 75 /* 78 76 * this is where we switch to the IRQ stack. However, if we are ··· 109 107 int node = cpu_to_node(cpu); 110 108 struct page *ph, *ps; 111 109 112 - if (per_cpu(pcpu_hot.hardirq_stack_ptr, cpu)) 110 + if (per_cpu(hardirq_stack_ptr, cpu)) 113 111 return 0; 114 112 115 113 ph = alloc_pages_node(node, THREADINFO_GFP, THREAD_SIZE_ORDER); ··· 121 119 return -ENOMEM; 122 120 } 123 121 124 - per_cpu(pcpu_hot.hardirq_stack_ptr, cpu) = page_address(ph); 125 - per_cpu(pcpu_hot.softirq_stack_ptr, cpu) = page_address(ps); 122 + per_cpu(hardirq_stack_ptr, cpu) = page_address(ph); 123 + per_cpu(softirq_stack_ptr, cpu) = page_address(ps); 126 124 return 0; 127 125 } 128 126 ··· 132 130 struct irq_stack *irqstk; 133 131 u32 *isp, *prev_esp; 134 132 135 - irqstk = __this_cpu_read(pcpu_hot.softirq_stack_ptr); 133 + irqstk = __this_cpu_read(softirq_stack_ptr); 136 134 137 135 /* build the stack frame on the softirq stack */ 138 136 isp = (u32 *) ((char *)irqstk + sizeof(*irqstk));
+4 -3
arch/x86/kernel/irq_64.c
··· 26 26 #include <asm/io_apic.h> 27 27 #include <asm/apic.h> 28 28 29 + DEFINE_PER_CPU_CACHE_HOT(bool, hardirq_stack_inuse); 29 30 DEFINE_PER_CPU_PAGE_ALIGNED(struct irq_stack, irq_stack_backing_store) __visible; 30 31 31 32 #ifdef CONFIG_VMAP_STACK ··· 51 50 return -ENOMEM; 52 51 53 52 /* Store actual TOS to avoid adjustment in the hotpath */ 54 - per_cpu(pcpu_hot.hardirq_stack_ptr, cpu) = va + IRQ_STACK_SIZE - 8; 53 + per_cpu(hardirq_stack_ptr, cpu) = va + IRQ_STACK_SIZE - 8; 55 54 return 0; 56 55 } 57 56 #else ··· 64 63 void *va = per_cpu_ptr(&irq_stack_backing_store, cpu); 65 64 66 65 /* Store actual TOS to avoid adjustment in the hotpath */ 67 - per_cpu(pcpu_hot.hardirq_stack_ptr, cpu) = va + IRQ_STACK_SIZE - 8; 66 + per_cpu(hardirq_stack_ptr, cpu) = va + IRQ_STACK_SIZE - 8; 68 67 return 0; 69 68 } 70 69 #endif 71 70 72 71 int irq_init_percpu_irqstack(unsigned int cpu) 73 72 { 74 - if (per_cpu(pcpu_hot.hardirq_stack_ptr, cpu)) 73 + if (per_cpu(hardirq_stack_ptr, cpu)) 75 74 return 0; 76 75 return map_irq_stack(cpu); 77 76 }
+1 -1
arch/x86/kernel/process_64.c
··· 614 614 int cpu = smp_processor_id(); 615 615 616 616 WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) && 617 - this_cpu_read(pcpu_hot.hardirq_stack_inuse)); 617 + this_cpu_read(hardirq_stack_inuse)); 618 618 619 619 if (!test_tsk_thread_flag(prev_p, TIF_NEED_FPU_LOAD)) 620 620 switch_fpu_prepare(prev_p, cpu);