From 3d2eb900a3f390f6969a0d477e4287dfd8ca7043 Mon Sep 17 00:00:00 2001 From: Amelia Coutard Date: Tue, 1 Aug 2023 06:00:06 +0200 Subject: [PATCH] Changed processes to save all (general-purpose) registers on syscalls (except for r11 and rcx, of course). Will keep working on them later --- doc.txt | 4 +- kernel/src/elf64.cpp | 3 -- kernel/src/kernel.cpp | 6 ++- kernel/src/ring3.S | 96 +++++++++++++++++++++++++++---------------- kernel/src/ring3.cpp | 4 ++ kernel/src/ring3.hpp | 30 ++++++++------ 6 files changed, 88 insertions(+), 55 deletions(-) diff --git a/doc.txt b/doc.txt index 75829d0..307d7f8 100644 --- a/doc.txt +++ b/doc.txt @@ -12,8 +12,8 @@ isos documentation: 0000'7FFF'FFFF'0000 ↔ 0000'8000'0000'0000 - stack: 64KiB -- Invalid addresses -- FFFF'8000'0000'0000 ↔ FFFF'C000'0000'0000 - physical memory: 64TiB -FFFF'C000'0000'0000 ↔ FFFF'C000'1000'0000 - process information table: 256MiB, 2048 processes, 4093 ports/process -FFFF'C000'1000'0000 ↔ FFFF'FFFF'8000'0000 - unmapped: 64TiB - 2GiB - 128MiB - 64KiB +FFFF'C000'0000'0000 ↔ ____'____'____'____ - process information table: 2048 processes, 4093 ports/process +____'____'____'____ ↔ FFFF'FFFF'8000'0000 - unmapped FFFF'FFFF'8000'0000 ↔10000'0000'0000'0000 - kernel: 2GiB --------------------------- diff --git a/kernel/src/elf64.cpp b/kernel/src/elf64.cpp index acc4244..c129d07 100644 --- a/kernel/src/elf64.cpp +++ b/kernel/src/elf64.cpp @@ -33,7 +33,6 @@ void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length constexpr std::size_t stack_size = 16 * 0x1000 /* 64KiB */; std::byte* const stack = (std::byte*)0x0000'8000'0000'0000 - stack_size; - result.exists = true; result.PML4T = phys_ptr(os::paging::page_allocator.allocate(1).ptr.get_phys_addr()); result.rip = std::uint64_t(elf_header.entry); result.rsp = std::uint64_t(stack + stack_size); @@ -43,8 +42,6 @@ void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length result.r13 = 0; result.r14 = 0; result.r15 = 0; - result.mxcsr = 0; - result.x87cw = 0; // Copy kernel mappings to the new virtual address space. memset(result.PML4T->contents, 0, 256 * sizeof(os::paging::PML4E)); diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 1fd5a1c..2035138 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -59,6 +59,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptrtype != multiboot2::info::type_t::end; it = multiboot2::next(it)) { switch (it->type) { case multiboot2::info::type_t::memory_map: @@ -79,7 +80,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it)); - os::assert(!os::get_process(0).exists, "Multiple modules specified in the multiboot. This is unsupported."); + os::assert(!module_specified, "Multiple modules specified in the multiboot. This is unsupported."); + module_specified = true; os::elf::load_elf(os::get_process(0), (std::byte*)multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it), @@ -89,7 +91,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr kernel_s = ([]() { diff --git a/kernel/src/ring3.S b/kernel/src/ring3.S index dd23354..5551cff 100644 --- a/kernel/src/ring3.S +++ b/kernel/src/ring3.S @@ -37,45 +37,53 @@ load_tss: .globl syscall_64bit_handler syscall_64bit_handler: - mov %rax, rax_save - movq current_pid, %rax - shl $17, %rax # * 0x1000 * 32 (i.e. the size of a process) - addq process_struct_table, %rax - # %rax now contains the address of the current process struct. - movq %rcx, 0x10(%rax) # %rip - movq %rbx, 0x18(%rax) - movq %rsp, 0x20(%rax) - movq %rbp, 0x28(%rax) - movq %r12, 0x30(%rax) - movq %r13, 0x38(%rax) - movq %r14, 0x40(%rax) - movq %r15, 0x48(%rax) - fstcw 0x58(%rax) - # Current process registers have now all been saved. - mov rax_save, %rax - - mov %r10, %rcx + # Save all registers: + .irp reg,rax,rbx,rcx,rdx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15 + mov %\reg, save_reg_tmp_\reg + .endr + # Setup stack: + mov $stack_top, %rsp + # Get process data location: + mov current_pid, %rdi + call get_process + # Really save all regs: + .irp reg,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mov save_regs_tmp + \reg * 8, %rbx # Get %r\reg + mov %rbx, 8 + \reg * 8(%rax) # And store it. + .endr + mov save_reg_tmp_rcx, %rbx # Save the rip also. + mov %rbx, 0x88(%rax) + # Get ready for syscall: + mov save_reg_tmp_rdi, %rdi + mov save_reg_tmp_rsi, %rsi + mov save_reg_tmp_rdx, %rdx + mov save_reg_tmp_r10, %rcx # Syscall ABI -> C ABI + mov save_reg_tmp_r8, %r8 + mov save_reg_tmp_r9, %r9 + mov save_reg_tmp_rax, %rax cmp $syscall_n, %rax - mov $stack_top, %rsp # Setup stack jae incorrect_syscall callq *syscalls_call_table(, %rax, 8) syscall_end: - mov %rax, rax_save - movq current_pid, %rax - shl $17, %rax # * 0x1000 * 32 (i.e. the size of a process) - addq process_struct_table, %rax - # %rax now contains the address of the current process struct. - movq 0x10(%rax), %rcx # %rip - movq 0x18(%rax), %rbx - movq 0x20(%rax), %rsp - movq 0x28(%rax), %rbp - movq 0x30(%rax), %r12 - movq 0x38(%rax), %r13 - movq 0x40(%rax), %r14 - movq 0x48(%rax), %r15 - fldcw 0x58(%rax) - # Current process registers have now all been loaded. - mov rax_save, %rax + mov %rax, %rbp # Save the return + mov %rdx, %rbx # registers. + # Get process data location: + mov current_pid, %rdi + call get_process + # Restore all regs: + .irp reg,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mov 8 + \reg * 8(%rax), %rbx # Get %r\reg + mov %rbx, save_regs_tmp + \reg * 8 # And restore it. + .endr + mov %rbp, save_reg_tmp_rax # Restore the return + mov %rbx, save_reg_tmp_rdx # registers as well. + mov 0x88(%rax), %rbx # Save the rip in place of rcx, because this is sysret. + mov %rbx, save_reg_tmp_rcx + # Really restore all regs: + .irp reg,rax,rbx,rcx,rdx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15 + mov save_reg_tmp_\reg, %\reg + .endr + # Current process registers have now all been restored. sysretq incorrect_syscall: call syscall_rax_error_handler @@ -90,4 +98,20 @@ syscalls_call_table: process_struct_table: .quad 0xFFFFC00000000000 .section .data -rax_save: .quad 1 +save_regs_tmp: +save_reg_tmp_rax: .quad 1 +save_reg_tmp_rbx: .quad 1 +save_reg_tmp_rcx: .quad 1 +save_reg_tmp_rdx: .quad 1 +save_reg_tmp_rsp: .quad 1 +save_reg_tmp_rbp: .quad 1 +save_reg_tmp_rsi: .quad 1 +save_reg_tmp_rdi: .quad 1 +save_reg_tmp_r8: .quad 1 +save_reg_tmp_r9: .quad 1 +save_reg_tmp_r10: .quad 1 +save_reg_tmp_r11: .quad 1 +save_reg_tmp_r12: .quad 1 +save_reg_tmp_r13: .quad 1 +save_reg_tmp_r14: .quad 1 +save_reg_tmp_r15: .quad 1 diff --git a/kernel/src/ring3.cpp b/kernel/src/ring3.cpp index 847cbaf..c8b8400 100644 --- a/kernel/src/ring3.cpp +++ b/kernel/src/ring3.cpp @@ -69,4 +69,8 @@ extern "C" void os::syscall_rax_error_handler() { os::assert(false, "Incorrect %rax for syscall."); } +os::process& os::get_process(std::uint64_t pid) { + os::assert(pid < 2048, "Invalid pid: {}.\n", pid); + return ((process*)0xFFFF'C000'0000'0000)[pid]; +} std::uint64_t os::current_pid; diff --git a/kernel/src/ring3.hpp b/kernel/src/ring3.hpp index 7d26636..49069bf 100644 --- a/kernel/src/ring3.hpp +++ b/kernel/src/ring3.hpp @@ -61,31 +61,37 @@ struct port { }; struct process { - bool exists; phys_ptr PML4T; - std::uint64_t rip; + std::uint64_t rax; std::uint64_t rbx; + std::uint64_t rcx; + std::uint64_t rdx; std::uint64_t rsp; std::uint64_t rbp; + std::uint64_t rsi; + std::uint64_t rdi; + std::uint64_t r8; + std::uint64_t r9; + std::uint64_t r10; + std::uint64_t r11; std::uint64_t r12; std::uint64_t r13; std::uint64_t r14; std::uint64_t r15; - std::uint64_t mxcsr; // UNUSED for now. - std::uint64_t x87cw; - port ports[4093]; + std::uint64_t rip; + port ports[2043]; + char padding[16]; }; -static_assert(sizeof(process) == 0x1000 * 32); +static_assert(sizeof(process) == 4096 * 16); +static_assert(0xFFFF'C000'0000'0000 + sizeof(process) * 2048 < 0xFFFF'FFFF'8000'0000); + +extern "C" process& get_process(std::uint64_t pid); -inline process& get_process(std::uint64_t pid) { - os::assert(pid < 2048, "Invalid pid: {}.\n", pid); - return ((process*)0xFFFF'C000'0000'0000)[pid]; -} inline bool process_exists(std::uint64_t pid) { - return pid < 2048 && get_process(pid).exists; + return pid < 2048; } inline bool port_exists(std::uint64_t pid, std::uint64_t port) { - return port < 4093 && process_exists(pid) && get_process(pid).ports[port].exists; + return port < 2043 && process_exists(pid) && get_process(pid).ports[port].exists; } extern "C" std::uint64_t current_pid; -- 2.47.0