Based on kernel version 3.9. Page generated on 2013-05-02 23:17 EST.
1 This file documents some of the kernel entries in 2 arch/x86/kernel/entry_64.S. A lot of this explanation is adapted from 3 an email from Ingo Molnar: 4 5 http://lkml.kernel.org/r/<20110529191055.GC9835%40elte.hu> 6 7 The x86 architecture has quite a few different ways to jump into 8 kernel code. Most of these entry points are registered in 9 arch/x86/kernel/traps.c and implemented in arch/x86/kernel/entry_64.S 10 and arch/x86/ia32/ia32entry.S. 11 12 The IDT vector assignments are listed in arch/x86/include/irq_vectors.h. 13 14 Some of these entries are: 15 16 - system_call: syscall instruction from 64-bit code. 17 18 - ia32_syscall: int 0x80 from 32-bit or 64-bit code; compat syscall 19 either way. 20 21 - ia32_syscall, ia32_sysenter: syscall and sysenter from 32-bit 22 code 23 24 - interrupt: An array of entries. Every IDT vector that doesn't 25 explicitly point somewhere else gets set to the corresponding 26 value in interrupts. These point to a whole array of 27 magically-generated functions that make their way to do_IRQ with 28 the interrupt number as a parameter. 29 30 - APIC interrupts: Various special-purpose interrupts for things 31 like TLB shootdown. 32 33 - Architecturally-defined exceptions like divide_error. 34 35 There are a few complexities here. The different x86-64 entries 36 have different calling conventions. The syscall and sysenter 37 instructions have their own peculiar calling conventions. Some of 38 the IDT entries push an error code onto the stack; others don't. 39 IDT entries using the IST alternative stack mechanism need their own 40 magic to get the stack frames right. (You can find some 41 documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM, 42 Volume 3, Chapter 6.) 43 44 Dealing with the swapgs instruction is especially tricky. Swapgs 45 toggles whether gs is the kernel gs or the user gs. The swapgs 46 instruction is rather fragile: it must nest perfectly and only in 47 single depth, it should only be used if entering from user mode to 48 kernel mode and then when returning to user-space, and precisely 49 so. If we mess that up even slightly, we crash. 50 51 So when we have a secondary entry, already in kernel mode, we *must 52 not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's 53 not switched/swapped yet. 54 55 Now, there's a secondary complication: there's a cheap way to test 56 which mode the CPU is in and an expensive way. 57 58 The cheap way is to pick this info off the entry frame on the kernel 59 stack, from the CS of the ptregs area of the kernel stack: 60 61 xorl %ebx,%ebx 62 testl $3,CS+8(%rsp) 63 je error_kernelspace 64 SWAPGS 65 66 The expensive (paranoid) way is to read back the MSR_GS_BASE value 67 (which is what SWAPGS modifies): 68 69 movl $1,%ebx 70 movl $MSR_GS_BASE,%ecx 71 rdmsr 72 testl %edx,%edx 73 js 1f /* negative -> in kernel */ 74 SWAPGS 75 xorl %ebx,%ebx 76 1: ret 77 78 and the whole paranoid non-paranoid macro complexity is about whether 79 to suffer that RDMSR cost. 80 81 If we are at an interrupt or user-trap/gate-alike boundary then we can 82 use the faster check: the stack will be a reliable indicator of 83 whether SWAPGS was already done: if we see that we are a secondary 84 entry interrupting kernel mode execution, then we know that the GS 85 base has already been switched. If it says that we interrupted 86 user-space execution then we must do the SWAPGS. 87 88 But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context, 89 which might have triggered right after a normal entry wrote CS to the 90 stack but before we executed SWAPGS, then the only safe way to check 91 for GS is the slower method: the RDMSR. 92 93 So we try only to mark those entry methods 'paranoid' that absolutely 94 need the more expensive check for the GS base - and we generate all 95 'normal' entry points with the regular (faster) entry macros.