1This file documents some of the kernel entries in
   2arch/x86/kernel/entry_64.S.  A lot of this explanation is adapted from
   3an email from Ingo Molnar:
   7The x86 architecture has quite a few different ways to jump into
   8kernel code.  Most of these entry points are registered in
   9arch/x86/kernel/traps.c and implemented in arch/x86/kernel/entry_64.S
  10and arch/x86/ia32/ia32entry.S.
  12The IDT vector assignments are listed in arch/x86/include/irq_vectors.h.
  14Some of these entries are:
  16 - system_call: syscall instruction from 64-bit code.
  18 - ia32_syscall: int 0x80 from 32-bit or 64-bit code; compat syscall
  19   either way.
  21 - ia32_syscall, ia32_sysenter: syscall and sysenter from 32-bit
  22   code
  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.
  30 - APIC interrupts: Various special-purpose interrupts for things
  31   like TLB shootdown.
  33 - Architecturally-defined exceptions like divide_error.
  35There are a few complexities here.  The different x86-64 entries
  36have different calling conventions.  The syscall and sysenter
  37instructions have their own peculiar calling conventions.  Some of
  38the IDT entries push an error code onto the stack; others don't.
  39IDT entries using the IST alternative stack mechanism need their own
  40magic to get the stack frames right.  (You can find some
  41documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
  42Volume 3, Chapter 6.)
  44Dealing with the swapgs instruction is especially tricky.  Swapgs
  45toggles whether gs is the kernel gs or the user gs.  The swapgs
  46instruction is rather fragile: it must nest perfectly and only in
  47single depth, it should only be used if entering from user mode to
  48kernel mode and then when returning to user-space, and precisely
  49so. If we mess that up even slightly, we crash.
  51So when we have a secondary entry, already in kernel mode, we *must
  52not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
  53not switched/swapped yet.
  55Now, there's a secondary complication: there's a cheap way to test
  56which mode the CPU is in and an expensive way.
  58The cheap way is to pick this info off the entry frame on the kernel
  59stack, from the CS of the ptregs area of the kernel stack:
  61        xorl %ebx,%ebx
  62        testl $3,CS+8(%rsp)
  63        je error_kernelspace
  64        SWAPGS
  66The expensive (paranoid) way is to read back the MSR_GS_BASE value
  67(which is what SWAPGS modifies):
  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
  761:      ret
  78and the whole paranoid non-paranoid macro complexity is about whether
  79to suffer that RDMSR cost.
  81If we are at an interrupt or user-trap/gate-alike boundary then we can
  82use the faster check: the stack will be a reliable indicator of
  83whether SWAPGS was already done: if we see that we are a secondary
  84entry interrupting kernel mode execution, then we know that the GS
  85base has already been switched. If it says that we interrupted
  86user-space execution then we must do the SWAPGS.
  88But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
  89which might have triggered right after a normal entry wrote CS to the
  90stack but before we executed SWAPGS, then the only safe way to check
  91for GS is the slower method: the RDMSR.
  93So we try only to mark those entry methods 'paranoid' that absolutely
  94need the more expensive check for the GS base - and we generate all
  95'normal' entry points with the regular (faster) entry macros.
  96 kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.