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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
.section .boot,"ax"
.code16
.global boot
boot:
cli
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
mov $0x7c00, %sp
mov $packet, %si
mov $0x42, %ah
int $0x13
jc stopped
in $0x92, %al
or $2, %al
out %al, $0x92
lgdt descriptor
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
ljmpl $8, $protected
stopped:
hlt
jmp stopped
.balign 8
packet:
.byte 16, 0
.word 120
.word 0, 0x1000
.quad 1
.global gdt
gdt:
.quad 0
.quad 0x00cf9a000000ffff
.quad 0x00cf92000000ffff
.quad 0x00af9a000000ffff
.quad 0x00affa000000ffff
.quad 0x00cff2000000ffff
.quad 0, 0
descriptor:
.word 63
.long gdt
.org 510
.word 0xaa55
.section .text
.code32
protected:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
mov $0x90000, %esp
cld
mov $0x70000, %edi
xor %eax, %eax
mov $3072, %ecx
rep stosl
movl $0x71003, 0x70000
movl $0x72003, 0x71000
mov $0x72000, %edi
mov $0x83, %eax
mov $512, %ecx
1:
mov %eax, (%edi)
add $0x200000, %eax
add $8, %edi
loop 1b
mov $0x20, %eax
mov %eax, %cr4
mov $0x70000, %eax
mov %eax, %cr3
mov $0xc0000080, %ecx
rdmsr
or $0x900, %eax
wrmsr
mov %cr0, %eax
or $0x80010000, %eax
mov %eax, %cr0
ljmp $0x18, $longmode
.code64
longmode:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
mov $0x90000, %rsp
lea __bss_start(%rip), %rdi
lea __bss_end(%rip), %rcx
sub %rdi, %rcx
xor %eax, %eax
rep stosb
call guest
2:
hlt
jmp 2b
.global probe
probe:
mov %rsp, recovery_stack(%rip)
lea 5f(%rip), %rax
mov %rax, recovery_address(%rip)
test %edi, %edi
jz 3f
cmp $1, %edi
je 4f
call *%rsi
jmp 5f
3:
mov (%rsi), %rax
jmp 5f
4:
movq $0xc3, (%rsi)
5:
ret
.global probe_user
probe_user:
mov %rsp, recovery_stack(%rip)
lea 9f(%rip), %rax
mov %rax, recovery_address(%rip)
pushq $0x2b
pushq $0x86000
pushq $2
pushq $0x23
lea 6f(%rip), %rax
push %rax
iretq
6:
test %edi, %edi
jz 7f
cmp $1, %edi
je 8f
call *%rsi
int $0x80
7:
mov (%rsi), %rax
int $0x80
8:
movq $0xc3, (%rsi)
int $0x80
9:
ret
.global completed
completed:
pushq $0
jmp recover
.global pagefault
pagefault:
movq $14, observed_vector(%rip)
jmp recover
.global protection
protection:
movq $13, observed_vector(%rip)
recover:
push %rax
mov 8(%rsp), %rax
mov %rax, observed_error(%rip)
mov recovery_address(%rip), %rax
mov %rax, 16(%rsp)
mov recovery_stack(%rip), %rax
mov %rax, 40(%rsp)
movq $0x18, 24(%rsp)
movq $0x10, 48(%rsp)
pop %rax
add $8, %rsp
iretq
.section .note.GNU-stack,"",@progbits
|