blob: a48b3f6ebbe87b67ffae0be3a64618d858d6fca4 [file] [log] [blame]
Changbin Duc2dea5c2019-05-08 23:21:20 +08001.. SPDX-License-Identifier: GPL-2.0
2
3==============
4Kernel Entries
5==============
6
Andy Lutomirski8b4777a2011-06-05 13:50:18 -04007This file documents some of the kernel entries in
James C Boyd864d5bb2015-07-01 15:13:26 -05008arch/x86/entry/entry_64.S. A lot of this explanation is adapted from
Andy Lutomirski8b4777a2011-06-05 13:50:18 -04009an email from Ingo Molnar:
10
11http://lkml.kernel.org/r/<20110529191055.GC9835%40elte.hu>
12
13The x86 architecture has quite a few different ways to jump into
14kernel code. Most of these entry points are registered in
James C Boyd864d5bb2015-07-01 15:13:26 -050015arch/x86/kernel/traps.c and implemented in arch/x86/entry/entry_64.S
16for 64-bit, arch/x86/entry/entry_32.S for 32-bit and finally
17arch/x86/entry/entry_64_compat.S which implements the 32-bit compatibility
Luis R. Rodriguez96ed4cd2014-12-09 14:54:44 -080018syscall entry points and thus provides for 32-bit processes the
19ability to execute syscalls when running on 64-bit kernels.
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040020
Luis R. Rodriguez96ed4cd2014-12-09 14:54:44 -080021The IDT vector assignments are listed in arch/x86/include/asm/irq_vectors.h.
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040022
23Some of these entries are:
24
25 - system_call: syscall instruction from 64-bit code.
26
Ingo Molnar2cd23552015-06-08 08:28:07 +020027 - entry_INT80_compat: int 0x80 from 32-bit or 64-bit code; compat syscall
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040028 either way.
29
Ingo Molnar2cd23552015-06-08 08:28:07 +020030 - entry_INT80_compat, ia32_sysenter: syscall and sysenter from 32-bit
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040031 code
32
33 - interrupt: An array of entries. Every IDT vector that doesn't
34 explicitly point somewhere else gets set to the corresponding
35 value in interrupts. These point to a whole array of
36 magically-generated functions that make their way to do_IRQ with
37 the interrupt number as a parameter.
38
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040039 - APIC interrupts: Various special-purpose interrupts for things
40 like TLB shootdown.
41
42 - Architecturally-defined exceptions like divide_error.
43
44There are a few complexities here. The different x86-64 entries
45have different calling conventions. The syscall and sysenter
46instructions have their own peculiar calling conventions. Some of
47the IDT entries push an error code onto the stack; others don't.
48IDT entries using the IST alternative stack mechanism need their own
49magic to get the stack frames right. (You can find some
50documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
51Volume 3, Chapter 6.)
52
53Dealing with the swapgs instruction is especially tricky. Swapgs
54toggles whether gs is the kernel gs or the user gs. The swapgs
55instruction is rather fragile: it must nest perfectly and only in
56single depth, it should only be used if entering from user mode to
57kernel mode and then when returning to user-space, and precisely
58so. If we mess that up even slightly, we crash.
59
60So when we have a secondary entry, already in kernel mode, we *must
61not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
62not switched/swapped yet.
63
64Now, there's a secondary complication: there's a cheap way to test
65which mode the CPU is in and an expensive way.
66
67The cheap way is to pick this info off the entry frame on the kernel
Changbin Duc2dea5c2019-05-08 23:21:20 +080068stack, from the CS of the ptregs area of the kernel stack::
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040069
70 xorl %ebx,%ebx
71 testl $3,CS+8(%rsp)
72 je error_kernelspace
73 SWAPGS
74
75The expensive (paranoid) way is to read back the MSR_GS_BASE value
Changbin Duc2dea5c2019-05-08 23:21:20 +080076(which is what SWAPGS modifies)::
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040077
78 movl $1,%ebx
79 movl $MSR_GS_BASE,%ecx
80 rdmsr
81 testl %edx,%edx
82 js 1f /* negative -> in kernel */
83 SWAPGS
84 xorl %ebx,%ebx
Changbin Duc2dea5c2019-05-08 23:21:20 +080085 1: ret
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040086
Andy Lutomirski8b4777a2011-06-05 13:50:18 -040087If we are at an interrupt or user-trap/gate-alike boundary then we can
88use the faster check: the stack will be a reliable indicator of
89whether SWAPGS was already done: if we see that we are a secondary
90entry interrupting kernel mode execution, then we know that the GS
91base has already been switched. If it says that we interrupted
92user-space execution then we must do the SWAPGS.
93
94But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
95which might have triggered right after a normal entry wrote CS to the
96stack but before we executed SWAPGS, then the only safe way to check
97for GS is the slower method: the RDMSR.
98
Andy Lutomirski48e08d02014-11-11 12:49:41 -080099Therefore, super-atomic entries (except NMI, which is handled separately)
100must use idtentry with paranoid=1 to handle gsbase correctly. This
101triggers three main behavior changes:
102
103 - Interrupt entry will use the slower gsbase check.
104 - Interrupt entry from user mode will switch off the IST stack.
105 - Interrupt exit to kernel mode will not attempt to reschedule.
106
107We try to only use IST entries and the paranoid entry code for vectors
108that absolutely need the more expensive check for the GS base - and we
109generate all 'normal' entry points with the regular (faster) paranoid=0
110variant.