brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 0afdce3 Raw
111 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3==============4Kernel Entries5==============6 7This file documents some of the kernel entries in8arch/x86/entry/entry_64.S.  A lot of this explanation is adapted from9an email from Ingo Molnar:10 11https://lore.kernel.org/r/20110529191055.GC9835%40elte.hu12 13The x86 architecture has quite a few different ways to jump into14kernel code.  Most of these entry points are registered in15arch/x86/kernel/traps.c and implemented in arch/x86/entry/entry_64.S16for 64-bit, arch/x86/entry/entry_32.S for 32-bit and finally17arch/x86/entry/entry_64_compat.S which implements the 32-bit compatibility18syscall entry points and thus provides for 32-bit processes the19ability to execute syscalls when running on 64-bit kernels.20 21The IDT vector assignments are listed in arch/x86/include/asm/irq_vectors.h.22 23Some of these entries are:24 25 - system_call: syscall instruction from 64-bit code.26 27 - entry_INT80_compat: int 0x80 from 32-bit or 64-bit code; compat syscall28   either way.29 30 - entry_INT80_compat, ia32_sysenter: syscall and sysenter from 32-bit31   code32 33 - interrupt: An array of entries.  Every IDT vector that doesn't34   explicitly point somewhere else gets set to the corresponding35   value in interrupts.  These point to a whole array of36   magically-generated functions that make their way to common_interrupt()37   with the interrupt number as a parameter.38 39 - APIC interrupts: Various special-purpose interrupts for things40   like TLB shootdown.41 42 - Architecturally-defined exceptions like divide_error.43 44There are a few complexities here.  The different x86-64 entries45have different calling conventions.  The syscall and sysenter46instructions have their own peculiar calling conventions.  Some of47the IDT entries push an error code onto the stack; others don't.48IDT entries using the IST alternative stack mechanism need their own49magic to get the stack frames right.  (You can find some50documentation 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.  Swapgs54toggles whether gs is the kernel gs or the user gs.  The swapgs55instruction is rather fragile: it must nest perfectly and only in56single depth, it should only be used if entering from user mode to57kernel mode and then when returning to user-space, and precisely58so. If we mess that up even slightly, we crash.59 60So when we have a secondary entry, already in kernel mode, we *must61not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's62not switched/swapped yet.63 64Now, there's a secondary complication: there's a cheap way to test65which mode the CPU is in and an expensive way.66 67The cheap way is to pick this info off the entry frame on the kernel68stack, from the CS of the ptregs area of the kernel stack::69 70	xorl %ebx,%ebx71	testl $3,CS+8(%rsp)72	je error_kernelspace73	SWAPGS74 75The expensive (paranoid) way is to read back the MSR_GS_BASE value76(which is what SWAPGS modifies)::77 78	movl $1,%ebx79	movl $MSR_GS_BASE,%ecx80	rdmsr81	testl %edx,%edx82	js 1f   /* negative -> in kernel */83	SWAPGS84	xorl %ebx,%ebx85  1:	ret86 87If we are at an interrupt or user-trap/gate-alike boundary then we can88use the faster check: the stack will be a reliable indicator of89whether SWAPGS was already done: if we see that we are a secondary90entry interrupting kernel mode execution, then we know that the GS91base has already been switched. If it says that we interrupted92user-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 the96stack but before we executed SWAPGS, then the only safe way to check97for GS is the slower method: the RDMSR.98 99Therefore, super-atomic entries (except NMI, which is handled separately)100must use idtentry with paranoid=1 to handle gsbase correctly.  This101triggers 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 vectors108that absolutely need the more expensive check for the GS base - and we109generate all 'normal' entry points with the regular (faster) paranoid=0110variant.111