xref: /dflybsd-src/test/nvmm/demo/smallkern/locore.S (revision 20b815aaa70f0fb8a4c815b9686a6de1feb2fa58)
18368e25fSAaron LI/*
28368e25fSAaron LI * Copyright (c) 1998, 2000, 2007, 2008, 2016, 2017 The NetBSD Foundation, Inc.
38368e25fSAaron LI * All rights reserved.
48368e25fSAaron LI *
58368e25fSAaron LI * This code is derived from software contributed to The NetBSD Foundation
68368e25fSAaron LI * by Charles M. Hannum and by Maxime Villard.
78368e25fSAaron LI *
88368e25fSAaron LI * Redistribution and use in source and binary forms, with or without
98368e25fSAaron LI * modification, are permitted provided that the following conditions
108368e25fSAaron LI * are met:
118368e25fSAaron LI * 1. Redistributions of source code must retain the above copyright
128368e25fSAaron LI *    notice, this list of conditions and the following disclaimer.
138368e25fSAaron LI * 2. Redistributions in binary form must reproduce the above copyright
148368e25fSAaron LI *    notice, this list of conditions and the following disclaimer in the
158368e25fSAaron LI *    documentation and/or other materials provided with the distribution.
168368e25fSAaron LI *
178368e25fSAaron LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
188368e25fSAaron LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
198368e25fSAaron LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
208368e25fSAaron LI * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
218368e25fSAaron LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
228368e25fSAaron LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
238368e25fSAaron LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
248368e25fSAaron LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
258368e25fSAaron LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
268368e25fSAaron LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
278368e25fSAaron LI * POSSIBILITY OF SUCH DAMAGE.
288368e25fSAaron LI */
298368e25fSAaron LI
308368e25fSAaron LI#define _LOCORE
31*20b815aaSAaron LI#define LOCORE /* DragonFly */
328368e25fSAaron LI
333bac6f2aSAaron LI#include "asm.h"
343bac6f2aSAaron LI#include "pdir.h"
358368e25fSAaron LI
368368e25fSAaron LI#include <machine/param.h>
378368e25fSAaron LI#include <machine/segments.h>
388368e25fSAaron LI#include <machine/specialreg.h>
398368e25fSAaron LI
403bac6f2aSAaron LI#define PSL_MBO		0x00000002	/* must be zero bits */
418368e25fSAaron LI
423bac6f2aSAaron LI#define PTE_P		0x001	/* P: Valid */
433bac6f2aSAaron LI#define PTE_W		0x002	/* R/W: Read/Write */
443bac6f2aSAaron LI#define PTE_PCD		0x010	/* PCD: Cache disable */
458368e25fSAaron LI
468368e25fSAaron LI/* 32bit version of PG_NX */
478368e25fSAaron LI#define PG_NX32		0x80000000
488368e25fSAaron LI
498368e25fSAaron LI#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
508368e25fSAaron LI#define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES
518368e25fSAaron LI
528368e25fSAaron LI#define PROC0_PML4_OFF	0
538368e25fSAaron LI#define PROC0_STK_OFF	(PROC0_PML4_OFF + 1 * PAGE_SIZE)
548368e25fSAaron LI#define PROC0_PTP3_OFF	(PROC0_STK_OFF + UPAGES * PAGE_SIZE)
558368e25fSAaron LI#define PROC0_PTP2_OFF	(PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * PAGE_SIZE)
568368e25fSAaron LI#define PROC0_PTP1_OFF	(PROC0_PTP2_OFF + TABLE_L3_ENTRIES * PAGE_SIZE)
578368e25fSAaron LI#define TABLESIZE \
588368e25fSAaron LI  ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES) \
598368e25fSAaron LI    * PAGE_SIZE)
608368e25fSAaron LI
618368e25fSAaron LI/*
628368e25fSAaron LI * fillkpt - Fill in a kernel page table
638368e25fSAaron LI *	eax = pte (page frame | control | status)
648368e25fSAaron LI *	ebx = page table address
658368e25fSAaron LI *	ecx = number of pages to map
668368e25fSAaron LI *
678368e25fSAaron LI * Each entry is 8 (PDE_SIZE) bytes long: we must set the 4 upper bytes to 0.
688368e25fSAaron LI */
698368e25fSAaron LI#define fillkpt	\
708368e25fSAaron LI	cmpl	$0,%ecx			;	/* zero-sized? */	\
718368e25fSAaron LI	je 	2f			; \
728368e25fSAaron LI1:	movl	$0,(PDE_SIZE-4)(%ebx)	;	/* upper 32 bits: 0 */	\
738368e25fSAaron LI	movl	%eax,(%ebx)		;	/* store phys addr */	\
748368e25fSAaron LI	addl	$PDE_SIZE,%ebx		;	/* next PTE/PDE */	\
758368e25fSAaron LI	addl	$PAGE_SIZE,%eax		;	/* next phys page */	\
768368e25fSAaron LI	loop	1b			; \
778368e25fSAaron LI2:					;
788368e25fSAaron LI
798368e25fSAaron LI/*
808368e25fSAaron LI * fillkpt_nox - Same as fillkpt, but sets the NX/XD bit.
818368e25fSAaron LI */
828368e25fSAaron LI#define fillkpt_nox \
838368e25fSAaron LI	cmpl	$0,%ecx			;	/* zero-sized? */	\
848368e25fSAaron LI	je 	2f			; \
858368e25fSAaron LI	pushl	%ebp			; \
868368e25fSAaron LI	movl	_C_LABEL(nox_flag),%ebp	; \
878368e25fSAaron LI1:	movl	%ebp,(PDE_SIZE-4)(%ebx)	;	/* upper 32 bits: NX */ \
888368e25fSAaron LI	movl	%eax,(%ebx)		;	/* store phys addr */	\
898368e25fSAaron LI	addl	$PDE_SIZE,%ebx		;	/* next PTE/PDE */	\
908368e25fSAaron LI	addl	$PAGE_SIZE,%eax		;	/* next phys page */	\
918368e25fSAaron LI	loop	1b			; \
928368e25fSAaron LI	popl	%ebp			; \
938368e25fSAaron LI2:					;
948368e25fSAaron LI
958368e25fSAaron LI/*
968368e25fSAaron LI * fillkpt_blank - Fill in a kernel page table with blank entries
978368e25fSAaron LI *	ebx = page table address
988368e25fSAaron LI *	ecx = number of pages to map
998368e25fSAaron LI */
1008368e25fSAaron LI#define fillkpt_blank	\
1018368e25fSAaron LI	cmpl	$0,%ecx			;	/* zero-sized? */	\
1028368e25fSAaron LI	je 	2f			; \
1038368e25fSAaron LI1:	movl	$0,(PDE_SIZE-4)(%ebx)	;	/* upper 32 bits: 0 */	\
1048368e25fSAaron LI	movl	$0,(%ebx)		;	/* lower 32 bits: 0 */	\
1058368e25fSAaron LI	addl	$PDE_SIZE,%ebx		;	/* next PTE/PDE */	\
1068368e25fSAaron LI	loop	1b			; \
1078368e25fSAaron LI2:					;
1088368e25fSAaron LI
1098368e25fSAaron LI/*
1108368e25fSAaron LI * Initialization
1118368e25fSAaron LI */
1128368e25fSAaron LI	.data
1138368e25fSAaron LI
1148368e25fSAaron LI	.globl	_C_LABEL(tablesize)
1158368e25fSAaron LI	.globl	_C_LABEL(nox_flag)
1168368e25fSAaron LI	.globl	_C_LABEL(cpuid_level)
1178368e25fSAaron LI	.globl	_C_LABEL(PDPpaddr)
1188368e25fSAaron LI	.globl	_C_LABEL(atdevbase)
119aaa1e810SAaron LI	.globl	_C_LABEL(lapicbase)
1208368e25fSAaron LI	.globl	_C_LABEL(stkpa)
1218368e25fSAaron LI	.globl	_C_LABEL(stkva)
1228368e25fSAaron LI
1238368e25fSAaron LI	.type	_C_LABEL(tablesize), @object
1248368e25fSAaron LI_C_LABEL(tablesize):	.long	TABLESIZE
1258368e25fSAaron LIEND(tablesize)
1268368e25fSAaron LI	.type	_C_LABEL(nox_flag), @object
1278368e25fSAaron LILABEL(nox_flag)		.long	0	/* 32bit NOX flag, set if supported */
1288368e25fSAaron LIEND(nox_flag)
1298368e25fSAaron LI	.type	_C_LABEL(cpuid_level), @object
1308368e25fSAaron LILABEL(cpuid_level)	.long	-1	/* max. level accepted by cpuid instr */
1318368e25fSAaron LIEND(cpuid_level)
1328368e25fSAaron LI	.type	_C_LABEL(PDPpaddr), @object
1338368e25fSAaron LILABEL(PDPpaddr)		.quad	0
1348368e25fSAaron LIEND(PDPpaddr)
1358368e25fSAaron LI	.type	_C_LABEL(atdevbase), @object
1368368e25fSAaron LILABEL(atdevbase)	.quad	0	/* location of start of iomem in virt */
1378368e25fSAaron LIEND(atdevbase)
1388368e25fSAaron LI	.type	_C_LABEL(lapicbase), @object
1398368e25fSAaron LILABEL(lapicbase)	.quad	0	/* location of start of lapic in virt */
1408368e25fSAaron LIEND(lapicbase)
1418368e25fSAaron LI	.type	_C_LABEL(stkpa), @object
1428368e25fSAaron LILABEL(stkpa)		.quad	0
1438368e25fSAaron LIEND(stkpa)
1448368e25fSAaron LI	.type	_C_LABEL(stkva), @object
1458368e25fSAaron LILABEL(stkva)		.quad	0
1468368e25fSAaron LIEND(stkva)
1478368e25fSAaron LI
1488368e25fSAaron LI	.globl	gdt64_lo
1498368e25fSAaron LI	.globl	gdt64_start
1508368e25fSAaron LI
1518368e25fSAaron LI#define GDT64_LIMIT gdt64_end-gdt64_start-1
1528368e25fSAaron LI/* Temporary gdt64, with base address in low memory */
1538368e25fSAaron LI	.type	_C_LABEL(gdt64_lo), @object
1548368e25fSAaron LILABEL(gdt64_lo)
1558368e25fSAaron LI	.word	GDT64_LIMIT
1568368e25fSAaron LI	.quad	gdt64_start
1578368e25fSAaron LIEND(gdt64_lo)
1588368e25fSAaron LI.align 64
1598368e25fSAaron LI#undef GDT64_LIMIT
1608368e25fSAaron LI
1618368e25fSAaron LI	.type	_C_LABEL(gdt64_start), @object
1628368e25fSAaron LILABEL(gdt64_start)
1638368e25fSAaron LI	.quad 0x0000000000000000	/* always empty */
1648368e25fSAaron LI	.quad 0x00af9a000000ffff	/* kernel CS */
1658368e25fSAaron LI	.quad 0x00cf92000000ffff	/* kernel DS */
1668368e25fSAaron LI	.quad 0x0000000000000000	/* kernel TSS [1/2] */
1678368e25fSAaron LI	.quad 0x0000000000000000	/* kernel TSS [2/2] */
1688368e25fSAaron LIEND(gdt64_start)
1698368e25fSAaron LIgdt64_end:
1708368e25fSAaron LI
1718368e25fSAaron LI	.type	_C_LABEL(farjmp64), @object
1728368e25fSAaron LI_C_LABEL(farjmp64):
1738368e25fSAaron LI	.long	longmode
1748368e25fSAaron LI	.word	GSEL(GCODE_SEL, SEL_KPL)
1758368e25fSAaron LIEND(farjmp64)
1768368e25fSAaron LI
1778368e25fSAaron LI	/* Space for the temporary stack */
1788368e25fSAaron LI	.size	tmpstk, tmpstk - .
1798368e25fSAaron LI	.space	512
1808368e25fSAaron LItmpstk:
1818368e25fSAaron LI
1828368e25fSAaron LI	.text
1838368e25fSAaron LI
1848368e25fSAaron LIENTRY(start)
1858368e25fSAaron LI	.code32
1868368e25fSAaron LI
1878368e25fSAaron LI	xorl	%eax,%eax
1888368e25fSAaron LI
1898368e25fSAaron LI	/* Switch to new stack now. */
1908368e25fSAaron LI	movl	$_C_LABEL(tmpstk),%esp
1918368e25fSAaron LI
1928368e25fSAaron LI	/* First, reset the PSL. */
1938368e25fSAaron LI	pushl	$PSL_MBO
1948368e25fSAaron LI	popfl
1958368e25fSAaron LI
1968368e25fSAaron LI	xorl	%eax,%eax
1978368e25fSAaron LI	cpuid
1988368e25fSAaron LI	movl	%eax,_C_LABEL(cpuid_level)
1998368e25fSAaron LI
2008368e25fSAaron LI	/*
2018368e25fSAaron LI	 * Retrieve the NX/XD flag. We use the 32bit version of PG_NX.
2028368e25fSAaron LI	 */
2038368e25fSAaron LI	movl	$0x80000001,%eax
2048368e25fSAaron LI	cpuid
2058368e25fSAaron LI	andl	$CPUID_NOX,%edx
2068368e25fSAaron LI	jz	.Lno_NOX
2078368e25fSAaron LI	movl	$PG_NX32,_C_LABEL(nox_flag)
2088368e25fSAaron LI.Lno_NOX:
2098368e25fSAaron LI
2108368e25fSAaron LI/*
2118368e25fSAaron LI * There are four levels of pages in amd64: PML4 -> PDP -> PD -> PT. They will
2128368e25fSAaron LI * be referred to as: L4 -> L3 -> L2 -> L1.
2138368e25fSAaron LI *
2148368e25fSAaron LI * Physical address space:
2158368e25fSAaron LI * +-----------------+------------------+
2168368e25fSAaron LI * | SMALLKERN IMAGE | BOOTSTRAP TABLES |
2178368e25fSAaron LI * +-----------------+------------------+
2188368e25fSAaron LI *                  (1)
2198368e25fSAaron LI *
2208368e25fSAaron LI * Virtual address space of the smallkern:
2218368e25fSAaron LI * +-----------------+------------------+
2228368e25fSAaron LI * | SMALLKERN IMAGE | BOOTSTRAP TABLES |
2238368e25fSAaron LI * +-----------------+------------------+
2248368e25fSAaron LI *
2258368e25fSAaron LI * PROC0 STK is obviously not linked as a page level. It just happens to be
2268368e25fSAaron LI * caught between L4 and L3.
2278368e25fSAaron LI *
2288368e25fSAaron LI * (PROC0 STK + L4 + L3 + L2 + L1) is later referred to as BOOTSTRAP TABLES.
2298368e25fSAaron LI *
2308368e25fSAaron LI * Important note: the kernel segments are properly 4k-aligned
2318368e25fSAaron LI * (see kern.ldscript), so there's no need to enforce alignment.
2328368e25fSAaron LI */
2338368e25fSAaron LI
2348368e25fSAaron LI	/* Find end of the kernel image; brings us on (1). */
2358368e25fSAaron LI	movl	$_C_LABEL(__smallkern_end),%edi
2368368e25fSAaron LI
2378368e25fSAaron LI	/* We are on (1). Align up for LAPIC PAGE. */
2388368e25fSAaron LI	movl	%edi,%esi
2398368e25fSAaron LI	addl	$PGOFSET,%esi
2408368e25fSAaron LI	andl	$~PGOFSET,%esi
2418368e25fSAaron LI
2428368e25fSAaron LI	/* We are on the BOOTSTRAP TABLES. Save L4's physical address. */
2438368e25fSAaron LI	movl	$_C_LABEL(PDPpaddr),%ebp
2448368e25fSAaron LI	movl	%esi,(%ebp)
2458368e25fSAaron LI	movl	$0,4(%ebp)
2468368e25fSAaron LI
2478368e25fSAaron LI	/* Now, zero out the BOOTSTRAP TABLES (before filling them in). */
2488368e25fSAaron LI	movl	%esi,%edi
2498368e25fSAaron LI	xorl	%eax,%eax
2508368e25fSAaron LI	cld
2518368e25fSAaron LI	movl	$TABLESIZE,%ecx
2528368e25fSAaron LI	shrl	$2,%ecx
2538368e25fSAaron LI	rep
2548368e25fSAaron LI	stosl				/* copy eax -> edi */
2558368e25fSAaron LI
2568368e25fSAaron LI/*
2578368e25fSAaron LI * Build the page tables and levels. We go from L1 to L4, and link the levels
2588368e25fSAaron LI * together.
2598368e25fSAaron LI */
2608368e25fSAaron LI	/*
2618368e25fSAaron LI	 * Build L1.
2628368e25fSAaron LI	 */
2638368e25fSAaron LI	leal	(PROC0_PTP1_OFF)(%esi),%ebx
2648368e25fSAaron LI
2658368e25fSAaron LI	/* Skip the area below the smallkern text. */
2668368e25fSAaron LI	movl	$(SMALLKERNTEXTOFF - SMALLKERNBASE),%ecx
2678368e25fSAaron LI	shrl	$PGSHIFT,%ecx
2688368e25fSAaron LI	fillkpt_blank
2698368e25fSAaron LI
2708368e25fSAaron LI	/* Map the smallkern text RX. */
2718368e25fSAaron LI	movl	$(SMALLKERNTEXTOFF - SMALLKERNBASE),%eax /* start of TEXT */
2728368e25fSAaron LI	movl	$_C_LABEL(__rodata_start),%ecx
2738368e25fSAaron LI	subl	%eax,%ecx
2748368e25fSAaron LI	shrl	$PGSHIFT,%ecx
2758368e25fSAaron LI	orl	$(PTE_P),%eax
2768368e25fSAaron LI	fillkpt
2778368e25fSAaron LI
2788368e25fSAaron LI	/* Map the smallkern rodata R. */
2798368e25fSAaron LI	movl	$_C_LABEL(__rodata_start),%eax
2808368e25fSAaron LI	movl	$_C_LABEL(__data_start),%ecx
2818368e25fSAaron LI	subl	%eax,%ecx
2828368e25fSAaron LI	shrl	$PGSHIFT,%ecx
2838368e25fSAaron LI	orl	$(PTE_P),%eax
2848368e25fSAaron LI	fillkpt_nox
2858368e25fSAaron LI
2868368e25fSAaron LI	/* Map the smallkern data+bss RW. */
2878368e25fSAaron LI	movl	$_C_LABEL(__data_start),%eax
2888368e25fSAaron LI	movl	$_C_LABEL(__smallkern_end),%ecx
2898368e25fSAaron LI	subl	%eax,%ecx
2908368e25fSAaron LI	shrl	$PGSHIFT,%ecx
2918368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
2928368e25fSAaron LI	fillkpt_nox
2938368e25fSAaron LI
2948368e25fSAaron LI	/* Map some blank space, to keep pa = va. */
2958368e25fSAaron LI	movl	$_C_LABEL(__smallkern_end),%eax
2968368e25fSAaron LI	movl	%esi,%ecx		/* start of BOOTSTRAP TABLES */
2978368e25fSAaron LI	subl	%eax,%ecx
2988368e25fSAaron LI	shrl	$PGSHIFT,%ecx
2998368e25fSAaron LI	fillkpt_blank
3008368e25fSAaron LI
3018368e25fSAaron LI	/* Map the BOOTSTRAP TABLES RW. */
3028368e25fSAaron LI	movl	%esi,%eax		/* start of BOOTSTRAP TABLES */
3038368e25fSAaron LI	movl	$TABLESIZE,%ecx		/* length of BOOTSTRAP TABLES */
3048368e25fSAaron LI	shrl	$PGSHIFT,%ecx
3058368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
3068368e25fSAaron LI	fillkpt_nox
3078368e25fSAaron LI
3088368e25fSAaron LI	/* Map the LAPIC PAGE RW. */
3098368e25fSAaron LI	movl	$0xfee00000,%eax
3108368e25fSAaron LI	movl	$PAGE_SIZE,%ecx	/* size of the LAPIC PAGE */
3118368e25fSAaron LI	shrl	$PGSHIFT,%ecx
3128368e25fSAaron LI	orl	$(PTE_P|PTE_W/*|PTE_PCD*/),%eax
3138368e25fSAaron LI	fillkpt_nox
3148368e25fSAaron LI
3158368e25fSAaron LI	/* Map the ISA I/O MEM RW. */
3168368e25fSAaron LI	movl	$IOM_BEGIN,%eax
3178368e25fSAaron LI	movl	$IOM_SIZE,%ecx	/* size of ISA I/O MEM */
3188368e25fSAaron LI	shrl	$PGSHIFT,%ecx
3198368e25fSAaron LI	orl	$(PTE_P|PTE_W/*|PTE_PCD*/),%eax
3208368e25fSAaron LI	fillkpt_nox
3218368e25fSAaron LI
3228368e25fSAaron LI	/*
3238368e25fSAaron LI	 * Build L2. Linked to L1.
3248368e25fSAaron LI	 */
3258368e25fSAaron LI	leal	(PROC0_PTP2_OFF)(%esi),%ebx
3268368e25fSAaron LI	leal	(PROC0_PTP1_OFF)(%esi),%eax
3278368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
3288368e25fSAaron LI	movl	$(NKL2_KIMG_ENTRIES+1),%ecx
3298368e25fSAaron LI	fillkpt
3308368e25fSAaron LI
3318368e25fSAaron LI	/*
3328368e25fSAaron LI	 * Build L3. Linked to L2.
3338368e25fSAaron LI	 */
3348368e25fSAaron LI	leal	(PROC0_PTP3_OFF)(%esi),%ebx
3358368e25fSAaron LI	leal	(PROC0_PTP2_OFF)(%esi),%eax
3368368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
3378368e25fSAaron LI	movl	$NKL3_KIMG_ENTRIES,%ecx
3388368e25fSAaron LI	fillkpt
3398368e25fSAaron LI
3408368e25fSAaron LI	/*
3418368e25fSAaron LI	 * Build L4. Linked to L3.
3428368e25fSAaron LI	 */
3438368e25fSAaron LI	leal	(PROC0_PML4_OFF)(%esi),%ebx
3448368e25fSAaron LI	leal	(PROC0_PTP3_OFF)(%esi),%eax
3458368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
3468368e25fSAaron LI	movl	$NKL4_KIMG_ENTRIES,%ecx
3478368e25fSAaron LI	fillkpt
3488368e25fSAaron LI
3498368e25fSAaron LI	/* Install recursive top level PDE (one entry) */
3508368e25fSAaron LI	leal	(PROC0_PML4_OFF + PDIR_SLOT_PTE * PDE_SIZE)(%esi),%ebx
3518368e25fSAaron LI	leal	(PROC0_PML4_OFF)(%esi),%eax
3528368e25fSAaron LI	orl	$(PTE_P|PTE_W),%eax
3538368e25fSAaron LI	movl	$1,%ecx
3548368e25fSAaron LI	fillkpt_nox
3558368e25fSAaron LI
3568368e25fSAaron LI	/*
3578368e25fSAaron LI	 * Startup checklist:
3588368e25fSAaron LI	 * 1. Enable PAE (and SSE while here).
3598368e25fSAaron LI	 */
3608368e25fSAaron LI	movl	%cr4,%eax
3618368e25fSAaron LI	orl	$(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax
3628368e25fSAaron LI	movl	%eax,%cr4
3638368e25fSAaron LI
3648368e25fSAaron LI	/*
3658368e25fSAaron LI	 * 2. Set Long Mode Enable in EFER. Also enable the syscall extensions,
3668368e25fSAaron LI	 *    and NOX if available.
3678368e25fSAaron LI	 */
3688368e25fSAaron LI	movl	$MSR_EFER,%ecx
3698368e25fSAaron LI	rdmsr
3708368e25fSAaron LI	xorl	%eax,%eax
3718368e25fSAaron LI	orl	$(EFER_LME|EFER_SCE),%eax
3728368e25fSAaron LI	movl	_C_LABEL(nox_flag),%ebx
3738368e25fSAaron LI	cmpl	$0,%ebx
3748368e25fSAaron LI	je 	.Lskip_NOX
3758368e25fSAaron LI	orl	$(EFER_NXE),%eax
3768368e25fSAaron LI.Lskip_NOX:
3778368e25fSAaron LI	wrmsr
3788368e25fSAaron LI
3798368e25fSAaron LI	/*
3808368e25fSAaron LI	 * 3. Load %cr3 with pointer to PML4.
3818368e25fSAaron LI	 */
3828368e25fSAaron LI	movl	%esi,%eax
3838368e25fSAaron LI	movl	%eax,%cr3
3848368e25fSAaron LI
3858368e25fSAaron LI	/*
3868368e25fSAaron LI	 * 4. Enable paging and the rest of it.
3878368e25fSAaron LI	 */
3888368e25fSAaron LI	movl	%cr0,%eax
3898368e25fSAaron LI	orl	$(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM),%eax
3908368e25fSAaron LI	movl	%eax,%cr0
3918368e25fSAaron LI	jmp	compat
3928368e25fSAaron LIcompat:
3938368e25fSAaron LI
3948368e25fSAaron LI	/*
3958368e25fSAaron LI	 * 5. Not quite done yet, we're now in a compatibility segment, in
3968368e25fSAaron LI	 *    legacy mode. We must jump to a long mode segment. Need to set up
3978368e25fSAaron LI	 *    a GDT with a long mode segment in it to do that.
3988368e25fSAaron LI	 */
3998368e25fSAaron LI	movl	$_C_LABEL(gdt64_lo),%eax
4008368e25fSAaron LI	lgdt	(%eax)
4018368e25fSAaron LI	movl	$_C_LABEL(farjmp64),%eax
4028368e25fSAaron LI	ljmp	*(%eax)
4038368e25fSAaron LI
4048368e25fSAaron LI	.code64
4058368e25fSAaron LIlongmode:
4068368e25fSAaron LI
4078368e25fSAaron LI	/*
4088368e25fSAaron LI	 * We have arrived. Everything is identity-mapped.
4098368e25fSAaron LI	 */
4108368e25fSAaron LI
4118368e25fSAaron LI	/* Store lapicbase. */
4128368e25fSAaron LI	movq	$TABLESIZE,%rdx
4138368e25fSAaron LI	addq	%rsi,%rdx
4148368e25fSAaron LI	movq	%rdx,_C_LABEL(lapicbase)(%rip)
4158368e25fSAaron LI
4168368e25fSAaron LI	/* Store atdevbase. */
4178368e25fSAaron LI	addq	$PAGE_SIZE,%rdx
4188368e25fSAaron LI	movq	%rdx,_C_LABEL(atdevbase)(%rip)
4198368e25fSAaron LI
4208368e25fSAaron LI	/* Set up bootstrap stack. */
4218368e25fSAaron LI	leaq	(PROC0_STK_OFF)(%rsi),%rax
4228368e25fSAaron LI	movq	%rax,_C_LABEL(stkpa)(%rip)
4238368e25fSAaron LI	leaq	(USPACE-FRAMESIZE)(%rax),%rsp
4248368e25fSAaron LI	xorq	%rbp,%rbp			/* mark end of frames */
4258368e25fSAaron LI
4268368e25fSAaron LI	xorw	%ax,%ax
4278368e25fSAaron LI	movw	%ax,%gs
4288368e25fSAaron LI	movw	%ax,%fs
4298368e25fSAaron LI
4308368e25fSAaron LI	/* The first physical page available. */
4318368e25fSAaron LI	leaq	(TABLESIZE)(%rsi),%rdi
4328368e25fSAaron LI
4338368e25fSAaron LI	/*
4348368e25fSAaron LI	 * Continue execution in C.
4358368e25fSAaron LI	 */
4368368e25fSAaron LI	call	_C_LABEL(main)
4378368e25fSAaron LI
4388368e25fSAaron LI	ret
4398368e25fSAaron LIEND(start)
4408368e25fSAaron LI
4418368e25fSAaron LI/* -------------------------------------------------------------------------- */
4428368e25fSAaron LI
4438368e25fSAaron LIENTRY(lidt)
4448368e25fSAaron LI	lidt	(%rdi)
4458368e25fSAaron LI	ret
4468368e25fSAaron LIEND(lidt)
4478368e25fSAaron LI
4488368e25fSAaron LIENTRY(vmmcall)
4498368e25fSAaron LI	vmmcall
4508368e25fSAaron LIEND(vmmcall)
4518368e25fSAaron LI
4528368e25fSAaron LIENTRY(outsb)
4538368e25fSAaron LI	movl	%edx,%ecx
4548368e25fSAaron LI	movl	%edi,%edx
4558368e25fSAaron LI	rep
4568368e25fSAaron LI	outsb
4578368e25fSAaron LI	ret
4588368e25fSAaron LIEND(outsb)
4598368e25fSAaron LI
4608368e25fSAaron LIENTRY(clts)
4618368e25fSAaron LI	clts
4628368e25fSAaron LI	ret
4638368e25fSAaron LIEND(clts)
4648368e25fSAaron LI
4658368e25fSAaron LIENTRY(sti)
4668368e25fSAaron LI	sti
4678368e25fSAaron LI	ret
4688368e25fSAaron LIEND(sti)
4698368e25fSAaron LI
4708368e25fSAaron LIENTRY(lcr8)
4718368e25fSAaron LI	movq	%rdi, %cr8
4728368e25fSAaron LI	ret
4738368e25fSAaron LIEND(lcr8)
4748368e25fSAaron LI
4758368e25fSAaron LIENTRY(rdmsr)
4768368e25fSAaron LI	movq	%rdi, %rcx
4778368e25fSAaron LI	xorq	%rax, %rax
4788368e25fSAaron LI	rdmsr
4798368e25fSAaron LI	shlq	$32, %rdx
4808368e25fSAaron LI	orq	%rdx, %rax
4818368e25fSAaron LI	ret
4828368e25fSAaron LIEND(rdmsr)
4838368e25fSAaron LI
4848368e25fSAaron LIENTRY(cpuid)
4858368e25fSAaron LI	movq	%rbx,%r8
4868368e25fSAaron LI	movq	%rdi,%rax
4878368e25fSAaron LI	movq	%rsi,%rcx
4888368e25fSAaron LI	movq	%rdx,%rsi
4898368e25fSAaron LI	cpuid
4908368e25fSAaron LI	movl	%eax,0(%rsi)
4918368e25fSAaron LI	movl	%ebx,4(%rsi)
4928368e25fSAaron LI	movl	%ecx,8(%rsi)
4938368e25fSAaron LI	movl	%edx,12(%rsi)
4948368e25fSAaron LI	movq	%r8,%rbx
4958368e25fSAaron LI	ret
4968368e25fSAaron LIEND(cpuid)
497