Home | History | Annotate | Line # | Download | only in prekern
      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