• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4// kvm_gen.cc generates machine code from this file and saves it into kvm.S.h.
5
6// +build
7
8#include "kvm.h"
9
10.global kvm_asm64_enable_long, kvm_asm64_enable_long_end
11kvm_asm64_enable_long:
12.code32
13	mov %cr0, %eax
14	or $0x80000000, %eax
15	mov %eax, %cr0
16	ljmp $SEL_CS64, NEXT_INSN
17.code64
18	mov $SEL_TSS64, %rax
19	ltr %ax
20kvm_asm64_enable_long_end:
21	nop
22
23.global kvm_asm32_paged, kvm_asm32_paged_end
24kvm_asm32_paged:
25.code32
26	mov %cr0, %eax
27	or $0x80000000, %eax
28	mov %eax, %cr0
29kvm_asm32_paged_end:
30	nop
31
32.global kvm_asm32_vm86, kvm_asm32_vm86_end
33kvm_asm32_vm86:
34.code32
35	mov $SEL_TSS32, %ax
36	ltr %ax
37	ljmp $SEL_TSS32_VM86, $0
38kvm_asm32_vm86_end:
39	nop
40
41.global kvm_asm32_paged_vm86, kvm_asm32_paged_vm86_end
42kvm_asm32_paged_vm86:
43.code32
44	mov %cr0, %eax
45	or $0x80000000, %eax
46	mov %eax, %cr0
47	mov $SEL_TSS32, %ax
48	ltr %ax
49	ljmp $SEL_TSS32_VM86, $0
50kvm_asm32_paged_vm86_end:
51	nop
52
53.global kvm_asm64_vm86, kvm_asm64_vm86_end
54kvm_asm64_vm86:
55.code32
56	mov %cr0, %eax
57	or $0x80000000, %eax
58	mov %eax, %cr0
59	mov $SEL_TSS32, %ax
60	ltr %ax
61	ljmp $SEL_TSS32_VM86, $0
62kvm_asm64_vm86_end:
63	nop
64
65.global kvm_asm16_cpl3, kvm_asm16_cpl3_end
66kvm_asm16_cpl3:
67.code16
68	mov %cr0, %eax
69	or $1, %eax
70	mov %eax, %cr0
71	mov $SEL_TSS16, %ax
72	ltr %ax
73	mov $SEL_DS16_CPL3, %ax
74	mov %ax, %ds
75	mov %ax, %es
76	mov %ax, %fs
77	mov %ax, %gs
78	mov $0x100, %sp
79	movw $PREFIX_SIZE, 0x100
80	movw $SEL_CS16_CPL3, 0x102
81	movw $0x100, 0x104
82	movw $SEL_DS16_CPL3, 0x106
83	lret
84kvm_asm16_cpl3_end:
85	nop
86
87.global kvm_asm64_cpl3, kvm_asm64_cpl3_end
88kvm_asm64_cpl3:
89.code32
90	mov %cr0, %eax
91	or $0x80000000, %eax
92	mov %eax, %cr0
93	ljmp $SEL_CS64, NEXT_INSN
94.code64
95	mov $SEL_TSS64, %rax
96	ltr %ax
97	mov $SEL_DS64_CPL3, %rax
98	mov %ax, %ds
99	mov %ax, %es
100	mov %ax, %fs
101	mov %ax, %gs
102	mov $ADDR_STACK0, %rsp
103	movq $PREFIX_SIZE, 0(%rsp)
104	movq $SEL_CS64_CPL3, 4(%rsp)
105	movq $ADDR_STACK0, 8(%rsp)
106	movq $SEL_DS64_CPL3, 12(%rsp)
107	lret
108kvm_asm64_cpl3_end:
109	nop
110
111.global kvm_asm64_init_vm, kvm_asm64_init_vm_end
112kvm_asm64_init_vm:
113.code32
114	// CR0.PG = 1
115	mov %cr0, %eax
116	or $0x80000000, %eax
117	mov %eax, %cr0
118	ljmp $SEL_CS64, NEXT_INSN
119.code64
120	mov $SEL_TSS64, %rax
121	ltr %ax
122
123	// Enable and lock non-SMM VM
124	mov $MSR_IA32_FEATURE_CONTROL, %rcx
125	rdmsr
126	or $0x5, %rax
127	wrmsr
128
129	// CR4.VMXE = 1
130	mov %cr4, %rax
131	or $0x2000, %rax
132	mov %rax, %cr4
133
134	// Write VMCS revision into VMXON and VMCS regions
135	mov $MSR_IA32_VMX_BASIC, %rcx
136	rdmsr
137	mov $ADDR_VAR_VMXON, %rdx
138	mov %eax, (%rdx)
139	mov $ADDR_VAR_VMCS, %rdx
140	mov %eax, (%rdx)
141
142	mov $ADDR_VAR_VMXON_PTR, %rax
143	vmxon (%rax)
144	mov $ADDR_VAR_VMCS_PTR, %rax
145	vmclear (%rax)
146	vmptrld (%rax)
147
148#define VMSET(FIELD, VAL)	\
149	mov $FIELD, %rdx;	\
150	mov VAL, %rax;		\
151	vmwrite %rax, %rdx;	\
152	/**/
153
154#define VMSET_LIMITED(FIELD, VAL, MSR)	\
155	mov $MSR, %rcx;		\
156	rdmsr;			\
157	or VAL, %rax;		\
158	and %rdx, %rax;		\
159	mov $FIELD, %rdx;	\
160	vmwrite %rax, %rdx;	\
161	/**/
162
163	VMSET_LIMITED(0x00004000, $0x3f, 0x481) // Pin-based VM-execution controls
164	//VMSET_LIMITED(0x00004002, $0x61999e84, 0x482) // Primary processor-based VM-execution controls
165	VMSET(0x00004002, $0xf3999e84)
166	VMSET(0x0000401E, $((1<<0) | (1<<7))) // Secondary processor-based VM-execution controls
167	VMSET_LIMITED(0x0000400C, $0x36fff, 0x483) // VM-exit controls (F6FFF)
168	VMSET_LIMITED(0x00004012, $0x17ff, 0x484) // VM-entry controls (51FF)
169
170	VMSET(0x00002C04, $0) // Host IA32_PERF_GLOBAL_CTR
171	VMSET(0x00002800, $0xffffffffffffffff) // VMCS link pointer
172
173	VMSET(0x00000C02, $SEL_CS64) // host CS
174
175	mov $SEL_DS64, %rax
176	mov $0x00000C00, %rdx // host ES
177	vmwrite %rax, %rdx
178	mov $0x00000C04, %rdx // host SS
179	vmwrite %rax, %rdx
180	mov $0x00000C06, %rdx // host DS
181	vmwrite %rax, %rdx
182	mov $0x00000C08, %rdx // host FS
183	vmwrite %rax, %rdx
184	mov $0x00000C0A, %rdx // host GS
185	vmwrite %rax, %rdx
186	mov $SEL_TSS64, %rax
187	mov $0x00000C0C, %rdx // host TR
188	vmwrite %rax, %rdx
189
190	VMSET(0x00002C02, $0x500) // host EFER
191
192	VMSET(0x00004C00, $SEL_CS64) // Host IA32_SYSENTER_CS
193	VMSET(0x00006C10, $0) // Host IA32_SYSENTER_ESP
194	VMSET(0x00006C12, $0) // Host IA32_SYSENTER_EIP
195
196	mov %cr0, %rax
197	VMSET(0x00006C00, %rax) // host CR0
198	mov %cr3, %rax
199	VMSET(0x00006C02, %rax) // host CR3
200	mov %cr4, %rax
201	VMSET(0x00006C04, %rax) // host CR4
202
203	VMSET(0x00006C06, $0) // host FS base
204	VMSET(0x00006C08, $0) // host GS base
205	VMSET(0x00006C0A, $ADDR_VAR_TSS64) // host TR base
206
207	VMSET(0x00006C0C, $ADDR_GDT) // host GDTR base
208	VMSET(0x00006C0E, $ADDR_VAR_IDT) // host IDTR base
209
210	VMSET(0x00006C14, $0) // host RSP
211	VMSET(0x00006C16, ADDR_VAR_VMEXIT_PTR) // host RIP
212
213	VMSET(0x00000000, $1) // VPID
214	VMSET(0x00000002, $0) // Posted-interrupt notification vector
215	//VMSET(0x00000004, $0) // EPTP index
216
217	VMSET(0x00002000, $0) // Address of I/O bitmap A
218	VMSET(0x00002002, $0) // Address of I/O bitmap B
219	VMSET(0x00002004, $0) // Address of MSR bitmaps
220	VMSET(0x00002006, $0) // VM-exit MSR-store address
221
222	mov $0x277, %rcx
223	rdmsr
224	shl $32, %rdx
225	or %rdx, %rax
226	VMSET(0x00002C00, %rax) // Host IA32_PAT
227
228	VMSET(0x00004004, $0) // Exception bitmap
229	VMSET(0x0000400A, $0) // CR3-target count
230	VMSET(0x0000400E, $0) // VM-exit MSR-store count
231	VMSET(0x00004010, $0) // VM-exit MSR-load count
232	VMSET(0x00004016, $0) // VM-entry interruption-information field
233	VMSET(0x00004014, $0) // VM-entry MSR-load count
234
235	VMSET(0x00006000, $0xffffffffffffffff) // CR0 guest/host mask
236	VMSET(0x00006002, $0xffffffffffffffff) // CR4 guest/host mask
237
238	VMSET(0x0000201C, $0) // EOI-exit bitmap 0
239	VMSET(0x0000201E, $0) // EOI-exit bitmap 1
240	VMSET(0x00002020, $0) // EOI-exit bitmap 2
241	VMSET(0x00002022, $0) // EOI-exit bitmap 3
242
243	VMSET(0x00000800, $SEL_DS64) // Guest ES selector
244	VMSET(0x00000802, $SEL_CS64) // Guest CS selector
245	VMSET(0x00000804, $SEL_DS64) // Guest SS selector
246	VMSET(0x00000806, $SEL_DS64) // Guest DS selector
247	VMSET(0x00000808, $SEL_DS64) // Guest FS selector
248	VMSET(0x0000080A, $SEL_DS64) // Guest GS selector
249	VMSET(0x0000080C, $0) // Guest LDTR selector
250	VMSET(0x0000080E, $SEL_TSS64) // Guest TR selector
251
252	VMSET(0x00006812, $0) // Guest LDTR base
253	VMSET(0x00006814, $ADDR_VAR_TSS64) // Guest TR base
254	VMSET(0x00006816, $ADDR_GDT) // Guest GDTR base
255	VMSET(0x00006818, $ADDR_VAR_IDT) // Guest IDTR base
256
257	VMSET(0x00004800, $0xfffff) // Guest ES limit
258	VMSET(0x00004802, $0xfffff) // Guest CS limit
259	VMSET(0x00004804, $0xfffff) // Guest SS limit
260	VMSET(0x00004806, $0xfffff) // Guest DS limit
261	VMSET(0x00004808, $0xfffff) // Guest FS limit
262	VMSET(0x0000480A, $0xfffff) // Guest GS limit
263	VMSET(0x0000480C, $0) // Guest LDTR limit
264	VMSET(0x0000480E, $0x1fff) // Guest TR limit
265	VMSET(0x00004810, $0x1fff) // Guest GDTR limit
266	VMSET(0x00004812, $0x1fff) // Guest IDTR limit
267
268	VMSET(0x00004814, $0x4093) // Guest ES access rights
269	VMSET(0x00004816, $0x209b) // Guest CS access rights
270	VMSET(0x00004818, $0x4093) // Guest SS access rights
271	VMSET(0x0000481A, $0x4093) // Guest DS access rights
272	VMSET(0x0000481C, $0x4093) // Guest FS access rights
273	VMSET(0x0000481E, $0x4093) // Guest GS access rights
274	VMSET(0x00004820, $0x82) // Guest LDTR access rights
275	VMSET(0x00004822, $0x8b) // Guest TR access rights
276
277	VMSET(0x0000681C, $0) // Guest RSP
278	VMSET(0x0000681E, $ADDR_VAR_USER_CODE) // Guest RIP
279	VMSET(0x00006820, $((1<<1))) // Guest RFLAGS
280	VMSET(0x00002806, $0x500) // Guest IA32_EFER
281	VMSET(0x0000280A, $0) // Guest PDPTE0
282	VMSET(0x0000280C, $0) // Guest PDPTE1
283	VMSET(0x0000280E, $0) // Guest PDPTE2
284	VMSET(0x00002810, $0) // Guest PDPTE3
285
286	mov %cr0, %rax
287	VMSET(0x00006800, %rax) // Guest CR0
288	mov %cr3, %rax
289	VMSET(0x00006802, %rax) // Guest CR3
290	mov %cr4, %rax
291	VMSET(0x00006804, %rax) // Guest CR4
292
293	// Write 1 additional random field.
294	mov $ADDR_VAR_VMWRITE_FLD, %rax
295	mov (%rax), %rdx
296	mov $ADDR_VAR_VMWRITE_VAL, %rax
297	mov (%rax), %rcx
298	xor %rax, %rax
299	vmread %rdx, %rax
300	xor %rcx, %rax
301	vmwrite %rax, %rdx
302
303	vmlaunch
304
305	mov $0x00004400, %rdx
306	vmread %rdx, %rax
307	hlt
308kvm_asm64_init_vm_end:
309	nop
310
311.global kvm_asm64_vm_exit, kvm_asm64_vm_exit_end
312kvm_asm64_vm_exit:
313.code64
314	//vmresume
315	mov $0x00004400, %rbx // VM-instruction error
316	vmread %rbx, %rdx
317	mov $0x00004402, %rbx // Exit reason
318	vmread %rbx, %rcx
319	mov $0x00006400, %rax // Exit qualification
320	vmread %rax, %rax
321	mov $0x0000681E, %rbx // Guest RIP
322	vmread %rbx, %rbx
323	hlt
324kvm_asm64_vm_exit_end:
325	nop
326