/* entry.S * * Copyright (c) 2013 Brian Swetland * Modified by Nexoniarz * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #define mboot_magic 0x1badb002 #define mboot_flags 0x00010000 #include "mmu.h" .code64 .global mboot_header .global mboot_entry mboot_header: .long mboot_magic .long mboot_flags .long (-mboot_magic -mboot_flags) .long mboot_load_addr .long mboot_load_addr .long mboot_load_end .long mboot_bss_end .long mboot_entry_addr .code32 mboot_entry: mov %eax, %ebp # bootstrap page tables (0x1000 - 0x3000) xor %eax, %eax mov $0x1000, %edi mov $0x2000, %ecx rep stosb # Bootstrap page tables (Identity mapping 4GB) # PML4T[0] i PML4T[256] -> PDPT pod 0x2000 mov $(0x2000 | PTE_P | PTE_W), %edx mov %edx, 0x1000 mov %edx, 0x1800 # PDPT mapping 4GB using 1GB huge pages mov $(0x00000000 | PTE_P | PTE_PS | PTE_W), %edx mov %edx, 0x2000 mov $(0x40000000 | PTE_P | PTE_PS | PTE_W), %edx mov %edx, 0x2008 mov $(0x80000000 | PTE_P | PTE_PS | PTE_W), %edx mov %edx, 0x2010 mov $(0xC0000000 | PTE_P | PTE_PS | PTE_W), %edx mov %edx, 0x2018 mov %ebp, %ebx .global entry32mp entry32mp: mov $0x1000, %eax mov %eax, %cr3 lgdt (gdtr64 - mboot_header + mboot_load_addr) mov %cr4, %eax bts $5, %eax mov %eax, %cr4 mov $MSR_EFER, %ecx rdmsr bts $0, %eax bts $8, %eax wrmsr mov %cr0, %eax orl $(CR0_PG | CR0_WP | CR0_MP), %eax mov %eax, %cr0 ljmp $8, $(entry64low - mboot_header + mboot_load_addr) .align 16 gdtr64: .word gdt64_end - gdt64_begin - 1; .quad gdt64_begin - mboot_header + mboot_load_addr .align 16 gdt64_begin: .long 0x00000000 .long 0x00000000 .long 0x00000000 # 64-bit code .long 0x00209800 .long 0x00000000 # 64-bit data .long 0x00009000 gdt64_end: .align 16 .code64 entry64low: movabs $entry64high, %rax jmp *%rax .global _start _start: entry64high: xor %rax, %rax mov %ax, %ss mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs # Is this an application processor, or the boot processor? # # This check used to be a comment saying it had not been written yet, and # every AP fell straight through into the BSP path below: it set RSP to the # *boot processor's* stack, passed its own flag to kmain() as a framebuffer # address, and re-ran the entire bootstrap -- e820_init, kinit1, kvmalloc -- # on a second core sharing one stack with the first. That is the SMP triple # fault. QEMU hid it for years by never reporting more than one CPU (see # kernel/arch/x86_64/acpi.c); VMware did not. # # EBX is the discriminator, and entryother.S sets it to 1 immediately before # entering long mode for exactly this purpose. It is safe: on the boot # processor EBX carries the VESA framebuffer address from the loader, which is # either zero or a physical MMIO address, and can never be 1. cmp $1, %ebx je entry64mp # Setup initial stack movabs $0xFFFF800000010000, %rax mov %rax, %rsp # Pass VESA address to main (1st argument in RDI) mov %rbx, %rdi call kmain .global __deadloop __deadloop: jmp . entry64mp: mov $0x7000, %rax mov -16(%rax), %rsp jmp mpenter .global wrmsr wrmsr: mov %rdi, %rcx mov %rsi, %rax shr $32, %rsi mov %rsi, %rdx wrmsr retq .global ignore_sysret ignore_sysret: mov $-38, %rax sysretq