diff --git a/arch/x86_64/src/context.rs b/arch/x86_64/src/context.rs new file mode 100644 index 0000000..8818118 --- /dev/null +++ b/arch/x86_64/src/context.rs @@ -0,0 +1,72 @@ +pub struct Context { + flags: usize, + bx: usize, + r12: usize, + r13: usize, + r14: usize, + r15: usize, + bp: usize, + sp: usize, + cr3: usize +} + +impl Context { + pub fn new() -> Context { + Context { + flags: 0, + bx: 0, + r12: 0, + r13: 0, + r14: 0, + r15: 0, + bp: 0, + sp: 0, + cr3: 0 + } + } + + #[inline(never)] + #[naked] + pub unsafe fn switch_to(&mut self, next: &mut Context) { + asm!("xchg bx, bx" : : : "memory" : "intel", "volatile"); + +/* + asm!("fxsave [$0]" : : "r"(self.fx) : "memory" : "intel", "volatile"); + self.loadable = true; + if next.loadable { + asm!("fxrstor [$0]" : : "r"(next.fx) : "memory" : "intel", "volatile"); + }else{ + asm!("fninit" : : : "memory" : "intel", "volatile"); + } +*/ + + asm!("pushfq ; pop $0" : "=r"(self.flags) : : "memory" : "intel", "volatile"); + asm!("push $0 ; popfq" : : "r"(next.flags) : "memory" : "intel", "volatile"); + + asm!("mov $0, rbx" : "=r"(self.bx) : : "memory" : "intel", "volatile"); + asm!("mov rbx, $0" : : "r"(next.bx) : "memory" : "intel", "volatile"); + + asm!("mov $0, r12" : "=r"(self.r12) : : "memory" : "intel", "volatile"); + asm!("mov r12, $0" : : "r"(next.r12) : "memory" : "intel", "volatile"); + + asm!("mov $0, r13" : "=r"(self.r13) : : "memory" : "intel", "volatile"); + asm!("mov r13, $0" : : "r"(next.r13) : "memory" : "intel", "volatile"); + + asm!("mov $0, r14" : "=r"(self.r14) : : "memory" : "intel", "volatile"); + asm!("mov r14, $0" : : "r"(next.r14) : "memory" : "intel", "volatile"); + + asm!("mov $0, r15" : "=r"(self.r15) : : "memory" : "intel", "volatile"); + asm!("mov r15, $0" : : "r"(next.r15) : "memory" : "intel", "volatile"); + + asm!("mov $0, rbp" : "=r"(self.bp) : : "memory" : "intel", "volatile"); + asm!("mov rbp, $0" : : "r"(next.bp) : "memory" : "intel", "volatile"); + + asm!("mov $0, rsp" : "=r"(self.sp) : : "memory" : "intel", "volatile"); + asm!("mov rsp, $0" : : "r"(next.sp) : "memory" : "intel", "volatile"); + + /* TODO + asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile"); + asm!("mov cr3, $0" : : "r"(self.cr3) : "memory" : "intel", "volatile"); + */ + } +} diff --git a/arch/x86_64/src/gdt.rs b/arch/x86_64/src/gdt.rs index 7ef3450..b100e90 100644 --- a/arch/x86_64/src/gdt.rs +++ b/arch/x86_64/src/gdt.rs @@ -107,6 +107,7 @@ pub unsafe fn init_ap(tcb_offset: usize, stack_offset: usize) { // Load the initial GDT, before we have access to thread locals dtables::lgdt(&INIT_GDTR); + // Load the segment descriptors segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16)); segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16)); segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16)); @@ -131,6 +132,14 @@ pub unsafe fn init_ap(tcb_offset: usize, stack_offset: usize) { // Load the new GDT, which is correctly located in thread local storage dtables::lgdt(&GDTR); + // Reload the segment descriptors + segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16)); + segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16)); + segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16)); + segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16)); + segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16)); + segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16)); + // Load the task register task::load_ltr(SegmentSelector::new(GDT_TSS as u16)); } diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index eaa0e5b..2bb0cb9 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -121,6 +121,9 @@ macro_rules! interrupt_error { /// ACPI table parsing pub mod acpi; +/// Context switching +pub mod context; + /// Memcpy, memmove, etc. pub mod externs; diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index 08b2113..bb35b84 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -105,7 +105,6 @@ pub unsafe extern fn kstart() -> ! { { let index = heap_start_page.p4_index(); - println!("HEAP: {} {} {} {}", index, heap_start_page.p3_index(), heap_start_page.p2_index(), heap_start_page.p1_index()); assert_eq!(index, heap_end_page.p4_index()); let frame = memory::allocate_frame().expect("no frames available"); diff --git a/bootloader/x86/startup-x86_64.asm b/bootloader/x86/startup-x86_64.asm index bd5a6db..95c01e2 100644 --- a/bootloader/x86/startup-x86_64.asm +++ b/bootloader/x86/startup-x86_64.asm @@ -103,8 +103,6 @@ startup_arch: or ebx, 1 << 31 | 1 << 16 | 1 ;Bit 31: Paging, Bit 16: write protect kernel, Bit 0: Protected Mode mov cr0, ebx - xchg bx, bx - ; far jump to enable Long Mode and load CS with 64 bit segment jmp gdt.kernel_code:long_mode