Skip to content

Commit f881855

Browse files
committed
Merge tag 'x86-urgent-2020-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "Two fixes for the x86 interrupt code: - Unbreak the magic 'search the timer interrupt' logic in IO/APIC code which got wreckaged when the core interrupt code made the state tracking logic stricter. That caused the interrupt line to stay masked after switching from IO/APIC to PIC delivery mode, which obviously prevents interrupts from being delivered. - Make run_on_irqstack_code() typesafe. The function argument is a void pointer which is then cast to 'void (*fun)(void *). This breaks Control Flow Integrity checking in clang. Use proper helper functions for the three variants reuqired" * tag 'x86-urgent-2020-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/ioapic: Unbreak check_timer() x86/irq: Make run_on_irqstack_cond() typesafe
2 parents ba25f05 + 86a82ae commit f881855

File tree

7 files changed

+68
-12
lines changed

7 files changed

+68
-12
lines changed

arch/x86/entry/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ __visible noinstr void xen_pv_evtchn_do_upcall(struct pt_regs *regs)
299299
old_regs = set_irq_regs(regs);
300300

301301
instrumentation_begin();
302-
run_on_irqstack_cond(__xen_pv_evtchn_do_upcall, NULL, regs);
302+
run_on_irqstack_cond(__xen_pv_evtchn_do_upcall, regs);
303303
instrumentation_begin();
304304

305305
set_irq_regs(old_regs);

arch/x86/entry/entry_64.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,8 @@ SYM_CODE_END(.Lbad_gs)
682682
* rdx: Function argument (can be NULL if none)
683683
*/
684684
SYM_FUNC_START(asm_call_on_stack)
685+
SYM_INNER_LABEL(asm_call_sysvec_on_stack, SYM_L_GLOBAL)
686+
SYM_INNER_LABEL(asm_call_irq_on_stack, SYM_L_GLOBAL)
685687
/*
686688
* Save the frame pointer unconditionally. This allows the ORC
687689
* unwinder to handle the stack switch.

arch/x86/include/asm/idtentry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ __visible noinstr void func(struct pt_regs *regs) \
242242
instrumentation_begin(); \
243243
irq_enter_rcu(); \
244244
kvm_set_cpu_l1tf_flush_l1d(); \
245-
run_on_irqstack_cond(__##func, regs, regs); \
245+
run_sysvec_on_irqstack_cond(__##func, regs); \
246246
irq_exit_rcu(); \
247247
instrumentation_end(); \
248248
irqentry_exit(regs, state); \

arch/x86/include/asm/irq_stack.h

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,50 @@ static __always_inline bool irqstack_active(void)
1212
return __this_cpu_read(irq_count) != -1;
1313
}
1414

15-
void asm_call_on_stack(void *sp, void *func, void *arg);
15+
void asm_call_on_stack(void *sp, void (*func)(void), void *arg);
16+
void asm_call_sysvec_on_stack(void *sp, void (*func)(struct pt_regs *regs),
17+
struct pt_regs *regs);
18+
void asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
19+
struct irq_desc *desc);
1620

17-
static __always_inline void __run_on_irqstack(void *func, void *arg)
21+
static __always_inline void __run_on_irqstack(void (*func)(void))
1822
{
1923
void *tos = __this_cpu_read(hardirq_stack_ptr);
2024

2125
__this_cpu_add(irq_count, 1);
22-
asm_call_on_stack(tos - 8, func, arg);
26+
asm_call_on_stack(tos - 8, func, NULL);
27+
__this_cpu_sub(irq_count, 1);
28+
}
29+
30+
static __always_inline void
31+
__run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
32+
struct pt_regs *regs)
33+
{
34+
void *tos = __this_cpu_read(hardirq_stack_ptr);
35+
36+
__this_cpu_add(irq_count, 1);
37+
asm_call_sysvec_on_stack(tos - 8, func, regs);
38+
__this_cpu_sub(irq_count, 1);
39+
}
40+
41+
static __always_inline void
42+
__run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
43+
struct irq_desc *desc)
44+
{
45+
void *tos = __this_cpu_read(hardirq_stack_ptr);
46+
47+
__this_cpu_add(irq_count, 1);
48+
asm_call_irq_on_stack(tos - 8, func, desc);
2349
__this_cpu_sub(irq_count, 1);
2450
}
2551

2652
#else /* CONFIG_X86_64 */
2753
static inline bool irqstack_active(void) { return false; }
28-
static inline void __run_on_irqstack(void *func, void *arg) { }
54+
static inline void __run_on_irqstack(void (*func)(void)) { }
55+
static inline void __run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
56+
struct pt_regs *regs) { }
57+
static inline void __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
58+
struct irq_desc *desc) { }
2959
#endif /* !CONFIG_X86_64 */
3060

3161
static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
@@ -37,17 +67,40 @@ static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
3767
return !user_mode(regs) && !irqstack_active();
3868
}
3969

40-
static __always_inline void run_on_irqstack_cond(void *func, void *arg,
70+
71+
static __always_inline void run_on_irqstack_cond(void (*func)(void),
4172
struct pt_regs *regs)
4273
{
43-
void (*__func)(void *arg) = func;
74+
lockdep_assert_irqs_disabled();
75+
76+
if (irq_needs_irq_stack(regs))
77+
__run_on_irqstack(func);
78+
else
79+
func();
80+
}
81+
82+
static __always_inline void
83+
run_sysvec_on_irqstack_cond(void (*func)(struct pt_regs *regs),
84+
struct pt_regs *regs)
85+
{
86+
lockdep_assert_irqs_disabled();
4487

88+
if (irq_needs_irq_stack(regs))
89+
__run_sysvec_on_irqstack(func, regs);
90+
else
91+
func(regs);
92+
}
93+
94+
static __always_inline void
95+
run_irq_on_irqstack_cond(void (*func)(struct irq_desc *desc), struct irq_desc *desc,
96+
struct pt_regs *regs)
97+
{
4598
lockdep_assert_irqs_disabled();
4699

47100
if (irq_needs_irq_stack(regs))
48-
__run_on_irqstack(__func, arg);
101+
__run_irq_on_irqstack(func, desc);
49102
else
50-
__func(arg);
103+
func(desc);
51104
}
52105

53106
#endif

arch/x86/kernel/apic/io_apic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,6 +2243,7 @@ static inline void __init check_timer(void)
22432243
legacy_pic->init(0);
22442244
legacy_pic->make_irq(0);
22452245
apic_write(APIC_LVT0, APIC_DM_EXTINT);
2246+
legacy_pic->unmask(0);
22462247

22472248
unlock_ExtINT_logic();
22482249

arch/x86/kernel/irq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ static __always_inline void handle_irq(struct irq_desc *desc,
227227
struct pt_regs *regs)
228228
{
229229
if (IS_ENABLED(CONFIG_X86_64))
230-
run_on_irqstack_cond(desc->handle_irq, desc, regs);
230+
run_irq_on_irqstack_cond(desc->handle_irq, desc, regs);
231231
else
232232
__handle_irq(desc, regs);
233233
}

arch/x86/kernel/irq_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,5 @@ int irq_init_percpu_irqstack(unsigned int cpu)
7474

7575
void do_softirq_own_stack(void)
7676
{
77-
run_on_irqstack_cond(__do_softirq, NULL, NULL);
77+
run_on_irqstack_cond(__do_softirq, NULL);
7878
}

0 commit comments

Comments
 (0)