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