diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 60bcdcf744..2a942df653 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -104,7 +104,7 @@ long_mmu_init() // Allocate the top level PML4. pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir); memset(pml4, 0, B_PAGE_SIZE); - gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4; + gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pml4); // Find the highest physical memory address. We map all physical memory // into the kernel address space, so we want to make sure we map everything @@ -319,14 +319,11 @@ long_start_kernel() // We're about to enter the kernel -- disable console output. stdout = NULL; - // Load the new GDT. The physical address is used because long_enter_kernel - // disables 32-bit paging. - gdt_idt_descr gdtr = { GDT_LIMIT - 1, gKernelArgs.arch_args.phys_gdt }; - asm volatile("lgdt %0" :: "m"(gdtr)); - // Enter the kernel! - long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, entry, stackTop, - kernelArgs, 0); + long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, + gKernelArgs.arch_args.phys_gdt, gKernelArgs.arch_args.vir_gdt, + entry, stackTop, kernelArgs, 0); + panic("Shouldn't get here"); } diff --git a/src/system/boot/platform/bios_ia32/long.h b/src/system/boot/platform/bios_ia32/long.h index de2a0392c7..084b5b36e8 100644 --- a/src/system/boot/platform/bios_ia32/long.h +++ b/src/system/boot/platform/bios_ia32/long.h @@ -9,8 +9,9 @@ #include -extern "C" void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, - uint64 kernelArgs, int currentCPU); +extern "C" void long_enter_kernel(uint32 physPML4, uint32 physGDT, + uint64 virtGDT, uint64 entry, uint64 stackTop, uint64 kernelArgs, + int currentCPU); extern void long_start_kernel(); diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 43be6af4cd..30bfd2be02 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -11,13 +11,22 @@ #undef __x86_64__ +#define GDT_LIMIT 0x800 + + .code32 -/*! void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, - uint64 kernelArgs, int currentCPU); +/*! void long_enter_kernel(uint32 physPML4, uint32 physGDT, uint64 virtGDT, + uint64 entry, uint64 stackTop, uint64 kernelArgs, int currentCPU); */ FUNCTION(long_enter_kernel): + // We're about to disable paging, so we need to load the the physical + // address of our GDT. + movl 8(%esp), %eax + movl %eax, (long_gdtr + 2) + lgdtl (long_gdtr) + // Currently running with 32-bit paging tables at an identity mapped // address. To switch to 64-bit paging we must first disable 32-bit paging, // otherwise loading the new CR3 will fault. @@ -62,11 +71,16 @@ FUNCTION(long_enter_kernel): // Clear the high 32 bits of RSP. movl %esp, %esp + // Load the virtual address of the GDT. + movq 12(%rsp), %rax + movq %rax, long_gdtr + 2(%rip) + lgdtq long_gdtr(%rip) + // Get the entry point address, arguments and new stack pointer. - movq 8(%rsp), %rax - movq 24(%rsp), %rdi - movl 32(%rsp), %esi - movq 16(%rsp), %rsp + movq 20(%rsp), %rax + movq 36(%rsp), %rdi + movl 44(%rsp), %esi + movq 28(%rsp), %rsp // Clear the stack frame/RFLAGS. xorq %rbp, %rbp @@ -75,3 +89,11 @@ FUNCTION(long_enter_kernel): // Call the kernel entry point. call *%rax + + +.data + + +long_gdtr: + .word GDT_LIMIT - 1 + .quad 0