diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-06-28 17:03:08 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-28 22:29:28 +0200 |
commit | b5aad1c81d1c11f506d5c0e71cc1f9c57642b6a4 (patch) | |
tree | 3ca41d26cca2fcc9d6d61d263d800ffc7e58fbbd /Kernel/Arch | |
parent | 04fc7d708c9079aa1556387e52c0b42be74eb6f3 (diff) | |
download | serenity-b5aad1c81d1c11f506d5c0e71cc1f9c57642b6a4.zip |
Kernel: Fix GDT and segment selectors to make userland work on x86_64
Userland faulted on the very first instruction before because the
PML4T/PDPT/etc. weren't marked as user-accessible. For some reason
x86 doesn't care about that.
Also, we need to provide an appropriate userspace stack segment
selector to iretq.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r-- | Kernel/Arch/x86/DescriptorTable.h | 5 | ||||
-rw-r--r-- | Kernel/Arch/x86/common/Processor.cpp | 1 | ||||
-rw-r--r-- | Kernel/Arch/x86/x86_64/Processor.cpp | 9 |
3 files changed, 11 insertions, 4 deletions
diff --git a/Kernel/Arch/x86/DescriptorTable.h b/Kernel/Arch/x86/DescriptorTable.h index 51585279a3..907dd5f998 100644 --- a/Kernel/Arch/x86/DescriptorTable.h +++ b/Kernel/Arch/x86/DescriptorTable.h @@ -28,8 +28,9 @@ static_assert(GDT_SELECTOR_CODE0 + 24 == GDT_SELECTOR_DATA3); // SS3 = CS0 + 32 #else # define GDT_SELECTOR_CODE0 0x08 # define GDT_SELECTOR_CODE3 0x10 -# define GDT_SELECTOR_TSS 0x18 -# define GDT_SELECTOR_TSS_PART2 0x20 +# define GDT_SELECTOR_DATA3 0x18 +# define GDT_SELECTOR_TSS 0x20 +# define GDT_SELECTOR_TSS_PART2 0x28 #endif namespace Kernel { diff --git a/Kernel/Arch/x86/common/Processor.cpp b/Kernel/Arch/x86/common/Processor.cpp index 48b9bbef7b..f608713c78 100644 --- a/Kernel/Arch/x86/common/Processor.cpp +++ b/Kernel/Arch/x86/common/Processor.cpp @@ -1070,6 +1070,7 @@ UNMAP_AFTER_INIT void Processor::gdt_init() #else write_raw_gdt_entry(GDT_SELECTOR_CODE0, 0x0000ffff, 0x00af9a00); // code0 write_raw_gdt_entry(GDT_SELECTOR_CODE3, 0x0000ffff, 0x00affa00); // code3 + write_raw_gdt_entry(GDT_SELECTOR_DATA3, 0x0000ffff, 0x008ff200); // data3 #endif #if ARCH(I386) diff --git a/Kernel/Arch/x86/x86_64/Processor.cpp b/Kernel/Arch/x86/x86_64/Processor.cpp index 104202cb95..00fd7a25eb 100644 --- a/Kernel/Arch/x86/x86_64/Processor.cpp +++ b/Kernel/Arch/x86/x86_64/Processor.cpp @@ -115,8 +115,13 @@ u32 Processor::init_context(Thread& thread, bool leave_crit) iretframe.rflags = regs.rflags; iretframe.rip = regs.rip; iretframe.cs = regs.cs; - iretframe.userspace_rsp = kernel_stack_top; - iretframe.userspace_ss = 0; + if (return_to_user) { + iretframe.userspace_rsp = regs.rsp; + iretframe.userspace_ss = GDT_SELECTOR_DATA3 | 3; + } else { + iretframe.userspace_rsp = kernel_stack_top; + iretframe.userspace_ss = 0; + } // make space for a trap frame stack_top -= sizeof(TrapFrame); |