1/* 2 * Copyright (c) 2009 Corey Tabaka 3 * Copyright (c) 2015 Intel Corporation 4 * Copyright (c) 2016 Travis Geiselbrecht 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files 8 * (the "Software"), to deal in the Software without restriction, 9 * including without limitation the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25#include <asm.h> 26#include <arch/x86/descriptor.h> 27#include <arch/x86/mmu.h> 28 29/* The magic number for the Multiboot header. */ 30#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 31 32/* The flags for the Multiboot header. */ 33#if defined(__ELF__) && 0 34#define MULTIBOOT_HEADER_FLAGS 0x00000002 35#else 36#define MULTIBOOT_HEADER_FLAGS 0x00010002 37#endif 38 39/* The magic number passed by a Multiboot-compliant boot loader. */ 40#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 41 42#define PHYS_LOAD_ADDRESS (MEMBASE + KERNEL_LOAD_OFFSET) 43#define PHYS_ADDR_DELTA (KERNEL_BASE + KERNEL_LOAD_OFFSET - PHYS_LOAD_ADDRESS) 44#define PHYS(x) ((x) - PHYS_ADDR_DELTA) 45 46.section ".text.boot" 47.global _start 48_start: 49 jmp real_start 50 51.align 4 52 53.type multiboot_header,STT_OBJECT 54multiboot_header: 55 /* magic */ 56 .int MULTIBOOT_HEADER_MAGIC 57 /* flags */ 58 .int MULTIBOOT_HEADER_FLAGS 59 /* checksum */ 60 .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) 61 62#if !defined(__ELF__) || 1 63 /* header_addr */ 64 .int PHYS(multiboot_header) 65 /* load_addr */ 66 .int PHYS(_start) 67 /* load_end_addr */ 68 .int PHYS(__data_end) 69 /* bss_end_addr */ 70 .int PHYS(__bss_end) 71 /* entry_addr */ 72 .int PHYS(real_start) 73#endif 74 75real_start: 76 cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax 77 jne 0f 78 movl %ebx, PHYS(_multiboot_info) 79 800: 81 /* load our new gdt by physical pointer */ 82 lgdt PHYS(_gdtr_phys) 83 84 movw $DATA_SELECTOR, %ax 85 movw %ax, %ds 86 movw %ax, %es 87 movw %ax, %fs 88 movw %ax, %ss 89 movw %ax, %gs 90 movw %ax, %ss 91 92 /* load initial stack pointer */ 93 movl $PHYS(_kstack + 4096), %esp 94 95 /*We jumped here in protected mode in a code segment that migh not longer 96 be valid , do a long jump to our code segment, we use retf instead of 97 ljmp to be able to use relative labels */ 98 pushl $CODE_SELECTOR /*Pushing our code segment */ 99 pushl $PHYS(.Lfarjump) /*and jump address */ 100 retf /*This instruction will jump to codesel:farjump */ 101 102.Lfarjump: 103 104 /* zero the bss section */ 105bss_setup: 106 movl $PHYS(__bss_start), %edi /* starting address of the bss */ 107 movl $PHYS(__bss_end), %ecx /* find the length of the bss in bytes */ 108 subl %edi, %ecx 109 shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */ 1102: 111 movl $0, (%edi) 112 addl $4, %edi 113 loop 2b 114 115paging_setup: 116#ifdef PAE_MODE_ENABLED 117#error broken for now 118 /* Preparing PAE paging, we will use 2MB pages covering 1GB 119 for initial bootstrap, this page table will be 1 to 1 */ 120 121 /* Setting the First PDPTE with a PD table reference*/ 122 movl $pdp, %eax 123 orl $0x01, %eax 124 movl %eax, (pdpt) 125 126 movl $pdp, %esi 127 movl $0x1ff, %ecx 128 129fill_pdp: 130 movl $0x1ff, %eax 131 subl %ecx, %eax 132 shll $21,%eax 133 orl $0x83, %eax 134 movl %eax, (%esi) 135 addl $8,%esi 136 loop fill_pdp 137 138 /* Set PDPT in CR3 */ 139 movl $pdpt, %eax 140 mov %eax, %cr3 141 142 /* Enabling PAE*/ 143 mov %cr4, %eax 144 btsl $(5), %eax 145 mov %eax, %cr4 146 147 /* Enabling Paging and from this point we are in 148 32 bit compatibility mode */ 149 mov %cr0, %eax 150 btsl $(31), %eax 151 mov %eax, %cr0 152 153#else 154 /* map the first 1GB 1:1 */ 155 movl $PHYS(pd), %esi 156 movl $0x100, %ecx 157 xor %eax, %eax 158 159.Lfill_pd: 160 mov %eax, %edx 161 orl $X86_KERNEL_PD_LP_FLAGS, %edx 162 movl %edx, (%esi) 163 addl $4, %esi 164 addl $0x00400000, %eax 165 loop .Lfill_pd 166 167 /* map the first 1GB to KERNEL_ASPACE_BASE */ 168 movl $(PHYS(pd) + 0x800), %esi 169 movl $0x100, %ecx 170 xor %eax, %eax 171 172.Lfill_pd2: 173 mov %eax, %edx 174 orl $X86_KERNEL_PD_LP_FLAGS, %edx 175 movl %edx, (%esi) 176 addl $4, %esi 177 addl $0x00400000, %eax 178 loop .Lfill_pd2 179 180 /* Set PD in CR3 */ 181 movl $PHYS(pd), %eax 182 mov %eax, %cr3 183 184 /* Enabling Paging and from this point we are in */ 185 mov %cr4, %eax 186 orl $0x10, %eax 187 mov %eax, %cr4 188 189 mov %cr0, %eax 190 btsl $(31), %eax 191 mov %eax, %cr0 192#endif 193 194 /* load the high kernel stack */ 195 movl $(_kstack + 4096), %esp 196 197 /* reload the high gdtr */ 198 lgdt PHYS(_gdtr) 199 200 /* branch to the high address */ 201 movl $main_lk, %eax 202 jmp *%eax 203 204main_lk: 205 /* set up the idt */ 206 call setup_idt 207 208 /* call the main module */ 209 call lk_main 2100: /* just sit around waiting for interrupts */ 211 hlt /* interrupts will unhalt the processor */ 212 pause 213 jmp 0b /* so jump back to halt to conserve power */ 214