1e5fc2bfcSAlex Smith/* 2e5fc2bfcSAlex Smith * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 3e5fc2bfcSAlex Smith * Distributed under the terms of the MIT License. 4e5fc2bfcSAlex Smith */ 5e5fc2bfcSAlex Smith 6e5fc2bfcSAlex Smith 7e5fc2bfcSAlex Smith#include <asm_defs.h> 8e5fc2bfcSAlex Smith 9c005e747SAlex Smith#define __x86_64__ 10c005e747SAlex Smith#include <arch/x86/descriptors.h> 11527da4caSPawel Dziepak 12527da4caSPawel Dziepak#include "mmu.h" 13c005e747SAlex Smith#undef __x86_64__ 14e5fc2bfcSAlex Smith 15e5fc2bfcSAlex Smith 160da10c8bSAlex Smith#define GDT_LIMIT 0x800 170da10c8bSAlex Smith 180da10c8bSAlex Smith 19e5fc2bfcSAlex Smith.code32 20e5fc2bfcSAlex Smith 21e5fc2bfcSAlex Smith 2276a1175dSAlex Smith/*! void long_enter_kernel(int currentCPU, uint64 stackTop); */ 23e5fc2bfcSAlex SmithFUNCTION(long_enter_kernel): 2476a1175dSAlex Smith // Preserve the arguments. We may no longer be able to use the stack once 2576a1175dSAlex Smith // paging is disabled. 2676a1175dSAlex Smith movl 4(%esp), %ebx 2776a1175dSAlex Smith movl 8(%esp), %edi 2876a1175dSAlex Smith movl 12(%esp), %esi 2976a1175dSAlex Smith 30*1f8a8d2bSJérôme Duval movl gLongLA57, %ecx 31*1f8a8d2bSJérôme Duval shl $12, %ecx 32*1f8a8d2bSJérôme Duval 33e5fc2bfcSAlex Smith // Currently running with 32-bit paging tables at an identity mapped 34e5fc2bfcSAlex Smith // address. To switch to 64-bit paging we must first disable 32-bit paging, 35e5fc2bfcSAlex Smith // otherwise loading the new CR3 will fault. 36e5fc2bfcSAlex Smith movl %cr0, %eax 37e5fc2bfcSAlex Smith andl $~(1 << 31), %eax 38e5fc2bfcSAlex Smith movl %eax, %cr0 39e5fc2bfcSAlex Smith 40*1f8a8d2bSJérôme Duval // Enable PAE and PGE, and optionally LA57 41e5fc2bfcSAlex Smith movl %cr4, %eax 4240aeaeb9SAlex Smith orl $(1 << 5) | (1 << 7), %eax 43*1f8a8d2bSJérôme Duval orl %ecx, %eax 44e5fc2bfcSAlex Smith movl %eax, %cr4 45e5fc2bfcSAlex Smith 46*1f8a8d2bSJérôme Duval // Point CR3 to the kernel's PMLTop. 47*1f8a8d2bSJérôme Duval movl gLongPhysicalPMLTop, %eax 48e5fc2bfcSAlex Smith movl %eax, %cr3 49e5fc2bfcSAlex Smith 50e5fc2bfcSAlex Smith // Enable long mode by setting EFER.LME. 5176a1175dSAlex Smith movl $0xc0000080, %ecx 52e5fc2bfcSAlex Smith rdmsr 53e5fc2bfcSAlex Smith orl $(1 << 8), %eax 54e5fc2bfcSAlex Smith wrmsr 55e5fc2bfcSAlex Smith 56e5fc2bfcSAlex Smith // Re-enable paging, which will put us in compatibility mode as we are 57e5fc2bfcSAlex Smith // currently in a 32-bit code segment. 58e5fc2bfcSAlex Smith movl %cr0, %ecx 59e5fc2bfcSAlex Smith orl $(1 << 31), %ecx 60e5fc2bfcSAlex Smith movl %ecx, %cr0 61e5fc2bfcSAlex Smith 62527da4caSPawel Dziepak // Load 64-bit enabled GDT 63527da4caSPawel Dziepak lgdtl long_gdtr 64527da4caSPawel Dziepak 65e5fc2bfcSAlex Smith // Jump into the 64-bit code segment. 66611376feSPawel Dziepak ljmp $KERNEL_CODE_SELECTOR, $.Llmode 67e5fc2bfcSAlex Smith.align 8 68e5fc2bfcSAlex Smith.code64 69e5fc2bfcSAlex Smith.Llmode: 70e5fc2bfcSAlex Smith // Set data segments. 71611376feSPawel Dziepak mov $KERNEL_DATA_SELECTOR, %ax 72e5fc2bfcSAlex Smith mov %ax, %ss 7303add8e7SAlex Smith xor %ax, %ax 74e5fc2bfcSAlex Smith mov %ax, %ds 75e5fc2bfcSAlex Smith mov %ax, %es 76e5fc2bfcSAlex Smith mov %ax, %fs 77e5fc2bfcSAlex Smith mov %ax, %gs 78e5fc2bfcSAlex Smith 7976a1175dSAlex Smith // Set the stack pointer. 8076a1175dSAlex Smith movl %edi, %esp 8176a1175dSAlex Smith shl $32, %rsi 8276a1175dSAlex Smith orq %rsi, %rsp 83e5fc2bfcSAlex Smith 84e5fc2bfcSAlex Smith // Clear the stack frame/RFLAGS. 85e5fc2bfcSAlex Smith xorq %rbp, %rbp 86e5fc2bfcSAlex Smith push $0 87e5fc2bfcSAlex Smith popf 88e5fc2bfcSAlex Smith 8976a1175dSAlex Smith // Get arguments and call the kernel entry point. 9076a1175dSAlex Smith leaq gKernelArgs(%rip), %rdi 9176a1175dSAlex Smith movl %ebx, %esi 9276a1175dSAlex Smith movq gLongKernelEntry(%rip), %rax 93e5fc2bfcSAlex Smith call *%rax 940da10c8bSAlex Smith 950da10c8bSAlex Smith 960da10c8bSAlex Smith.data 970da10c8bSAlex Smith 980da10c8bSAlex Smith 99527da4caSPawel Dziepaklong_gdtr: 100527da4caSPawel Dziepak .word BOOT_GDT_SEGMENT_COUNT * 8 - 1 101527da4caSPawel DziepakSYMBOL(gLongGDT): 10276a1175dSAlex Smith .long 0 10376a1175dSAlex Smith 104*1f8a8d2bSJérôme DuvalSYMBOL(gLongPhysicalPMLTop): 105*1f8a8d2bSJérôme Duval .long 0 106*1f8a8d2bSJérôme Duval 107*1f8a8d2bSJérôme DuvalSYMBOL(gLongLA57): 10876a1175dSAlex Smith .long 0 10976a1175dSAlex Smith 11076a1175dSAlex SmithSYMBOL(gLongKernelEntry): 1110da10c8bSAlex Smith .quad 0 112