diff --git a/arch/x86_64/src/gdt.rs b/arch/x86_64/src/gdt.rs index ed5cab9..96e1b99 100644 --- a/arch/x86_64/src/gdt.rs +++ b/arch/x86_64/src/gdt.rs @@ -11,8 +11,9 @@ pub const GDT_KERNEL_DATA: usize = 2; pub const GDT_KERNEL_TLS: usize = 3; pub const GDT_USER_CODE: usize = 4; pub const GDT_USER_DATA: usize = 5; -pub const GDT_TSS: usize = 6; -pub const GDT_TSS_HIGH: usize = 7; +pub const GDT_USER_TLS: usize = 6; +pub const GDT_TSS: usize = 7; +pub const GDT_TSS_HIGH: usize = 8; pub const GDT_A_PRESENT: u8 = 1 << 7; pub const GDT_A_RING_0: u8 = 0 << 5; @@ -55,7 +56,7 @@ pub static mut GDTR: DescriptorTablePointer = DescriptorTablePointer { }; #[thread_local] -pub static mut GDT: [GdtEntry; 8] = [ +pub static mut GDT: [GdtEntry; 9] = [ // Null GdtEntry::new(0, 0, 0, 0), // Kernel code @@ -68,6 +69,8 @@ pub static mut GDT: [GdtEntry; 8] = [ GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), // User data GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + // User TLS + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), // TSS GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0), // TSS must be 16 bytes long, twice the normal size @@ -113,6 +116,9 @@ pub unsafe fn init(tcb_offset: usize, stack_offset: usize) { // Set the TLS segment to the offset of the Thread Control Block GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32); + // Set the User TLS segment to the offset of the user TCB + GDT[GDT_USER_TLS].set_offset(::USER_TCB_OFFSET as u32); + // We can now access our TSS, which is a thread local GDT[GDT_TSS].set_offset(&TSS as *const _ as u32); GDT[GDT_TSS].set_limit(mem::size_of::() as u32); diff --git a/arch/x86_64/src/interrupt/syscall.rs b/arch/x86_64/src/interrupt/syscall.rs index cc44ea0..04cf5d2 100644 --- a/arch/x86_64/src/interrupt/syscall.rs +++ b/arch/x86_64/src/interrupt/syscall.rs @@ -24,8 +24,6 @@ pub unsafe extern fn syscall() { } asm!("push r15 - rdfsbase r15 - push r15 push fs mov r15, 0x18 mov fs, r15" @@ -35,8 +33,6 @@ pub unsafe extern fn syscall() { // Interrupt return asm!("pop fs - pop r15 - wrfsbase r15 pop r15 iretq" : : : : "intel", "volatile"); diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index a0224ba..032826c 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -48,6 +48,9 @@ pub extern crate x86; /// Offset to user image pub const USER_OFFSET: usize = 0; + /// Offset to user TCB + pub const USER_TCB_OFFSET: usize = 0xB000_0000; + /// Offset to user arguments pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2; @@ -118,8 +121,6 @@ macro_rules! interrupt { push r9 push r10 push r11 - rdfsbase rax - push rax push fs mov rax, 0x18 mov fs, ax" @@ -130,8 +131,6 @@ macro_rules! interrupt { // Pop scratch registers and return asm!("pop fs - pop rax - wrfsbase rax pop r11 pop r10 pop r9 @@ -184,8 +183,6 @@ macro_rules! interrupt_stack { push r9 push r10 push r11 - rdfsbase rax - push rax push fs mov rax, 0x18 mov fs, ax" @@ -200,8 +197,6 @@ macro_rules! interrupt_stack { // Pop scratch registers and return asm!("pop fs - pop rax - wrfsbase rax pop r11 pop r10 pop r9 diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index a9da113..55a3087 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -158,14 +158,13 @@ pub unsafe extern fn kstart_ap(cpu_id: usize, bsp_table: usize, stack_start: usi kmain_ap(cpu_id); } -pub unsafe fn usermode(ip: usize, sp: usize, fs: usize) -> ! { +pub unsafe fn usermode(ip: usize, sp: usize) -> ! { // Go to usermode asm!("xchg bx, bx mov ds, ax mov es, ax - mov fs, ax + mov fs, bx mov gs, ax - wrfsbase rbx push rax push rcx push rdx @@ -174,7 +173,7 @@ pub unsafe fn usermode(ip: usize, sp: usize, fs: usize) -> ! { iretq" : // No output because it never returns : "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment - "{rbx}"(fs), // TLS segment + "{rbx}"(gdt::GDT_USER_TLS << 3 | 3), // TLS segment "{rcx}"(sp), // Stack pointer "{rdx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag "{rsi}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment diff --git a/bootloader/x86_64/startup-x86_64.asm b/bootloader/x86_64/startup-x86_64.asm index f3abdf9..6059331 100644 --- a/bootloader/x86_64/startup-x86_64.asm +++ b/bootloader/x86_64/startup-x86_64.asm @@ -26,9 +26,9 @@ startup_ap: mov edi, 0x70000 mov cr3, edi - ;enable FSGSBASE, FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension + ;enable FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension mov eax, cr4 - or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 + or eax, 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 mov cr4, eax ; load protected mode GDT @@ -91,9 +91,9 @@ startup_arch: mov edi, 0x70000 mov cr3, edi - ;enable FSGSBASE, FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension + ;enable FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension mov eax, cr4 - or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 + or eax, 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 mov cr4, eax ; load protected mode GDT diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 39309cf..16dd015 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -448,7 +448,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { let entry; let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256; - let fs = arch::USER_STACK_OFFSET; { let mut args = Vec::new(); @@ -555,6 +554,18 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { context.image.push(memory.to_shared()); } else if segment.p_type == program_header::PT_TLS { + let memory = context::memory::Memory::new( + VirtualAddress::new(arch::USER_TCB_OFFSET), + 4096, + entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, + true, + true + ); + + unsafe { *(arch::USER_TCB_OFFSET as *mut usize) = arch::USER_TLS_OFFSET + segment.p_memsz as usize; } + + context.image.push(memory.to_shared()); + tls_option = Some(( VirtualAddress::new(segment.p_vaddr as usize), segment.p_filesz as usize, @@ -602,10 +613,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { file_size); } - // Set TLS pointer - //TODO: Do not use stack to store TLS pointer, use a TCB structure instead - unsafe { *(arch::USER_STACK_OFFSET as *mut usize) = tls.mem.start_address().get() + size; } - context.tls = Some(tls); } @@ -672,7 +679,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { } // Go to usermode - unsafe { usermode(entry, sp, fs); } + unsafe { usermode(entry, sp); } } pub fn exit(status: usize) -> ! {