1 1.11 maxv /* $NetBSD: locore.S,v 1.11 2019/03/19 19:15:57 maxv Exp $ */ 2 1.1 maxv 3 1.1 maxv /* 4 1.1 maxv * Copyright (c) 1998, 2000, 2007, 2008, 2016, 2017 The NetBSD Foundation, Inc. 5 1.1 maxv * All rights reserved. 6 1.1 maxv * 7 1.1 maxv * This code is derived from software contributed to The NetBSD Foundation 8 1.1 maxv * by Charles M. Hannum and by Maxime Villard. 9 1.1 maxv * 10 1.1 maxv * Redistribution and use in source and binary forms, with or without 11 1.1 maxv * modification, are permitted provided that the following conditions 12 1.1 maxv * are met: 13 1.1 maxv * 1. Redistributions of source code must retain the above copyright 14 1.1 maxv * notice, this list of conditions and the following disclaimer. 15 1.1 maxv * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 maxv * notice, this list of conditions and the following disclaimer in the 17 1.1 maxv * documentation and/or other materials provided with the distribution. 18 1.1 maxv * 19 1.1 maxv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 maxv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 maxv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 maxv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 maxv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 maxv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 maxv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 maxv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 maxv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 maxv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 maxv * POSSIBILITY OF SUCH DAMAGE. 30 1.1 maxv */ 31 1.1 maxv 32 1.1 maxv #define _LOCORE 33 1.1 maxv 34 1.1 maxv /* Override user-land alignment before including asm.h */ 35 1.1 maxv #define ALIGN_DATA .align 8 36 1.1 maxv #define ALIGN_TEXT .align 16,0x90 37 1.1 maxv #define _ALIGN_TEXT ALIGN_TEXT 38 1.1 maxv 39 1.1 maxv #include <machine/asm.h> 40 1.1 maxv #include <machine/param.h> 41 1.1 maxv #include <machine/pte.h> 42 1.1 maxv #include <machine/psl.h> 43 1.1 maxv #include <machine/segments.h> 44 1.1 maxv #include <machine/specialreg.h> 45 1.1 maxv #include <machine/trap.h> 46 1.1 maxv 47 1.1 maxv #define _KERNEL 48 1.1 maxv #include <machine/bootinfo.h> 49 1.1 maxv #undef _KERNEL 50 1.1 maxv 51 1.1 maxv #include "pdir.h" 52 1.1 maxv #include "redef.h" 53 1.1 maxv 54 1.10 maxv /* 32bit version of PTE_NX */ 55 1.10 maxv #define PTE_NX32 0x80000000 56 1.1 maxv 57 1.1 maxv #define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1) 58 1.1 maxv #define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES 59 1.1 maxv 60 1.1 maxv #define PROC0_PML4_OFF 0 61 1.1 maxv #define PROC0_STK_OFF (PROC0_PML4_OFF + 1 * PAGE_SIZE) 62 1.1 maxv #define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * PAGE_SIZE) 63 1.1 maxv #define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * PAGE_SIZE) 64 1.1 maxv #define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * PAGE_SIZE) 65 1.1 maxv #define TABLESIZE \ 66 1.1 maxv ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES) \ 67 1.1 maxv * PAGE_SIZE) 68 1.1 maxv 69 1.1 maxv /* 70 1.1 maxv * fillkpt - Fill in a kernel page table 71 1.1 maxv * eax = pte (page frame | control | status) 72 1.1 maxv * ebx = page table address 73 1.1 maxv * ecx = number of pages to map 74 1.1 maxv * 75 1.1 maxv * Each entry is 8 (PDE_SIZE) bytes long: we must set the 4 upper bytes to 0. 76 1.1 maxv */ 77 1.1 maxv #define fillkpt \ 78 1.1 maxv cmpl $0,%ecx ; /* zero-sized? */ \ 79 1.1 maxv je 2f ; \ 80 1.1 maxv 1: movl $0,(PDE_SIZE-4)(%ebx) ; /* upper 32 bits: 0 */ \ 81 1.1 maxv movl %eax,(%ebx) ; /* store phys addr */ \ 82 1.1 maxv addl $PDE_SIZE,%ebx ; /* next PTE/PDE */ \ 83 1.1 maxv addl $PAGE_SIZE,%eax ; /* next phys page */ \ 84 1.1 maxv loop 1b ; \ 85 1.1 maxv 2: ; 86 1.1 maxv 87 1.1 maxv /* 88 1.1 maxv * fillkpt_nox - Same as fillkpt, but sets the NX/XD bit. 89 1.1 maxv */ 90 1.1 maxv #define fillkpt_nox \ 91 1.1 maxv cmpl $0,%ecx ; /* zero-sized? */ \ 92 1.1 maxv je 2f ; \ 93 1.1 maxv pushl %ebp ; \ 94 1.1 maxv movl _C_LABEL(nox_flag),%ebp ; \ 95 1.1 maxv 1: movl %ebp,(PDE_SIZE-4)(%ebx) ; /* upper 32 bits: NX */ \ 96 1.1 maxv movl %eax,(%ebx) ; /* store phys addr */ \ 97 1.1 maxv addl $PDE_SIZE,%ebx ; /* next PTE/PDE */ \ 98 1.1 maxv addl $PAGE_SIZE,%eax ; /* next phys page */ \ 99 1.1 maxv loop 1b ; \ 100 1.1 maxv popl %ebp ; \ 101 1.1 maxv 2: ; 102 1.1 maxv 103 1.1 maxv /* 104 1.1 maxv * fillkpt_blank - Fill in a kernel page table with blank entries 105 1.1 maxv * ebx = page table address 106 1.1 maxv * ecx = number of pages to map 107 1.1 maxv */ 108 1.1 maxv #define fillkpt_blank \ 109 1.1 maxv cmpl $0,%ecx ; /* zero-sized? */ \ 110 1.1 maxv je 2f ; \ 111 1.1 maxv 1: movl $0,(PDE_SIZE-4)(%ebx) ; /* upper 32 bits: 0 */ \ 112 1.1 maxv movl $0,(%ebx) ; /* lower 32 bits: 0 */ \ 113 1.1 maxv addl $PDE_SIZE,%ebx ; /* next PTE/PDE */ \ 114 1.1 maxv loop 1b ; \ 115 1.1 maxv 2: ; 116 1.1 maxv 117 1.1 maxv /* 118 1.1 maxv * Initialization 119 1.1 maxv */ 120 1.1 maxv .data 121 1.1 maxv 122 1.1 maxv .globl _C_LABEL(tablesize) 123 1.1 maxv .globl _C_LABEL(nox_flag) 124 1.1 maxv .globl _C_LABEL(cpuid_level) 125 1.1 maxv .globl _C_LABEL(esym) 126 1.1 maxv .globl _C_LABEL(eblob) 127 1.1 maxv .globl _C_LABEL(atdevbase) 128 1.1 maxv .globl _C_LABEL(PDPpaddr) 129 1.1 maxv .globl _C_LABEL(boothowto) 130 1.1 maxv .globl _C_LABEL(bootinfo) 131 1.1 maxv .globl _C_LABEL(biosbasemem) 132 1.1 maxv .globl _C_LABEL(biosextmem) 133 1.1 maxv .globl _C_LABEL(stkpa) 134 1.1 maxv .globl _C_LABEL(stkva) 135 1.1 maxv .globl _C_LABEL(kernpa_start) 136 1.1 maxv .globl _C_LABEL(kernpa_end) 137 1.1 maxv 138 1.1 maxv .type _C_LABEL(tablesize), @object 139 1.1 maxv _C_LABEL(tablesize): .long TABLESIZE 140 1.1 maxv END(tablesize) 141 1.1 maxv .type _C_LABEL(nox_flag), @object 142 1.1 maxv LABEL(nox_flag) .long 0 /* 32bit NOX flag, set if supported */ 143 1.1 maxv END(nox_flag) 144 1.1 maxv .type _C_LABEL(cpuid_level), @object 145 1.1 maxv LABEL(cpuid_level) .long -1 /* max. level accepted by cpuid instr */ 146 1.1 maxv END(cpuid_level) 147 1.1 maxv .type _C_LABEL(esym), @object 148 1.1 maxv LABEL(esym) .quad 0 /* ptr to end of syms */ 149 1.1 maxv END(esym) 150 1.1 maxv .type _C_LABEL(eblob), @object 151 1.1 maxv LABEL(eblob) .quad 0 /* ptr to end of modules */ 152 1.1 maxv END(eblob) 153 1.1 maxv .type _C_LABEL(atdevbase), @object 154 1.1 maxv LABEL(atdevbase) .quad 0 /* location of start of iomem in virt */ 155 1.1 maxv END(atdevbase) 156 1.1 maxv .type _C_LABEL(PDPpaddr), @object 157 1.1 maxv LABEL(PDPpaddr) .quad 0 /* paddr of PTD, for libkvm */ 158 1.1 maxv END(PDPpaddr) 159 1.1 maxv .type _C_LABEL(biosbasemem), @object 160 1.1 maxv LABEL(biosbasemem) .long 0 /* base memory reported by BIOS */ 161 1.1 maxv END(biosbasemem) 162 1.1 maxv .type _C_LABEL(biosextmem), @object 163 1.1 maxv LABEL(biosextmem) .long 0 /* extended memory reported by BIOS */ 164 1.1 maxv END(biosextmem) 165 1.1 maxv .type _C_LABEL(stkpa), @object 166 1.1 maxv LABEL(stkpa) .quad 0 167 1.1 maxv END(stkpa) 168 1.1 maxv .type _C_LABEL(stkva), @object 169 1.1 maxv LABEL(stkva) .quad 0 170 1.1 maxv END(stkva) 171 1.1 maxv .type _C_LABEL(kernpa_start), @object 172 1.1 maxv LABEL(kernpa_start) .quad 0 173 1.1 maxv END(kernpa_start) 174 1.1 maxv .type _C_LABEL(kernpa_end), @object 175 1.1 maxv LABEL(kernpa_end) .quad 0 176 1.1 maxv END(kernpa_end) 177 1.1 maxv 178 1.1 maxv .globl gdt64_lo 179 1.1 maxv .globl gdt64_start 180 1.1 maxv 181 1.1 maxv #define GDT64_LIMIT gdt64_end-gdt64_start-1 182 1.1 maxv /* Temporary gdt64, with base address in low memory */ 183 1.1 maxv .type _C_LABEL(gdt64_lo), @object 184 1.1 maxv LABEL(gdt64_lo) 185 1.1 maxv .word GDT64_LIMIT 186 1.1 maxv .quad gdt64_start 187 1.1 maxv END(gdt64_lo) 188 1.1 maxv .align 64 189 1.1 maxv #undef GDT64_LIMIT 190 1.1 maxv 191 1.1 maxv .type _C_LABEL(gdt64_start), @object 192 1.1 maxv LABEL(gdt64_start) 193 1.1 maxv .quad 0x0000000000000000 /* always empty */ 194 1.1 maxv .quad 0x00af9a000000ffff /* kernel CS */ 195 1.1 maxv .quad 0x00cf92000000ffff /* kernel DS */ 196 1.1 maxv END(gdt64_start) 197 1.1 maxv gdt64_end: 198 1.1 maxv 199 1.1 maxv .type _C_LABEL(farjmp64), @object 200 1.1 maxv _C_LABEL(farjmp64): 201 1.1 maxv .long longmode 202 1.1 maxv .word GSEL(GCODE_SEL, SEL_KPL) 203 1.1 maxv END(farjmp64) 204 1.1 maxv 205 1.1 maxv /* Space for the temporary stack */ 206 1.1 maxv .size tmpstk, tmpstk - . 207 1.1 maxv .space 512 208 1.1 maxv tmpstk: 209 1.1 maxv 210 1.1 maxv .text 211 1.1 maxv 212 1.1 maxv ENTRY(start) 213 1.1 maxv .code32 214 1.1 maxv 215 1.1 maxv /* Warm boot */ 216 1.1 maxv movw $0x1234,0x472 217 1.1 maxv 218 1.1 maxv /* 219 1.1 maxv * Load parameters from the stack (32 bits): 220 1.1 maxv * boothowto, [bootdev], bootinfo, esym, biosextmem, biosbasemem 221 1.1 maxv * We are not interested in 'bootdev'. 222 1.1 maxv */ 223 1.1 maxv 224 1.1 maxv /* Load 'boothowto' */ 225 1.1 maxv movl 4(%esp),%eax 226 1.1 maxv movl %eax,_C_LABEL(boothowto) 227 1.1 maxv 228 1.1 maxv /* Load 'bootinfo' */ 229 1.1 maxv movl 12(%esp),%eax 230 1.1 maxv testl %eax,%eax /* bootinfo = NULL? */ 231 1.8 maxv jz .Lbootinfo_finished 232 1.1 maxv 233 1.1 maxv movl (%eax),%ebx /* number of entries */ 234 1.1 maxv movl $_C_LABEL(bootinfo),%ebp 235 1.1 maxv movl %ebp,%edx 236 1.1 maxv addl $BOOTINFO_MAXSIZE,%ebp 237 1.1 maxv movl %ebx,(%edx) 238 1.1 maxv addl $4,%edx 239 1.1 maxv 240 1.8 maxv .Lbootinfo_entryloop: 241 1.1 maxv testl %ebx,%ebx /* no remaining entries? */ 242 1.8 maxv jz .Lbootinfo_finished 243 1.1 maxv 244 1.1 maxv addl $4,%eax 245 1.1 maxv movl (%eax),%ecx /* address of entry */ 246 1.1 maxv pushl %edi 247 1.1 maxv pushl %esi 248 1.1 maxv pushl %eax 249 1.1 maxv 250 1.1 maxv movl (%ecx),%eax /* btinfo_common::len (size of entry) */ 251 1.1 maxv movl %edx,%edi 252 1.1 maxv addl (%ecx),%edx /* update dest pointer */ 253 1.1 maxv cmpl %ebp,%edx /* beyond bootinfo+BOOTINFO_MAXSIZE? */ 254 1.8 maxv jg .Lbootinfo_overflow 255 1.1 maxv 256 1.1 maxv movl %ecx,%esi 257 1.1 maxv movl %eax,%ecx 258 1.1 maxv 259 1.1 maxv /* If any modules were loaded, record where they end. */ 260 1.1 maxv cmpl $BTINFO_MODULELIST,4(%esi) /* btinfo_common::type */ 261 1.1 maxv jne 0f 262 1.1 maxv pushl 12(%esi) /* btinfo_modulelist::endpa */ 263 1.1 maxv popl _C_LABEL(eblob) 264 1.1 maxv 0: 265 1.1 maxv 266 1.1 maxv /* Record the information about the kernel. */ 267 1.1 maxv cmpl $BTINFO_PREKERN,4(%esi) /* btinfo_common::type */ 268 1.1 maxv jne 0f 269 1.1 maxv pushl 8(%esi) /* btinfo_prekern::kernpa_start */ 270 1.1 maxv popl _C_LABEL(kernpa_start) 271 1.1 maxv pushl 12(%esi) /* btinfo_prekern::kernpa_end */ 272 1.1 maxv popl _C_LABEL(kernpa_end) 273 1.1 maxv 0: 274 1.1 maxv 275 1.1 maxv rep 276 1.1 maxv movsb /* copy esi -> edi */ 277 1.1 maxv popl %eax 278 1.1 maxv popl %esi 279 1.1 maxv popl %edi 280 1.1 maxv subl $1,%ebx /* decrement the # of entries */ 281 1.8 maxv jmp .Lbootinfo_entryloop 282 1.1 maxv 283 1.8 maxv .Lbootinfo_overflow: 284 1.1 maxv /* 285 1.1 maxv * Cleanup for overflow case. Pop the registers, and correct the number 286 1.1 maxv * of entries. 287 1.1 maxv */ 288 1.1 maxv popl %eax 289 1.1 maxv popl %esi 290 1.1 maxv popl %edi 291 1.1 maxv movl $_C_LABEL(bootinfo),%ebp 292 1.1 maxv movl %ebp,%edx 293 1.1 maxv subl %ebx,(%edx) /* correct the number of entries */ 294 1.1 maxv 295 1.8 maxv .Lbootinfo_finished: 296 1.1 maxv /* Load 'esym' */ 297 1.1 maxv movl 16(%esp),%eax 298 1.1 maxv movl $_C_LABEL(esym),%ebp 299 1.1 maxv movl %eax,(%ebp) 300 1.1 maxv 301 1.1 maxv /* Load 'biosextmem' */ 302 1.1 maxv movl 20(%esp),%eax 303 1.1 maxv movl $_C_LABEL(biosextmem),%ebp 304 1.1 maxv movl %eax,(%ebp) 305 1.1 maxv 306 1.1 maxv /* Load 'biosbasemem' */ 307 1.1 maxv movl 24(%esp),%eax 308 1.1 maxv movl $_C_LABEL(biosbasemem),%ebp 309 1.1 maxv movl %eax,(%ebp) 310 1.1 maxv 311 1.1 maxv /* 312 1.1 maxv * Done with the parameters! 313 1.1 maxv */ 314 1.1 maxv 315 1.1 maxv /* First, reset the PSL. */ 316 1.1 maxv pushl $PSL_MBO 317 1.1 maxv popfl 318 1.1 maxv 319 1.1 maxv /* Switch to new stack now. */ 320 1.1 maxv movl $_C_LABEL(tmpstk),%esp 321 1.1 maxv 322 1.1 maxv xorl %eax,%eax 323 1.1 maxv cpuid 324 1.1 maxv movl %eax,_C_LABEL(cpuid_level) 325 1.1 maxv 326 1.1 maxv /* 327 1.10 maxv * Retrieve the NX/XD flag. We use the 32bit version of PTE_NX. 328 1.1 maxv */ 329 1.1 maxv movl $0x80000001,%eax 330 1.1 maxv cpuid 331 1.1 maxv andl $CPUID_NOX,%edx 332 1.8 maxv jz .Lno_NOX 333 1.10 maxv movl $PTE_NX32,_C_LABEL(nox_flag) 334 1.8 maxv .Lno_NOX: 335 1.1 maxv 336 1.1 maxv /* 337 1.1 maxv * There are four levels of pages in amd64: PML4 -> PDP -> PD -> PT. They will 338 1.1 maxv * be referred to as: L4 -> L3 -> L2 -> L1. 339 1.1 maxv * 340 1.1 maxv * Physical address space: 341 1.1 maxv * +---------------+----------+--------------+--------+---------------------+- 342 1.1 maxv * | PREKERN IMAGE |**UNUSED**| KERNEL IMAGE | [SYMS] | [PRELOADED MODULES] | 343 1.1 maxv * +---------------+----------+--------------+--------+---------------------+- 344 1.1 maxv * (1) (2) (3) (4) 345 1.1 maxv * ------------------+ 346 1.1 maxv * BOOTSTRAP TABLES | 347 1.1 maxv * ------------------+ 348 1.1 maxv * (5) 349 1.1 maxv * 350 1.7 maxv * The virtual address space is the same, since it is identity-mapped (va = pa). 351 1.7 maxv * However, the KERNEL IMAGE is mapped as read-only: the prekern reads it, but 352 1.7 maxv * won't write to it. (Needed when relocating the kernel.) 353 1.1 maxv * 354 1.1 maxv * PROC0 STK is obviously not linked as a page level. It just happens to be 355 1.1 maxv * caught between L4 and L3. 356 1.1 maxv * 357 1.1 maxv * (PROC0 STK + L4 + L3 + L2 + L1) is later referred to as BOOTSTRAP TABLES. 358 1.1 maxv * 359 1.7 maxv * Important note: the prekern segments are properly 4k-aligned 360 1.7 maxv * (see prekern.ldscript), so there's no need to enforce alignment. 361 1.1 maxv */ 362 1.1 maxv 363 1.1 maxv /* Find end of the prekern image; brings us on (1). */ 364 1.1 maxv movl $_C_LABEL(__prekern_end),%edi 365 1.1 maxv 366 1.2 maxv /* Find end of the kernel image; brings us on (2). */ 367 1.1 maxv movl _C_LABEL(kernpa_end),%eax 368 1.1 maxv testl %eax,%eax 369 1.1 maxv jz 1f 370 1.1 maxv movl %eax,%edi 371 1.1 maxv 1: 372 1.1 maxv 373 1.2 maxv /* Find end of the kernel symbols; brings us on (3). */ 374 1.1 maxv movl _C_LABEL(esym),%eax 375 1.1 maxv testl %eax,%eax 376 1.1 maxv jz 1f 377 1.1 maxv movl %eax,%edi 378 1.1 maxv 1: 379 1.1 maxv 380 1.1 maxv /* Find end of the kernel preloaded modules; brings us on (4). */ 381 1.1 maxv movl _C_LABEL(eblob),%eax 382 1.1 maxv testl %eax,%eax 383 1.1 maxv jz 1f 384 1.1 maxv movl %eax,%edi 385 1.1 maxv 1: 386 1.1 maxv 387 1.1 maxv /* We are on (3). Align up for BOOTSTRAP TABLES. */ 388 1.1 maxv movl %edi,%esi 389 1.1 maxv addl $PGOFSET,%esi 390 1.1 maxv andl $~PGOFSET,%esi 391 1.1 maxv 392 1.1 maxv /* We are on the BOOTSTRAP TABLES. Save L4's physical address. */ 393 1.1 maxv movl $_C_LABEL(PDPpaddr),%ebp 394 1.1 maxv movl %esi,(%ebp) 395 1.1 maxv movl $0,4(%ebp) 396 1.1 maxv 397 1.1 maxv /* Now, zero out the BOOTSTRAP TABLES (before filling them in). */ 398 1.1 maxv movl %esi,%edi 399 1.1 maxv xorl %eax,%eax 400 1.1 maxv cld 401 1.1 maxv movl $TABLESIZE,%ecx 402 1.1 maxv shrl $2,%ecx 403 1.1 maxv rep 404 1.1 maxv stosl /* copy eax -> edi */ 405 1.1 maxv 406 1.1 maxv /* 407 1.1 maxv * Build the page tables and levels. We go from L1 to L4, and link the levels 408 1.1 maxv * together. 409 1.1 maxv */ 410 1.1 maxv /* 411 1.1 maxv * Build L1. 412 1.1 maxv */ 413 1.1 maxv leal (PROC0_PTP1_OFF)(%esi),%ebx 414 1.1 maxv 415 1.1 maxv /* Skip the area below the prekern text. */ 416 1.1 maxv movl $(PREKERNTEXTOFF - PREKERNBASE),%ecx 417 1.1 maxv shrl $PGSHIFT,%ecx 418 1.1 maxv fillkpt_blank 419 1.1 maxv 420 1.1 maxv /* Map the prekern text RX. */ 421 1.1 maxv movl $(PREKERNTEXTOFF - PREKERNBASE),%eax /* start of TEXT */ 422 1.1 maxv movl $_C_LABEL(__rodata_start),%ecx 423 1.1 maxv subl %eax,%ecx 424 1.1 maxv shrl $PGSHIFT,%ecx 425 1.10 maxv orl $(PTE_P),%eax 426 1.1 maxv fillkpt 427 1.1 maxv 428 1.1 maxv /* Map the prekern rodata R. */ 429 1.1 maxv movl $_C_LABEL(__rodata_start),%eax 430 1.1 maxv movl $_C_LABEL(__data_start),%ecx 431 1.1 maxv subl %eax,%ecx 432 1.1 maxv shrl $PGSHIFT,%ecx 433 1.10 maxv orl $(PTE_P),%eax 434 1.1 maxv fillkpt_nox 435 1.1 maxv 436 1.1 maxv /* Map the prekern data+bss RW. */ 437 1.1 maxv movl $_C_LABEL(__data_start),%eax 438 1.1 maxv movl $_C_LABEL(__prekern_end),%ecx 439 1.1 maxv subl %eax,%ecx 440 1.1 maxv shrl $PGSHIFT,%ecx 441 1.10 maxv orl $(PTE_P|PTE_W),%eax 442 1.1 maxv fillkpt_nox 443 1.1 maxv 444 1.3 maxv /* Map a RO view of the kernel. */ 445 1.1 maxv movl $_C_LABEL(__prekern_end),%eax 446 1.1 maxv movl %esi,%ecx /* start of BOOTSTRAP TABLES */ 447 1.1 maxv subl %eax,%ecx 448 1.1 maxv shrl $PGSHIFT,%ecx 449 1.10 maxv orl $(PTE_P),%eax 450 1.3 maxv fillkpt_nox 451 1.1 maxv 452 1.1 maxv /* Map the BOOTSTRAP TABLES RW. */ 453 1.1 maxv movl %esi,%eax /* start of BOOTSTRAP TABLES */ 454 1.1 maxv movl $TABLESIZE,%ecx /* length of BOOTSTRAP TABLES */ 455 1.1 maxv shrl $PGSHIFT,%ecx 456 1.10 maxv orl $(PTE_P|PTE_W),%eax 457 1.1 maxv fillkpt_nox 458 1.1 maxv 459 1.1 maxv /* Map the ISA I/O MEM RW. */ 460 1.1 maxv movl $IOM_BEGIN,%eax 461 1.1 maxv movl $IOM_SIZE,%ecx /* size of ISA I/O MEM */ 462 1.1 maxv shrl $PGSHIFT,%ecx 463 1.10 maxv orl $(PTE_P|PTE_W/*|PTE_PCD*/),%eax 464 1.1 maxv fillkpt_nox 465 1.1 maxv 466 1.1 maxv /* 467 1.1 maxv * Build L2. Linked to L1. 468 1.1 maxv */ 469 1.1 maxv leal (PROC0_PTP2_OFF)(%esi),%ebx 470 1.1 maxv leal (PROC0_PTP1_OFF)(%esi),%eax 471 1.10 maxv orl $(PTE_P|PTE_W),%eax 472 1.1 maxv movl $(NKL2_KIMG_ENTRIES+1),%ecx 473 1.1 maxv fillkpt 474 1.1 maxv 475 1.1 maxv /* 476 1.1 maxv * Build L3. Linked to L2. 477 1.1 maxv */ 478 1.1 maxv leal (PROC0_PTP3_OFF)(%esi),%ebx 479 1.1 maxv leal (PROC0_PTP2_OFF)(%esi),%eax 480 1.10 maxv orl $(PTE_P|PTE_W),%eax 481 1.1 maxv movl $NKL3_KIMG_ENTRIES,%ecx 482 1.1 maxv fillkpt 483 1.1 maxv 484 1.1 maxv /* 485 1.1 maxv * Build L4. Linked to L3. 486 1.1 maxv */ 487 1.1 maxv leal (PROC0_PML4_OFF)(%esi),%ebx 488 1.1 maxv leal (PROC0_PTP3_OFF)(%esi),%eax 489 1.10 maxv orl $(PTE_P|PTE_W),%eax 490 1.1 maxv movl $NKL4_KIMG_ENTRIES,%ecx 491 1.1 maxv fillkpt 492 1.1 maxv 493 1.1 maxv /* Install recursive top level PDE (one entry) */ 494 1.1 maxv leal (PROC0_PML4_OFF + PDIR_SLOT_PTE * PDE_SIZE)(%esi),%ebx 495 1.1 maxv leal (PROC0_PML4_OFF)(%esi),%eax 496 1.10 maxv orl $(PTE_P|PTE_W),%eax 497 1.1 maxv movl $1,%ecx 498 1.1 maxv fillkpt_nox 499 1.1 maxv 500 1.1 maxv /* 501 1.1 maxv * Startup checklist: 502 1.1 maxv * 1. Enable PAE (and SSE while here). 503 1.1 maxv */ 504 1.1 maxv movl %cr4,%eax 505 1.1 maxv orl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax 506 1.1 maxv movl %eax,%cr4 507 1.1 maxv 508 1.1 maxv /* 509 1.1 maxv * 2. Set Long Mode Enable in EFER. Also enable the syscall extensions, 510 1.1 maxv * and NOX if available. 511 1.1 maxv */ 512 1.1 maxv movl $MSR_EFER,%ecx 513 1.1 maxv rdmsr 514 1.1 maxv xorl %eax,%eax 515 1.1 maxv orl $(EFER_LME|EFER_SCE),%eax 516 1.1 maxv movl _C_LABEL(nox_flag),%ebx 517 1.1 maxv cmpl $0,%ebx 518 1.8 maxv je .Lskip_NOX 519 1.1 maxv orl $(EFER_NXE),%eax 520 1.8 maxv .Lskip_NOX: 521 1.1 maxv wrmsr 522 1.1 maxv 523 1.1 maxv /* 524 1.1 maxv * 3. Load %cr3 with pointer to PML4. 525 1.1 maxv */ 526 1.1 maxv movl %esi,%eax 527 1.1 maxv movl %eax,%cr3 528 1.1 maxv 529 1.1 maxv /* 530 1.1 maxv * 4. Enable paging and the rest of it. 531 1.1 maxv */ 532 1.1 maxv movl %cr0,%eax 533 1.1 maxv orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM),%eax 534 1.1 maxv movl %eax,%cr0 535 1.1 maxv jmp compat 536 1.1 maxv compat: 537 1.1 maxv 538 1.1 maxv /* 539 1.1 maxv * 5. Not quite done yet, we're now in a compatibility segment, in 540 1.1 maxv * legacy mode. We must jump to a long mode segment. Need to set up 541 1.1 maxv * a GDT with a long mode segment in it to do that. 542 1.1 maxv */ 543 1.1 maxv movl $_C_LABEL(gdt64_lo),%eax 544 1.1 maxv lgdt (%eax) 545 1.1 maxv movl $_C_LABEL(farjmp64),%eax 546 1.1 maxv ljmp *(%eax) 547 1.1 maxv 548 1.1 maxv .code64 549 1.1 maxv longmode: 550 1.1 maxv 551 1.1 maxv /* 552 1.1 maxv * We have arrived. Everything is identity-mapped. 553 1.1 maxv */ 554 1.1 maxv 555 1.1 maxv /* Store atdevbase. */ 556 1.1 maxv movq $TABLESIZE,%rdx 557 1.1 maxv addq %rsi,%rdx 558 1.1 maxv movq %rdx,_C_LABEL(atdevbase)(%rip) 559 1.1 maxv 560 1.1 maxv /* Set up bootstrap stack. */ 561 1.1 maxv leaq (PROC0_STK_OFF)(%rsi),%rax 562 1.1 maxv movq %rax,_C_LABEL(stkpa)(%rip) 563 1.1 maxv leaq (USPACE-FRAMESIZE)(%rax),%rsp 564 1.1 maxv xorq %rbp,%rbp /* mark end of frames */ 565 1.1 maxv 566 1.1 maxv xorw %ax,%ax 567 1.1 maxv movw %ax,%gs 568 1.1 maxv movw %ax,%fs 569 1.1 maxv 570 1.11 maxv movw $GSEL(GDATA_SEL, SEL_KPL),%ax 571 1.11 maxv movw %ax,%ss 572 1.11 maxv 573 1.1 maxv /* The first physical page available. */ 574 1.1 maxv leaq (TABLESIZE)(%rsi),%rdi 575 1.1 maxv 576 1.1 maxv /* 577 1.1 maxv * Continue execution in C. 578 1.1 maxv */ 579 1.1 maxv call _C_LABEL(init_prekern) 580 1.1 maxv 581 1.1 maxv ret 582 1.1 maxv END(start) 583 1.1 maxv 584 1.1 maxv /* -------------------------------------------------------------------------- */ 585 1.1 maxv 586 1.4 maxv ENTRY(cpuid) 587 1.4 maxv movq %rbx,%r8 588 1.4 maxv movq %rdi,%rax 589 1.4 maxv movq %rsi,%rcx 590 1.4 maxv movq %rdx,%rsi 591 1.4 maxv cpuid 592 1.4 maxv movl %eax,0(%rsi) 593 1.4 maxv movl %ebx,4(%rsi) 594 1.4 maxv movl %ecx,8(%rsi) 595 1.4 maxv movl %edx,12(%rsi) 596 1.4 maxv movq %r8,%rbx 597 1.4 maxv ret 598 1.4 maxv END(cpuid) 599 1.4 maxv 600 1.1 maxv ENTRY(lidt) 601 1.1 maxv lidt (%rdi) 602 1.1 maxv ret 603 1.4 maxv END(lidt) 604 1.1 maxv 605 1.1 maxv ENTRY(rdtsc) 606 1.1 maxv xorq %rax,%rax 607 1.1 maxv rdtsc 608 1.1 maxv shlq $32,%rdx 609 1.1 maxv orq %rdx,%rax 610 1.1 maxv ret 611 1.4 maxv END(rdtsc) 612 1.4 maxv 613 1.4 maxv ENTRY(rdseed) 614 1.4 maxv rdseed %rax 615 1.6 maxv jc .Lrdseed_success 616 1.4 maxv movq $(-1),%rax 617 1.4 maxv ret 618 1.6 maxv .Lrdseed_success: 619 1.4 maxv movq %rax,(%rdi) 620 1.4 maxv xorq %rax,%rax 621 1.4 maxv ret 622 1.4 maxv END(rdseed) 623 1.1 maxv 624 1.6 maxv ENTRY(rdrand) 625 1.6 maxv rdrand %rax 626 1.6 maxv jc .Lrdrand_success 627 1.6 maxv movq $(-1),%rax 628 1.6 maxv ret 629 1.6 maxv .Lrdrand_success: 630 1.6 maxv movq %rax,(%rdi) 631 1.6 maxv xorq %rax,%rax 632 1.6 maxv ret 633 1.6 maxv END(rdrand) 634 1.6 maxv 635 1.1 maxv ENTRY(jump_kernel) 636 1.1 maxv movq _C_LABEL(stkva),%rsp 637 1.5 maxv xorq %rbp,%rbp 638 1.5 maxv callq exec_kernel 639 1.4 maxv END(jump_kernel) 640