Files
bsb2/kernel/arch/core_ring.cc

46 lines
1.3 KiB
C++

#include "./core_ring.h"
#include "./core_interrupt.h"
#include "./gdt.h"
namespace Core {
namespace Ring {
[[gnu::noreturn]]
void switchToUsermode(void *stackpointer, void *kickoff,
void *kickoff_parameter) {
(void)stackpointer;
(void)kickoff;
(void)kickoff_parameter;
// Segment Selectors for Ring 3
constexpr uint16_t user_cs = 3 << 3 | 3;
constexpr uint16_t user_ds = 4 << 3 | 3;
asm volatile ( \
"mov %[user_data], %%ds \n" \
"mov %[user_data], %%es \n" \
"mov %[user_data], %%fs \n" \
"mov %[user_data], %%gs \n" \
"pushq %[user_data] \n" \
"pushq %[user_stack] \n" \
"pushq %[user_eflags] \n" \
"pushq %[user_code] \n" \
"pushq %[user_function] \n" \
"mov %[user_parameter], %%rdi\n" \
"iretq \n" \
: \
: [user_data] "r"((uint64_t)user_ds),
[user_code] "r"((uint64_t)user_cs),
[user_stack] "r"((uint64_t)stackpointer),
[user_eflags] "r"((uint64_t)1<<9 | 2), // Interrupt Enable Flag
[user_function] "r"((uint64_t)kickoff),
[user_parameter] "r"((uint64_t)kickoff_parameter)
\
: "memory", "rdi"\
);
__builtin_unreachable();
}
} // namespace Ring
} // namespace Core