1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11/* Configuration for MultiBoot, see MultiBoot Specification: 12 www.gnu.org/software/grub/manual/multiboot 13 We use a flags field of 3, indicating that we want modules loaded on page 14 boundaries and access to the memory map information. We do not set bit 16, 15 indicating that the structure of the image should be taken from its ELF 16 headers. */ 17 18#include <config.h> 19#include <machine/assembler.h> 20 21.section .phys.text 22 23BEGIN_FUNC(enable_paging) 24 # Set PSE (bit 4) to enable 4M pages 25 movl %cr4, %eax 26 orl $0x10, %eax 27 movl %eax, %cr4 28 29 # Load the boot PD (or PDPT) address into CR3 30 leal _boot_pd, %eax 31 movl %eax, %cr3 32 33 # Enable caches by clearing bits 29 and 30 of CR0 34 # Enable paging by setting bit 31 of CR0 35 movl %cr0, %eax 36 andl $0x9fffffff, %eax 37 orl $0x80000000, %eax 38 movl %eax, %cr0 39 40 # Now that paging is enabled we can enable global pages 41 # Must be done in this sequence as per the intel manual 42 # Set PGE (bit 7) to enable global pages 43 movl %cr4, %eax 44 orl $0x80, %eax 45 movl %eax, %cr4 46 ret 47END_FUNC(enable_paging) 48 49/* ===== booting up first CPU ===== */ 50 51BEGIN_FUNC(_start) 52 /* Assume we are MultiBooted, e.g. by GRUB. 53 See MultiBoot Specification: www.gnu.org/software/grub/manual/multiboot 54 */ 55 56 movl %eax, %edi /* multiboot_magic */ 57 movl %ebx, %esi /* multiboot_info_ptr */ 58 59 /* Load kernel boot stack pointer */ 60 leal boot_stack_top, %esp 61 62 /* Reset EFLAGS register (also disables interrupts etc.) */ 63 pushl $0 64 popf 65 66 /* Push parameters to preserve for calling boot_sys later */ 67 pushl %esi /* 2nd parameter: multiboot_info_ptr */ 68 pushl %edi /* 1st parameter: multiboot_magic */ 69 70 /* Initialise boot PD and enable paging */ 71 call init_boot_pd 72 call enable_paging 73 74 popl %edi 75 popl %esi 76 77 /* Stop using shared boot stack and get a real stack and move to the top of the stack */ 78 leal kernel_stack_alloc + (1 << CONFIG_KERNEL_STACK_BITS) - 4, %esp 79 80 pushl %esi /* 2nd parameter: multiboot_info_ptr */ 81 pushl %edi /* 1st parameter: multiboot_magic */ 82 83 /* Call boot_sys() (takes 2 parameters) and set restore_user_context() as */ 84 /* return EIP. This will start the roottask as soon as boot_sys() returns. */ 85 pushl $restore_user_context 86 jmp boot_sys 87END_FUNC(_start) 88 89/* ===== booting up another CPU ===== */ 90#ifdef ENABLE_SMP_SUPPORT 91BEGIN_FUNC(boot_cpu_start) 92 93.code16 94 /* Set DS equal to CS and load GDTR register with GDT pointer */ 95 movw %cs, %ax 96 movw %ax, %ds 97 lgdt _boot_gdt_ptr - boot_cpu_start 98 99 /* Enable Protected Mode */ 100 movl %cr0, %eax 101 orl $1, %eax 102 movl %eax, %cr0 103 104 /* Reload CS with a far jump */ 105 ljmpl $0x08, $1f 106 107.code32 108 /* Load DS/ES/SS with kernel data segment selector */ 1091: movw $0x10, %ax 110 movw %ax, %ds 111 movw %ax, %es 112 movw %ax, %ss 113 114 /* Use temporary kernel boot stack pointer */ 115 leal boot_stack_top, %esp 116 117 /* Reset EFLAGS register (also disables interrupts etc.) */ 118 pushl $0 119 popf 120 121 /* Enable paging */ 122 call enable_paging 123 124 /* Get index of this cpu, BSP always gets index of zero */ 125 movl smp_aps_index, %ecx 126 127 /* Stop using shared boot stack and get a real stack and move to the top of the stack */ 128 leal kernel_stack_alloc, %esp 129 inc %ecx 130 shll $CONFIG_KERNEL_STACK_BITS, %ecx 131 addl %ecx, %esp 132 subl $4, %esp 133 134 /* Call boot_node() and set restore_user_context() as return EIP. */ 135 pushl $restore_user_context 136 jmp boot_node 137END_FUNC(boot_cpu_start) 138 139_boot_gdt_ptr: 140 .word (3 * 8) - 1 /* Limit: 3 segments * 8 bytes - 1 byte */ 141 .long _boot_gdt /* Address of boot GDT */ 142 143 .align 16 144_boot_gdt: 145 .quad 0x0000000000000000 /* Null segment */ 146 .quad 0x00cf9b000000ffff /* 4GB kernel code segment */ 147 .quad 0x00cf93000000ffff /* 4GB kernel data segment */ 148 149.global boot_cpu_end 150boot_cpu_end: 151 152#endif /* ENABLE_SMP_SUPPORT */ 153