1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
.section .text
.global _start
.type _start, @function
_start:
cli
mov $_stack_top, %esp
push %ebx // save the address of the multiboot struct
mov $0x80000000, %eax // check CPUID extended functions
cpuid
cmp $0x80000001, %eax
jb panic_early
mov $0x80000001, %eax
cpuid
test $(1<<29), %edx // check long mode support
jz panic_early
mov %cr4, %eax
or $(1<<5 | 1<<9 | 1<<10), %eax // PAE | SSE | SSE
mov %eax, %cr4
call pml4_identity_init
mov $pml4_identity, %eax
mov %eax, %cr3
mov $0xC0000080, %ecx // EFER MSR
rdmsr
or $(1 | 1<<8 | 1<<11), %eax // syscall/ret | long mode | NX
wrmsr
mov %cr0, %eax
or $0x80000002, %eax // enable paging, coprocessor monitoring
and $(~4), %eax // disable coprocessor emulation
mov %eax, %cr0
call gdt_init
lgdt (lgdt_arg)
pop %edi
mov $(2 << 3), %eax // SEG_r0data
mov %eax, %ds
mov %eax, %ss
mov %eax, %es
mov %eax, %fs
mov %eax, %gs
ljmp $(1 << 3), $boot64 // SEG_r0code
panic_early:
// output a vga Fuck
movl $0x4F754F46, 0xB872A
movl $0x4F6B4F63, 0xB872E
jmp cpu_halt
.global cpu_shutdown
.type cpu_shutdown, @function
cpu_shutdown:
/* This quits QEMU. While I couldn't find this officially documented anywhere,
* it is used by QEMU in tests/tcg/i386/system/boot.S (as of commit 40d6ee), so
* I assume that this is safe-ish to use */
mov $0x604, %edx
mov $0x2000, %eax
outw %ax, %dx
.global cpu_halt
.type cpu_halt, @function
cpu_halt:
cli
1: hlt
jmp 1b
.global cpu_pause
.type cpu_pause, @function
cpu_pause:
sti
hlt
cli
ret
|