#define _LOCORE
#define ALIGN_DATA .align 8
#define ALIGN_TEXT .align 16,0x90
#define _ALIGN_TEXT ALIGN_TEXT
#include <machine/asm.h>
#include <machine/param.h>
#include <machine/pte.h>
#include <machine/psl.h>
#include <machine/segments.h>
#include <machine/specialreg.h>
#include <machine/trap.h>
#define _KERNEL
#include <machine/bootinfo.h>
#undef _KERNEL
#include "pdir.h"
#include "redef.h"
#define PTE_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(esym)
.globl _C_LABEL(eblob)
.globl _C_LABEL(atdevbase)
.globl _C_LABEL(PDPpaddr)
.globl _C_LABEL(boothowto)
.globl _C_LABEL(bootinfo)
.globl _C_LABEL(biosbasemem)
.globl _C_LABEL(biosextmem)
.globl _C_LABEL(stkpa)
.globl _C_LABEL(stkva)
.globl _C_LABEL(kernpa_start)
.globl _C_LABEL(kernpa_end)
.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(esym), @object
LABEL(esym) .quad 0
END(esym)
.type _C_LABEL(eblob), @object
LABEL(eblob) .quad 0
END(eblob)
.type _C_LABEL(atdevbase), @object
LABEL(atdevbase) .quad 0
END(atdevbase)
.type _C_LABEL(PDPpaddr), @object
LABEL(PDPpaddr) .quad 0
END(PDPpaddr)
.type _C_LABEL(biosbasemem), @object
LABEL(biosbasemem) .long 0
END(biosbasemem)
.type _C_LABEL(biosextmem), @object
LABEL(biosextmem) .long 0
END(biosextmem)
.type _C_LABEL(stkpa), @object
LABEL(stkpa) .quad 0
END(stkpa)
.type _C_LABEL(stkva), @object
LABEL(stkva) .quad 0
END(stkva)
.type _C_LABEL(kernpa_start), @object
LABEL(kernpa_start) .quad 0
END(kernpa_start)
.type _C_LABEL(kernpa_end), @object
LABEL(kernpa_end) .quad 0
END(kernpa_end)
.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
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
movw $0x1234,0x472
movl 4(%esp),%eax
movl %eax,_C_LABEL(boothowto)
movl 12(%esp),%eax
testl %eax,%eax
jz .Lbootinfo_finished
movl (%eax),%ebx
movl $_C_LABEL(bootinfo),%ebp
movl %ebp,%edx
addl $BOOTINFO_MAXSIZE,%ebp
movl %ebx,(%edx)
addl $4,%edx
.Lbootinfo_entryloop:
testl %ebx,%ebx
jz .Lbootinfo_finished
addl $4,%eax
movl (%eax),%ecx
pushl %edi
pushl %esi
pushl %eax
movl (%ecx),%eax
movl %edx,%edi
addl (%ecx),%edx
cmpl %ebp,%edx
jg .Lbootinfo_overflow
movl %ecx,%esi
movl %eax,%ecx
cmpl $BTINFO_MODULELIST,4(%esi)
jne 0f
pushl 12(%esi)
popl _C_LABEL(eblob)
0:
cmpl $BTINFO_PREKERN,4(%esi)
jne 0f
pushl 8(%esi)
popl _C_LABEL(kernpa_start)
pushl 12(%esi)
popl _C_LABEL(kernpa_end)
0:
rep
movsb
popl %eax
popl %esi
popl %edi
subl $1,%ebx
jmp .Lbootinfo_entryloop
.Lbootinfo_overflow:
popl %eax
popl %esi
popl %edi
movl $_C_LABEL(bootinfo),%ebp
movl %ebp,%edx
subl %ebx,(%edx)
.Lbootinfo_finished:
movl 16(%esp),%eax
movl $_C_LABEL(esym),%ebp
movl %eax,(%ebp)
movl 20(%esp),%eax
movl $_C_LABEL(biosextmem),%ebp
movl %eax,(%ebp)
movl 24(%esp),%eax
movl $_C_LABEL(biosbasemem),%ebp
movl %eax,(%ebp)
pushl $PSL_MBO
popfl
movl $_C_LABEL(tmpstk),%esp
xorl %eax,%eax
cpuid
movl %eax,_C_LABEL(cpuid_level)
movl $0x80000001,%eax
cpuid
andl $CPUID_NOX,%edx
jz .Lno_NOX
movl $PTE_NX32,_C_LABEL(nox_flag)
.Lno_NOX:
movl $_C_LABEL(__prekern_end),%edi
movl _C_LABEL(kernpa_end),%eax
testl %eax,%eax
jz 1f
movl %eax,%edi
1:
movl _C_LABEL(esym),%eax
testl %eax,%eax
jz 1f
movl %eax,%edi
1:
movl _C_LABEL(eblob),%eax
testl %eax,%eax
jz 1f
movl %eax,%edi
1:
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 $(PREKERNTEXTOFF - PREKERNBASE),%ecx
shrl $PGSHIFT,%ecx
fillkpt_blank
movl $(PREKERNTEXTOFF - PREKERNBASE),%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(__prekern_end),%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P|PTE_W),%eax
fillkpt_nox
movl $_C_LABEL(__prekern_end),%eax
movl %esi,%ecx
subl %eax,%ecx
shrl $PGSHIFT,%ecx
orl $(PTE_P),%eax
fillkpt_nox
movl %esi,%eax
movl $TABLESIZE,%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(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
movw $GSEL(GDATA_SEL, SEL_KPL),%ax
movw %ax,%ss
leaq (TABLESIZE)(%rsi),%rdi
call _C_LABEL(init_prekern)
ret
END(start)
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)
ENTRY(lidt)
lidt (%rdi)
ret
END(lidt)
ENTRY(rdtsc)
xorq %rax,%rax
rdtsc
shlq $32,%rdx
orq %rdx,%rax
ret
END(rdtsc)
ENTRY(rdseed)
rdseed %rax
jc .Lrdseed_success
movq $(-1),%rax
ret
.Lrdseed_success:
movq %rax,(%rdi)
xorq %rax,%rax
ret
END(rdseed)
ENTRY(rdrand)
rdrand %rax
jc .Lrdrand_success
movq $(-1),%rax
ret
.Lrdrand_success:
movq %rax,(%rdi)
xorq %rax,%rax
ret
END(rdrand)
ENTRY(jump_kernel)
movq _C_LABEL(stkva),%rsp
xorq %rbp,%rbp
callq exec_kernel
END(jump_kernel)