linux/arch/x86/include/asm/switch_to.h
<<
>>
Prefs
   1#ifndef _ASM_X86_SWITCH_TO_H
   2#define _ASM_X86_SWITCH_TO_H
   3
   4struct task_struct; /* one of the stranger aspects of C forward declarations */
   5
   6struct task_struct *__switch_to_asm(struct task_struct *prev,
   7                                    struct task_struct *next);
   8
   9__visible struct task_struct *__switch_to(struct task_struct *prev,
  10                                          struct task_struct *next);
  11struct tss_struct;
  12void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
  13                      struct tss_struct *tss);
  14
  15/* This runs runs on the previous thread's stack. */
  16static inline void prepare_switch_to(struct task_struct *prev,
  17                                     struct task_struct *next)
  18{
  19#ifdef CONFIG_VMAP_STACK
  20        /*
  21         * If we switch to a stack that has a top-level paging entry
  22         * that is not present in the current mm, the resulting #PF will
  23         * will be promoted to a double-fault and we'll panic.  Probe
  24         * the new stack now so that vmalloc_fault can fix up the page
  25         * tables if needed.  This can only happen if we use a stack
  26         * in vmap space.
  27         *
  28         * We assume that the stack is aligned so that it never spans
  29         * more than one top-level paging entry.
  30         *
  31         * To minimize cache pollution, just follow the stack pointer.
  32         */
  33        READ_ONCE(*(unsigned char *)next->thread.sp);
  34#endif
  35}
  36
  37asmlinkage void ret_from_fork(void);
  38
  39/*
  40 * This is the structure pointed to by thread.sp for an inactive task.  The
  41 * order of the fields must match the code in __switch_to_asm().
  42 */
  43struct inactive_task_frame {
  44#ifdef CONFIG_X86_64
  45        unsigned long r15;
  46        unsigned long r14;
  47        unsigned long r13;
  48        unsigned long r12;
  49#else
  50        unsigned long si;
  51        unsigned long di;
  52#endif
  53        unsigned long bx;
  54
  55        /*
  56         * These two fields must be together.  They form a stack frame header,
  57         * needed by get_frame_pointer().
  58         */
  59        unsigned long bp;
  60        unsigned long ret_addr;
  61};
  62
  63struct fork_frame {
  64        struct inactive_task_frame frame;
  65        struct pt_regs regs;
  66};
  67
  68#define switch_to(prev, next, last)                                     \
  69do {                                                                    \
  70        prepare_switch_to(prev, next);                                  \
  71                                                                        \
  72        ((last) = __switch_to_asm((prev), (next)));                     \
  73} while (0)
  74
  75#endif /* _ASM_X86_SWITCH_TO_H */
  76