mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.4 KiB
96 lines
2.4 KiB
/* SPDX-License-Identifier: GPL-2.0 */ |
|
#ifndef _ASM_X86_SWITCH_TO_H |
|
#define _ASM_X86_SWITCH_TO_H |
|
|
|
#include <linux/sched/task_stack.h> |
|
|
|
struct task_struct; /* one of the stranger aspects of C forward declarations */ |
|
|
|
struct task_struct *__switch_to_asm(struct task_struct *prev, |
|
struct task_struct *next); |
|
|
|
__visible struct task_struct *__switch_to(struct task_struct *prev, |
|
struct task_struct *next); |
|
|
|
asmlinkage void ret_from_fork(void); |
|
|
|
/* |
|
* This is the structure pointed to by thread.sp for an inactive task. The |
|
* order of the fields must match the code in __switch_to_asm(). |
|
*/ |
|
struct inactive_task_frame { |
|
#ifdef CONFIG_X86_64 |
|
unsigned long r15; |
|
unsigned long r14; |
|
unsigned long r13; |
|
unsigned long r12; |
|
#else |
|
unsigned long flags; |
|
unsigned long si; |
|
unsigned long di; |
|
#endif |
|
unsigned long bx; |
|
|
|
/* |
|
* These two fields must be together. They form a stack frame header, |
|
* needed by get_frame_pointer(). |
|
*/ |
|
unsigned long bp; |
|
unsigned long ret_addr; |
|
}; |
|
|
|
struct fork_frame { |
|
struct inactive_task_frame frame; |
|
struct pt_regs regs; |
|
}; |
|
|
|
#define switch_to(prev, next, last) \ |
|
do { \ |
|
((last) = __switch_to_asm((prev), (next))); \ |
|
} while (0) |
|
|
|
#ifdef CONFIG_X86_32 |
|
static inline void refresh_sysenter_cs(struct thread_struct *thread) |
|
{ |
|
/* Only happens when SEP is enabled, no need to test "SEP"arately: */ |
|
if (unlikely(this_cpu_read(cpu_tss_rw.x86_tss.ss1) == thread->sysenter_cs)) |
|
return; |
|
|
|
this_cpu_write(cpu_tss_rw.x86_tss.ss1, thread->sysenter_cs); |
|
wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); |
|
} |
|
#endif |
|
|
|
/* This is used when switching tasks or entering/exiting vm86 mode. */ |
|
static inline void update_task_stack(struct task_struct *task) |
|
{ |
|
/* sp0 always points to the entry trampoline stack, which is constant: */ |
|
#ifdef CONFIG_X86_32 |
|
if (static_cpu_has(X86_FEATURE_XENPV)) |
|
load_sp0(task->thread.sp0); |
|
else |
|
this_cpu_write(cpu_tss_rw.x86_tss.sp1, task->thread.sp0); |
|
#else |
|
/* |
|
* x86-64 updates x86_tss.sp1 via cpu_current_top_of_stack. That |
|
* doesn't work on x86-32 because sp1 and |
|
* cpu_current_top_of_stack have different values (because of |
|
* the non-zero stack-padding on 32bit). |
|
*/ |
|
if (static_cpu_has(X86_FEATURE_XENPV)) |
|
load_sp0(task_top_of_stack(task)); |
|
#endif |
|
} |
|
|
|
static inline void kthread_frame_init(struct inactive_task_frame *frame, |
|
unsigned long fun, unsigned long arg) |
|
{ |
|
frame->bx = fun; |
|
#ifdef CONFIG_X86_32 |
|
frame->di = arg; |
|
#else |
|
frame->r12 = arg; |
|
#endif |
|
} |
|
|
|
#endif /* _ASM_X86_SWITCH_TO_H */
|
|
|