#define _LOCORE
#define LOCORE
#include "asm.h"
#include "pdir.h"
#include <machine/param.h>
#include <machine/segments.h>
#include <machine/specialreg.h>
#define PSL_MBO 0x00000002
#define PTE_P 0x001
#define PTE_W 0x002
#define PTE_PCD 0x010
#define PG_NX32 0x80000000
#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
#define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES
#define PROC0_PML4_OFF 0
#define PROC0_STK_OFF (PROC0_PML4_OFF + 1 * PAGE_SIZE)
#define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * PAGE_SIZE)
#define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * PAGE_SIZE)
#define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * PAGE_SIZE)
#define TABLESIZE \
((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES) \
* PAGE_SIZE)
#define fillkpt \
cmpl $0,%ecx ; \
je 2f ; \
1: movl $0,(PDE_SIZE-4)(%ebx) ; \
movl %eax,(%ebx) ; \
addl $PDE_SIZE,%ebx ; \
addl $PAGE_SIZE,%eax ; \
loop 1b ; \
2: ;
#define fillkpt_nox \
cmpl $0,%ecx ; \
je 2f ; \
pushl %ebp ; \
movl _C_LABEL(nox_flag),%ebp ; \
1: movl %ebp,(PDE_SIZE-4)(%ebx) ; \
movl %eax,(%ebx) ; \
addl $PDE_SIZE,%ebx ; \
addl $PAGE_SIZE,%eax ; \
loop 1b ; \
popl %ebp ; \
2: ;
#define fillkpt_blank \
cmpl $0,%ecx ; \
je 2f ; \
1: movl $0,(PDE_SIZE-4)(%ebx) ; \
movl $0,(%ebx) ; \
addl $PDE_SIZE,%ebx ; \
loop 1b ; \
2: ;
.data
.globl _C_LABEL(tablesize)
.globl _C_LABEL(nox_flag)
.globl _C_LABEL(cpuid_level)
.globl _C_LABEL(PDPpaddr)
.globl _C_LABEL(atdevbase)
.globl _C_LABEL(lapicbase)
.globl _C_LABEL(stkpa)
.globl _C_LABEL(stkva)
.type _C_LABEL(tablesize), @object
_C_LABEL(tablesize): .long TABLESIZE
END(tablesize)
.type _C_LABEL(nox_flag), @object
LABEL(nox_flag) .long 0
END(nox_flag)
.type _C_LABEL(cpuid_level), @object
LABEL(cpuid_level) .long -1
END(cpuid_level)
.type _C_LABEL(PDPpaddr), @object
LABEL(PDPpaddr) .quad 0
END(PDPpaddr)
.type _C_LABEL(atdevbase), @object
LABEL(atdevbase) .quad 0
END(atdevbase)
.type _C_LABEL(lapicbase), @object
LABEL(lapicbase) .quad 0
END(lapicbase)
.type _C_LABEL(stkpa), @object
LABEL(stkpa) .quad 0
END(stkpa)
.type _C_LABEL(stkva), @object
LABEL(stkva) .quad 0
END(stkva)
.globl gdt64_lo
.globl gdt64_start
#define GDT64_LIMIT gdt64_end-gdt64_start-1
.type _C_LABEL(gdt64_lo), @object
LABEL(gdt64_lo)
.word GDT64_LIMIT
.quad gdt64_start
END(gdt64_lo)
.align 64
#undef GDT64_LIMIT
.type _C_LABEL(gdt64_start), @object
LABEL(gdt64_start)
.quad 0x0000000000000000
.quad 0x00af9a000000ffff
.quad 0x00cf92000000ffff
.quad 0x0000000000000000
.quad 0x0000000000000000
END(gdt64_start)
gdt64_end:
.type _C_LABEL(farjmp64), @object
_C_LABEL(farjmp64):
.long longmode
.word GSEL(GCODE_SEL, SEL_KPL)
END(farjmp64)
.size tmpstk, tmpstk - .
.space 512
tmpstk:
.text
ENTRY(start)
.code32
xorl %eax,%eax
movl $_C_LABEL(tmpstk),%esp
pushl $PSL_MBO
popfl
xorl %eax,%eax
cpuid
movl %eax,_C_LABEL(cpuid_level)
movl $0x80000001,%eax
cpuid
andl $CPUID_NOX,%edx
jz .Lno_NOX
movl $PG_NX32,_C_LABEL(nox_flag)
.Lno_NOX:
movl $_C_LABEL(__smallkern_end),%edi
movl %edi,%esi
addl $PGOFSET,%esi
andl $~PGOFSET,%esi
movl $_C_LABEL(PDPpaddr),%ebp
movl %esi,(%ebp)
movl $0,4(%ebp)
movl %esi,%edi
xorl %eax,%eax
cld
movl $TABLESIZE,%ecx
shrl $2,%ecx
rep
stosl
leal (PROC0_PTP1_OFF)(%esi),%ebx
movl $(SMALLKERNTEXTOFF - SMALLKERNBASE),%ecx
shrl $PGSHIFT,%ecx
fillkpt_blank
movl $(SMALLKERNTEXTOFF - SMALLKERNBASE),%eax
movl $_C_LABEL(__rodata_start),%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P),%eax
fillkpt
movl $_C_LABEL(__rodata_start),%eax
movl $_C_LABEL(__data_start),%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P),%eax
fillkpt_nox
movl $_C_LABEL(__data_start),%eax
movl $_C_LABEL(__smallkern_end),%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P|PTE_W),%eax
fillkpt_nox
movl $_C_LABEL(__smallkern_end),%eax
movl %esi,%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
fillkpt_blank
movl %esi,%eax
movl $TABLESIZE,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P|PTE_W),%eax
fillkpt_nox
movl $0xfee00000,%eax
movl $PAGE_SIZE,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P|PTE_W),%eax
fillkpt_nox
movl $IOM_BEGIN,%eax
movl $IOM_SIZE,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P|PTE_W),%eax
fillkpt_nox
leal (PROC0_PTP2_OFF)(%esi),%ebx
leal (PROC0_PTP1_OFF)(%esi),%eax
orl $(PTE_P|PTE_W),%eax
movl $(NKL2_KIMG_ENTRIES+1),%ecx
fillkpt
leal (PROC0_PTP3_OFF)(%esi),%ebx
leal (PROC0_PTP2_OFF)(%esi),%eax
orl $(PTE_P|PTE_W),%eax
movl $NKL3_KIMG_ENTRIES,%ecx
fillkpt
leal (PROC0_PML4_OFF)(%esi),%ebx
leal (PROC0_PTP3_OFF)(%esi),%eax
orl $(PTE_P|PTE_W),%eax
movl $NKL4_KIMG_ENTRIES,%ecx
fillkpt
leal (PROC0_PML4_OFF + PDIR_SLOT_PTE * PDE_SIZE)(%esi),%ebx
leal (PROC0_PML4_OFF)(%esi),%eax
orl $(PTE_P|PTE_W),%eax
movl $1,%ecx
fillkpt_nox
movl %cr4,%eax
orl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax
movl %eax,%cr4
movl $MSR_EFER,%ecx
rdmsr
xorl %eax,%eax
orl $(EFER_LME|EFER_SCE),%eax
movl _C_LABEL(nox_flag),%ebx
cmpl $0,%ebx
je .Lskip_NOX
orl $(EFER_NXE),%eax
.Lskip_NOX:
wrmsr
movl %esi,%eax
movl %eax,%cr3
movl %cr0,%eax
orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM),%eax
movl %eax,%cr0
jmp compat
compat:
movl $_C_LABEL(gdt64_lo),%eax
lgdt (%eax)
movl $_C_LABEL(farjmp64),%eax
ljmp *(%eax)
.code64
longmode:
movq $TABLESIZE,%rdx
addq %rsi,%rdx
movq %rdx,_C_LABEL(lapicbase)(%rip)
addq $PAGE_SIZE,%rdx
movq %rdx,_C_LABEL(atdevbase)(%rip)
leaq (PROC0_STK_OFF)(%rsi),%rax
movq %rax,_C_LABEL(stkpa)(%rip)
leaq (USPACE-FRAMESIZE)(%rax),%rsp
xorq %rbp,%rbp
xorw %ax,%ax
movw %ax,%gs
movw %ax,%fs
leaq (TABLESIZE)(%rsi),%rdi
call _C_LABEL(main)
ret
END(start)
ENTRY(lidt)
lidt (%rdi)
ret
END(lidt)
ENTRY(vmmcall)
vmmcall
END(vmmcall)
ENTRY(outsb)
movl %edx,%ecx
movl %edi,%edx
rep
outsb
ret
END(outsb)
ENTRY(clts)
clts
ret
END(clts)
ENTRY(sti)
sti
ret
END(sti)
ENTRY(lcr8)
movq %rdi, %cr8
ret
END(lcr8)
ENTRY(rdmsr)
movq %rdi, %rcx
xorq %rax, %rax
rdmsr
shlq $32, %rdx
orq %rdx, %rax
ret
END(rdmsr)
ENTRY(cpuid)
movq %rbx,%r8
movq %rdi,%rax
movq %rsi,%rcx
movq %rdx,%rsi
cpuid
movl %eax,0(%rsi)
movl %ebx,4(%rsi)
movl %ecx,8(%rsi)
movl %edx,12(%rsi)
movq %r8,%rbx
ret
END(cpuid)