linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 00/12] x86/irq/64: Inline irq stack switching
@ 2021-02-04 20:49 Thomas Gleixner
  2021-02-04 20:49 ` [patch 01/12] x86/entry: Fix instrumentation annotation Thomas Gleixner
                   ` (12 more replies)
  0 siblings, 13 replies; 34+ messages in thread
From: Thomas Gleixner @ 2021-02-04 20:49 UTC (permalink / raw)
  To: LKML; +Cc: x86, Josh Poimboeuf, Kees Cook

The recent effort to make the ASM entry code slim and unified moved
the irq stack switching out of the low level ASM code so that the
whole return from interrupt work and state handling can be done in C
and the ASM code just handles the true low level details of entry and
exit (which is horrible enough already due to the well thought out
architeture).

The main goal at this point was to get instrumentation and RCU state
under control in a validated way. Inlining the switch mechanism was
attempted back then, but that caused more objtool and unwinder trouble
than we had already on our plate, so we ended up with a simple,
functional but suboptimal implementation. The main issues are:

  - The unnecessary indirect call which is expensive thanks to
    retpoline
    
  - The inability to stay on the irq stack for softirq processing on return
    from interrupt which requires another stack switch operation.
    
  - The fact that the stack switching code ended up being an easy to find
    exploit gadget.

This series revisits the problem and reimplements the stack switch
mechanics via evil inline assembly. Peter Zijlstra provided the required
objtool and unwinder changes already. These are available here:

  https://lore.kernel.org/r/20210203120222.451068583@infradead.org

The full series (including Peter's series) is also available from git:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git x86/entry

All function calls are now direct and fully inlined including the single
instance in the softirq code which is invoked from local_bh_enable() in
task context.

The extra 100 lines in the diffstat are pretty much the extensive commentry
for the whole magic to spare everyone including myself to scratch heads 2
weeks down the road. 

The text size impact is in the noise and looking at the actual entry
functions there is depending on the compiler variant even a small size
decrease.

The patches have been tested with gcc8, gcc10 and clang-13 (fresh from
git). The difference between the output of these compilers is minimal.
gcc8 being slightly worse due to stupid register selection and random
NOPs injected.

Thanks,

	tglx
---
 arch/x86/Kconfig                 |    1 
 arch/x86/entry/common.c          |   19 --
 arch/x86/entry/entry_64.S        |   41 -----
 arch/x86/include/asm/idtentry.h  |   11 -
 arch/x86/include/asm/irq.h       |    3 
 arch/x86/include/asm/irq_stack.h |  283 +++++++++++++++++++++++++++------------
 arch/x86/include/asm/processor.h |    9 -
 arch/x86/kernel/apic/apic.c      |   31 ++--
 arch/x86/kernel/cpu/common.c     |    4 
 arch/x86/kernel/dumpstack_64.c   |   22 ++-
 arch/x86/kernel/irq.c            |    2 
 arch/x86/kernel/irq_64.c         |   11 -
 arch/x86/kernel/process_64.c     |    2 
 include/linux/interrupt.h        |    2 
 kernel/softirq.c                 |    4 
 15 files changed, 270 insertions(+), 175 deletions(-)


^ permalink raw reply	[flat|nested] 34+ messages in thread
* Re: [patch 05/12] x86/irq: Provide macro for inlining irq stack switching
@ 2021-02-05 11:03 Uros Bizjak
  2021-02-05 13:24 ` Thomas Gleixner
  0 siblings, 1 reply; 34+ messages in thread
From: Uros Bizjak @ 2021-02-05 11:03 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: LKML, X86 ML, Josh Poimboeuf, Kees Cook

> The effort to make the ASM entry code slim and unified moved the irq stack
> switching out of the low level ASM code so that the whole return from
> interrupt work and state handling can be done in C and the ASM code just
> handles the low level details of entry and exit.
>
> This ended up being a suboptimal implementation for various reasons
> (including tooling). The main pain points are:
>
>  - The indirect call which is expensive thanks to retpoline
>
>  - The inability to stay on the irq stack for softirq processing on return
>    from interrupt
>
>  - The fact that the stack switching code ends up being an easy to target
>    exploit gadget.
>
> Prepare for inlining the stack switching logic into the C entry points by
> providing a ASM macro which contains the guts of the switching mechanism:
>
>   1) Store RSP at the top of the irq stack
>   2) Switch RSP to the irq stack
>   3) Invoke code
>   4) Pop the original RSP back
>
> Document the unholy asm() logic while at it to reduce the amount of head
> scratching required a half year from now.

#define __call_on_irqstack(func, asm_call, constr...) \
+{ \
+ register void *tos asm("r11"); \
+ \
+ tos = ((void *)__this_cpu_read(hardirq_stack_ptr)); \
+ \
+ asm_inline volatile( \
+ "movq %%rsp, (%[__tos]) \n" \
+ "movq %[__tos], %%rsp \n" \
+ \
+ asm_call \
+ \
+ "popq %%rsp \n" \
+ \
+ : "+r" (tos) IRQSTACK_CALL_CONSTRAINT \

Please note that GCC documents "U" register constraint that can be
used here instead of declaring hard register in the variable
declaration:

    'U'
         The call-clobbered integer registers.

+ : [__func] "i" (func), [__tos] "r" (tos) constr \

There is no need to declare "tos" as read operand again, it is already
declared above as readwrite (+) operand.

Considering that (according to the above documentation) it is
necessary to list all input registers that pass function arguments,
the compiler is free to allocate any remaining register from "U"
register class, not only r11. Using an earlyclobber modifier prevents
the compiler from allocating a register that carries input argument,
so:

: [__tos] "+&U" (tos) IRQSTACK_CALL_CONSTRAINT \
: [__func] "i" (func) constr \

could be used.

Also note that functions with variable arguments pass information
about the number of vector registers used in %rax, so %rax should be
listed as input argument in this case. But this should be of no issue
here.

Uros.

+ : "cc", "rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", \
+  "memory" \
+ ); \

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2021-02-10  0:14 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-04 20:49 [patch 00/12] x86/irq/64: Inline irq stack switching Thomas Gleixner
2021-02-04 20:49 ` [patch 01/12] x86/entry: Fix instrumentation annotation Thomas Gleixner
2021-02-05 12:02   ` Borislav Petkov
2021-02-04 20:49 ` [patch 02/12] x86/irq: Sanitize irq stack tracking Thomas Gleixner
2021-02-04 20:49 ` [patch 03/12] x86/irq/64: Adjust the per CPU irq stack pointer by 8 Thomas Gleixner
2021-02-05 13:53   ` Peter Zijlstra
2021-02-05 15:00     ` Thomas Gleixner
2021-02-04 20:49 ` [patch 04/12] x86/apic: Split out spurious handling code Thomas Gleixner
2021-02-04 20:49 ` [patch 05/12] x86/irq: Provide macro for inlining irq stack switching Thomas Gleixner
2021-02-08 15:06   ` Borislav Petkov
2021-02-08 20:42   ` Josh Poimboeuf
2021-02-09 15:12     ` Thomas Gleixner
2021-02-09 16:22       ` Josh Poimboeuf
2021-02-09 18:14         ` Thomas Gleixner
2021-02-04 20:49 ` [patch 06/12] x86/entry: Convert system vectors to irq stack macro Thomas Gleixner
2021-02-05  3:52   ` kernel test robot
2021-02-05 14:13     ` Peter Zijlstra
2021-02-07  8:15       ` [kbuild-all] " Rong Chen
2021-02-08 14:19         ` Borislav Petkov
2021-02-09  8:57           ` Rong Chen
2021-02-09 10:46             ` Borislav Petkov
2021-02-04 20:49 ` [patch 07/12] x86/entry: Convert device interrupts to inline stack switching Thomas Gleixner
2021-02-04 20:49 ` [patch 08/12] x86/entry: Use run_sysvec_on_irqstack_cond() for XEN upcall Thomas Gleixner
2021-02-05  7:28   ` kernel test robot
2021-02-04 20:49 ` [patch 09/12] x86/softirq: Remove indirection in do_softirq_own_stack() Thomas Gleixner
2021-02-04 20:49 ` [patch 10/12] x86: Select CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK Thomas Gleixner
2021-02-04 20:49 ` [patch 11/12] softirq: Allow inlining do_softirq_own_stack() Thomas Gleixner
2021-02-05 10:14   ` Lai Jiangshan
2021-02-05 11:38     ` Thomas Gleixner
2021-02-09 20:43       ` Thomas Gleixner
2021-02-04 20:49 ` [patch 12/12] x86/softirq/64: Inline do_softirq_own_stack() Thomas Gleixner
2021-02-08 21:47 ` [patch 00/12] x86/irq/64: Inline irq stack switching Kees Cook
2021-02-05 11:03 [patch 05/12] x86/irq: Provide macro for inlining " Uros Bizjak
2021-02-05 13:24 ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).