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"
8
10#include <mos/mos_global.h>
12#include <mos/syslog/printk.hpp>
15#include <mos/types.hpp>
16#include <mos/x86/cpu/cpu.hpp>
20#include <mos_stdlib.hpp>
21#include <mos_string.hpp>
22
23typedef void (*switch_func_t)();
24
25extern "C" void x86_normal_switch_impl();
26extern "C" void x86_context_switch_impl(ptr_t *old_stack, ptr_t new_kstack, switch_func_t switcher, bool *lock);
28
30{
32 const thread_entry_t entry = (thread_entry_t) regs->ip;
33 void *const arg = (void *) regs->di;
34 entry(arg);
36}
37
42
44{
45 MOS_ASSERT_X(thread->platform_options.xsaveptr == NULL, "xsaveptr should be NULL");
46 thread->platform_options.xsaveptr = xsave_area_slab.create();
47 thread->k_stack.head -= sizeof(platform_regs_t);
49 *regs = (platform_regs_t) {};
50
53 regs->sp = thread->mode == THREAD_MODE_KERNEL ? thread->k_stack.top : thread->u_stack.top;
54
55 if (thread->mode == THREAD_MODE_USER)
56 {
57 regs->eflags = 0x202;
58 if (thread->owner->platform_options.iopl)
59 regs->eflags |= 0x3000;
60 }
61
62 return regs;
63}
64
65void platform_context_setup_main_thread(Thread *thread, ptr_t entry, ptr_t sp, int argc, ptr_t argv, ptr_t envp)
66{
68 regs->ip = entry;
69 regs->di = argc;
70 regs->si = argv;
71 regs->dx = envp;
72 regs->sp = sp;
73}
74
76{
77 if (thread->mode == THREAD_MODE_USER)
78 if (thread->platform_options.xsaveptr)
79 kfree(thread->platform_options.xsaveptr), thread->platform_options.xsaveptr = NULL;
80}
81
83{
85 regs->di = (ptr_t) arg;
86 regs->ip = (ptr_t) entry;
87
88 if (thread->mode == THREAD_MODE_KERNEL)
89 return;
90
91 MOS_ASSERT(thread->owner->mm == current_mm);
92 MOS_ASSERT(thread != thread->owner->main_thread);
93
94 regs->di = (ptr_t) arg; // argument
95 regs->sp = thread->u_stack.head; // update the stack pointer
96}
97
99{
101 *to_regs = *platform_thread_regs(from);
102 to_regs->ax = 0; // return 0 for the child
103
104 // synchronise the sp of user stack
105 if (to->mode == THREAD_MODE_USER)
106 {
107 to->u_stack.head = to_regs->sp;
110 }
111
114 to->k_stack.head -= sizeof(platform_regs_t);
115}
116
117void platform_switch_to_thread(Thread *current, Thread *new_thread, ContextSwitchBehaviorFlags switch_flags)
118{
119 const switch_func_t switch_func = [=]() -> switch_func_t
120 {
121 switch (switch_flags)
122 {
125 default: return x86_normal_switch_impl; break;
126 }
127 }();
128
129 if (current)
131
132 x86_xrstor_thread(new_thread);
133 x86_set_fsbase(new_thread);
134
135 current_cpu->thread = new_thread;
136 __atomic_store_n(&per_cpu(x86_cpu_descriptor)->tss.rspN[0], new_thread->k_stack.top, __ATOMIC_SEQ_CST);
137
138 ptr_t trash = 0;
139 ptr_t *const stack_ptr = current ? &current->k_stack.head : &trash;
140
141 bool trash_lock = false;
142 bool *const lock = current ? &current->state_lock.flag : &trash_lock;
143 x86_context_switch_impl(stack_ptr, new_thread->k_stack.head, switch_func, lock);
144}
145
147{
148 __asm__ volatile("wrfsbase %0" ::"r"(thread->platform_options.fs_base) : "memory");
149}
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:12
#define MOS_ASSERT(cond)
Definition assert.hpp:19
#define MOS_UNREACHABLE()
Definition assert.hpp:10
uint8_t argc
Definition avr_io.c:15
void platform_context_cleanup(Thread *thread)
Definition context.cpp:75
static void x86_start_kernel_thread()
Definition context.cpp:29
static void x86_start_user_thread()
Definition context.cpp:38
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:65
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:98
void platform_context_setup_child_thread(Thread *thread, thread_entry_t entry, void *arg)
Definition context.cpp:82
void x86_set_fsbase(Thread *thread)
Definition context.cpp:146
mos::Slab< u8 > xsave_area_slab("x86.xsave", 0)
static platform_regs_t * x86_setup_thread_common(Thread *thread)
Definition context.cpp:43
void platform_switch_to_thread(Thread *current, Thread *new_thread, ContextSwitchBehaviorFlags switch_flags)
Definition context.cpp:117
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)
MOSAPI void(1, 2) fatal_abort(const char *fmt
@ THREAD_MODE_KERNEL
@ THREAD_MODE_USER
#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
@ SWITCH_TO_NEW_KERNEL_THREAD
Definition platform.hpp:56
@ SWITCH_TO_NEW_USER_THREAD
Definition platform.hpp:55
#define current_thread
Definition platform.hpp:33
#define per_cpu(var)
Definition platform.hpp:28
#define current_mm
Definition platform.hpp:35
#define current_cpu
Definition platform.hpp:32
platform_regs_t * platform_thread_regs(Thread *thread)
void(* switch_func_t)()
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
void x86_interrupt_return_impl(const platform_regs_t *regs)