MOS Source Code
Loading...
Searching...
No Matches
context.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
5#include "mos/platform/platform_defs.hpp"
9
11#include <mos/mos_global.h>
13#include <mos/syslog/printk.hpp>
16#include <mos/types.hpp>
17#include <mos/x86/cpu/cpu.hpp>
21#include <mos_stdlib.hpp>
22#include <mos_string.hpp>
23
24typedef void (*switch_func_t)();
25
26extern "C" void x86_normal_switch_impl();
27extern "C" void x86_context_switch_impl(ptr_t *old_stack, ptr_t new_kstack, switch_func_t switcher, bool *lock);
29
31{
33 const thread_entry_t entry = (thread_entry_t) regs->ip;
34 void *const arg = (void *) regs->di;
35 entry(arg);
37}
38
45
47{
48 MOS_ASSERT_X(thread->platform_options.xsaveptr == NULL, "xsaveptr should be NULL");
49 thread->platform_options.xsaveptr = xsave_area_slab.create();
50 thread->k_stack.head -= sizeof(platform_regs_t);
52 *regs = (platform_regs_t) { 0 };
53
56 regs->sp = thread->mode == THREAD_MODE_KERNEL ? thread->k_stack.top : thread->u_stack.top;
57
58 if (thread->mode == THREAD_MODE_USER)
59 {
60 regs->eflags = 0x202;
61 if (thread->owner->platform_options.iopl)
62 regs->eflags |= 0x3000;
63 }
64
65 return regs;
66}
67
69{
71 regs->ip = entry;
72 regs->di = argc;
73 regs->si = argv;
74 regs->dx = envp;
75 regs->sp = sp;
76}
77
79{
80 if (thread->mode == THREAD_MODE_USER)
81 if (thread->platform_options.xsaveptr)
82 kfree(thread->platform_options.xsaveptr), thread->platform_options.xsaveptr = NULL;
83}
84
86{
88 regs->di = (ptr_t) arg;
89 regs->ip = (ptr_t) entry;
90
91 if (thread->mode == THREAD_MODE_KERNEL)
92 return;
93
94 MOS_ASSERT(thread->owner->mm == current_mm);
95 MOS_ASSERT(thread != thread->owner->main_thread);
96
97 regs->di = (ptr_t) arg; // argument
98 regs->sp = thread->u_stack.head; // update the stack pointer
99}
100
102{
104 *to_regs = *platform_thread_regs(from);
105 to_regs->ax = 0; // return 0 for the child
106
107 // synchronise the sp of user stack
108 if (to->mode == THREAD_MODE_USER)
109 {
110 to->u_stack.head = to_regs->sp;
113 }
114
117 to->k_stack.head -= sizeof(platform_regs_t);
118}
119
121{
122 const switch_func_t switch_func = [=]() -> switch_func_t
123 {
124 switch (switch_flags)
125 {
128 default: return x86_normal_switch_impl; break;
129 }
130 }();
131
132 if (current)
134
135 x86_xrstor_thread(new_thread);
136 x86_set_fsbase(new_thread);
137
138 current_cpu->thread = new_thread;
139 __atomic_store_n(&per_cpu(x86_cpu_descriptor)->tss.rsp0, new_thread->k_stack.top, __ATOMIC_SEQ_CST);
140
141 ptr_t trash = 0;
142 ptr_t *const stack_ptr = current ? &current->k_stack.head : &trash;
143
144 bool trash_lock = false;
145 bool *const lock = current ? &current->state_lock.flag : &trash_lock;
146 x86_context_switch_impl(stack_ptr, new_thread->k_stack.head, switch_func, lock);
147}
148
150{
151 __asm__ volatile("wrfsbase %0" ::"r"(thread->platform_options.fs_base) : "memory");
152}
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:15
#define MOS_ASSERT(cond)
Definition assert.hpp:14
#define MOS_UNREACHABLE()
Definition assert.hpp:11
void platform_context_cleanup(Thread *thread)
Definition context.cpp:78
void platform_switch_to_thread(Thread *current, Thread *new_thread, switch_flags_t switch_flags)
Definition context.cpp:120
static void x86_start_kernel_thread()
Definition context.cpp:30
static void x86_start_user_thread()
Definition context.cpp:39
void platform_context_setup_main_thread(Thread *thread, ptr_t entry, ptr_t sp, int argc, ptr_t argv, ptr_t envp)
Definition context.cpp:68
void x86_context_switch_impl(ptr_t *old_stack, ptr_t new_kstack, switch_func_t switcher, bool *lock)
void platform_context_clone(Thread *from, Thread *to)
Definition context.cpp:101
void platform_context_setup_child_thread(Thread *thread, thread_entry_t entry, void *arg)
Definition context.cpp:85
void x86_set_fsbase(Thread *thread)
Definition context.cpp:149
mos::Slab< u8 > xsave_area_slab("x86.xsave", 0)
static platform_regs_t * x86_setup_thread_common(Thread *thread)
Definition context.cpp:46
void x86_normal_switch_impl()
#define GDT_SEGMENT_USERCODE
#define GDT_SEGMENT_KCODE
#define GDT_SEGMENT_USERDATA
#define GDT_SEGMENT_KDATA
void x86_xsave_thread(Thread *thread)
mos::Slab< u8 > xsave_area_slab
void x86_xrstor_thread(Thread *thread)
void signal_exit_to_user_prepare(platform_regs_t *regs)
Prepare to exit to userspace.
Definition signal.cpp:240
MOSAPI void(1, 2) fatal_abort(const char *fmt
@ THREAD_MODE_KERNEL
@ THREAD_MODE_USER
const char ** argv
Definition kmain.cpp:34
size_t argc
Definition kmain.cpp:33
#define current
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
#define current_thread
Definition platform.hpp:32
#define per_cpu(var)
Definition platform.hpp:27
#define current_mm
Definition platform.hpp:34
#define current_cpu
Definition platform.hpp:31
switch_flags_t
Definition platform.hpp:76
@ SWITCH_TO_NEW_KERNEL_THREAD
Definition platform.hpp:79
@ SWITCH_TO_NEW_USER_THREAD
Definition platform.hpp:78
void platform_return_to_userspace(platform_regs_t *regs)
void(* switch_func_t)()
platform_regs_t * platform_thread_regs(const Thread *thread)
void(* thread_entry_t)(void *arg)
Definition signal_types.h:8
Thread * main_thread
platform_process_options_t platform_options
platform per-process flags
MMContext * mm
platform_thread_options_t platform_options
platform-specific thread options
thread_mode mode
user-mode thread or kernel-mode
Process * owner
downwards_stack_t u_stack
user-mode stack
downwards_stack_t k_stack
kernel-mode stack
unsigned long ptr_t
Definition types.h:21