From: Amelia Coutard Date: Tue, 11 Oct 2022 11:55:06 +0000 (+0200) Subject: Implemented a very simple way of jumping to userspace X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=e79110fb09e1f7a59f14d79c5ac2ca688ce3cefd;p=voyage-au-centre-des-fichiers.git Implemented a very simple way of jumping to userspace --- diff --git a/src/boot.S b/src/boot.S index d265748..fe2f52f 100644 --- a/src/boot.S +++ b/src/boot.S @@ -112,6 +112,10 @@ phys_mem_map: .skip 0x1000 * 128 - 8 stack_bottom: .skip 1024 * 16 # 16KiB stack_top: +interrupt_stack_bottom: +.skip 1024 * 16 # 16KiB +.globl interrupt_stack_top +interrupt_stack_top: .section .bootstrap_text .code32 diff --git a/src/kernel.cpp b/src/kernel.cpp index baf2dc7..850c108 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -3,8 +3,11 @@ #include "utils.hpp" #include "serial.hpp" #include "interrupts.hpp" +#include "ring3.hpp" os::idt<32> idt; +extern "C" os::tss TSS; +extern "C" char interrupt_stack_top; extern "C" os::paging::PML4T PML4T; extern "C" void kmain(unsigned long magic, os::phys_ptr info) { @@ -136,7 +139,28 @@ extern "C" void kmain(unsigned long magic, os::phys_ptrcontents[510].U_S(true); + PML4T.contents[511].base_address()->contents[511].U_S(true); + PML4T.contents[511].U_S(true); + + os::print("Load ring 3 interrupts stack:\n"); + os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top)); + os::print("Load TSS:\n"); + os::load_tss(); + os::print("Enable syscalls:\n"); + os::enable_syscalls(); + os::print("Trying move to ring 3:\n"); + os::ftl_to_userspace(); +} + +extern "C" std::uint64_t syscall(std::uint64_t in1); + +extern "C" void userspaaaaaaaaace() { + syscall('a'); + syscall('b'); + syscall('c'); + syscall('\n'); + while (true) { asm volatile("nop"); } } diff --git a/src/ring3.S b/src/ring3.S new file mode 100644 index 0000000..3e21c2e --- /dev/null +++ b/src/ring3.S @@ -0,0 +1,27 @@ +.section .text + +.globl ftl_to_userspace +ftl_to_userspace: + mov $userspaaaaaaaaace, %rcx + mov $0x202, %r11 # EFLAGS + sysretq + +.globl syscall_64bit_handler +syscall_64bit_handler: + push %rcx + mov %r10, %rcx + call syscall_64bit_handler_cpp + pop %rcx + sysretq + +.globl load_tss +load_tss: + mov $GDT.TSS, %ax + ltr %ax + ret + +.globl syscall +syscall: + mov %rcx, %r10 + syscall + ret diff --git a/src/ring3.cpp b/src/ring3.cpp new file mode 100644 index 0000000..282f0bb --- /dev/null +++ b/src/ring3.cpp @@ -0,0 +1,27 @@ +#include "ring3.hpp" +#include "utils.hpp" +#include "serial.hpp" + +void os::set_ring0_stack(os::tss& tss, std::uint64_t stack) { + tss.rsp0 = stack; +} + +extern "C" void syscall_64bit_handler(); + +void os::enable_syscalls() { + // Enable bit 0 (SYSCALL Enable) of msr IA32_EFER. + // This is required to enable syscall/sysret on x86_64 intel. + os::set_msr(0xC0000080, os::get_msr(0xC0000080) | (1 << 0)); + os::set_msr(0xC0000081, + (std::uint64_t(8 - 8 + 0b11) << 48) + // sysret_cs_and_ss (e.g., userspace segments) + (std::uint64_t(24 - 8 + 0b00) << 32) + // syscall_cs_and_ss (e.g., kernelspace segments) + std::uint64_t(0) // syscall_target_eip, only relevant to 32-bits so useless here + ); + os::set_msr(0xC0000082, std::uint64_t(&syscall_64bit_handler)); // RIP for 64-bit program + os::set_msr(0xC0000083, 0); // RIP for 32-bit program, we ignore this one because the OS is only supposed to support programs running with 64 bits. + os::set_msr(0xC0000084, 0x00000000); // syscall flag mask, we don't want to change the flags for now. +} + +extern "C" void syscall_64bit_handler_cpp(std::uint64_t v) { + os::printc((char)v); +} diff --git a/src/ring3.hpp b/src/ring3.hpp new file mode 100644 index 0000000..e19e354 --- /dev/null +++ b/src/ring3.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace os { + +struct __attribute__((packed)) tss { + std::uint32_t reserved_1; + std::uint64_t rsp0; + std::uint64_t rsp1; + std::uint64_t rsp2; + std::uint64_t reserved_2; + std::uint64_t ist1; + std::uint64_t ist2; + std::uint64_t ist3; + std::uint64_t ist4; + std::uint64_t ist5; + std::uint64_t ist6; + std::uint64_t ist7; + char reserved_3[10]; + std::uint16_t iopb; +}; + +void set_ring0_stack(tss& tss, std::uint64_t stack); +extern "C" void load_tss(); +void enable_syscalls(); +extern "C" void ftl_to_userspace(); + +}