summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-06-28 17:03:08 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-28 22:29:28 +0200
commitb5aad1c81d1c11f506d5c0e71cc1f9c57642b6a4 (patch)
tree3ca41d26cca2fcc9d6d61d263d800ffc7e58fbbd /Kernel/Arch
parent04fc7d708c9079aa1556387e52c0b42be74eb6f3 (diff)
downloadserenity-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.h5
-rw-r--r--Kernel/Arch/x86/common/Processor.cpp1
-rw-r--r--Kernel/Arch/x86/x86_64/Processor.cpp9
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);