1
2#ifndef _ASM_X86_SWITCH_TO_H
3#define _ASM_X86_SWITCH_TO_H
4
5#include <linux/sched/task_stack.h>
6
7struct task_struct;
8
9struct task_struct *__switch_to_asm(struct task_struct *prev,
10 struct task_struct *next);
11
12__visible struct task_struct *__switch_to(struct task_struct *prev,
13 struct task_struct *next);
14struct tss_struct;
15void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
16 struct tss_struct *tss);
17
18
19static inline void prepare_switch_to(struct task_struct *next)
20{
21#ifdef CONFIG_VMAP_STACK
22
23
24
25
26
27
28
29
30
31
32
33
34
35 READ_ONCE(*(unsigned char *)next->thread.sp);
36#endif
37}
38
39asmlinkage void ret_from_fork(void);
40
41
42
43
44
45struct inactive_task_frame {
46#ifdef CONFIG_X86_64
47 unsigned long r15;
48 unsigned long r14;
49 unsigned long r13;
50 unsigned long r12;
51#else
52 unsigned long si;
53 unsigned long di;
54#endif
55 unsigned long bx;
56
57
58
59
60
61 unsigned long bp;
62 unsigned long ret_addr;
63};
64
65struct fork_frame {
66 struct inactive_task_frame frame;
67 struct pt_regs regs;
68};
69
70#define switch_to(prev, next, last) \
71do { \
72 prepare_switch_to(next); \
73 \
74 ((last) = __switch_to_asm((prev), (next))); \
75} while (0)
76
77#ifdef CONFIG_X86_32
78static inline void refresh_sysenter_cs(struct thread_struct *thread)
79{
80
81 if (unlikely(this_cpu_read(cpu_tss_rw.x86_tss.ss1) == thread->sysenter_cs))
82 return;
83
84 this_cpu_write(cpu_tss_rw.x86_tss.ss1, thread->sysenter_cs);
85 wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
86}
87#endif
88
89
90static inline void update_sp0(struct task_struct *task)
91{
92
93#ifdef CONFIG_X86_32
94 load_sp0(task->thread.sp0);
95#else
96 if (static_cpu_has(X86_FEATURE_XENPV))
97 load_sp0(task_top_of_stack(task));
98#endif
99}
100
101#endif
102