HyperPlatform Programmer's Reference
x86.asm
Go to the documentation of this file.
1 ; Copyright (c) 2015-2017, Satoshi Tanda. All rights reserved.
2 ; Use of this source code is governed by a MIT-style license that can be
3 ; found in the LICENSE file.
4 
5 ;
6 ; This module implements all assembler code
7 ;
8 .686p
9 .model flat, stdcall
10 .MMX
11 .XMM
12 
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;
15 ; References to C functions
16 ;
17 EXTERN VmmVmExitHandler@4 : PROC
18 EXTERN VmmVmxFailureHandler@4 : PROC
19 EXTERN UtilDumpGpRegisters@8 : PROC
20 
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;
23 ; constants
24 ;
25 .CONST
26 
27 VMX_OK EQU 0
28 VMX_ERROR_WITH_STATUS EQU 1
29 VMX_ERROR_WITHOUT_STATUS EQU 2
30 
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;
33 ; macros
34 ;
35 
36 ; Dumps all general purpose registers and a flag register.
37 ASM_DUMP_REGISTERS MACRO
38  pushfd
39  pushad ; -4 * 8
40  mov ecx, esp ; all_regs
41  mov edx, esp
42  add edx, 4*9 ; stack_pointer
43 
44  push ecx
45  push edx
46  call UtilDumpGpRegisters@8 ; UtilDumpGpRegisters(all_regs, stack_pointer);
47 
48  popad
49  popfd
50 ENDM
51 
52 
53 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54 ;
55 ; implementations
56 ;
57 .CODE
58 
59 ; bool __stdcall AsmInitializeVm(
60 ; _In_ void (*vm_initialization_routine)(_In_ ULONG_PTR, _In_ ULONG_PTR,
61 ; _In_opt_ void *),
62 ; _In_opt_ void *context);
63 AsmInitializeVm PROC vm_initialization_routine, context
64  pushfd
65  pushad ; -4 * 8
66 
67  mov ecx, esp ; esp
68 
69  ; vm_initialization_routine(rsp, asmResumeVm, context)
70  push context
71  push asmResumeVm
72  push ecx
73  call vm_initialization_routine
74 
75  popad
76  popfd
77  xor eax, eax ; return false
78  ret
79 
80  ; This is where the virtualized guest start to execute after successful
81  ; vmlaunch.
82 asmResumeVm:
83  nop ; keep this nop for ease of debugging
84  popad
85  popfd
86  ASM_DUMP_REGISTERS
87  xor eax, eax
88  inc eax ; return true
89  ret
90 AsmInitializeVm ENDP
91 
92 ; void __stdcall AsmVmmEntryPoint();
93 AsmVmmEntryPoint PROC
94  ; No need to save the flag registers since it is restored from the VMCS at
95  ; the time of vmresume.
96  pushad ; -4 * 8
97  mov eax, esp
98 
99  ; save volatile XMM registers
100  sub esp, 68h ; +8 for alignment
101  mov ecx, cr0
102  mov edx, ecx ; save original CR0
103  and cl, 0f1h ; clear MP, EM, TS bits for floating point access
104  mov cr0, ecx ; update CR0
105  movaps xmmword ptr [esp + 0h], xmm0
106  movaps xmmword ptr [esp + 10h], xmm1
107  movaps xmmword ptr [esp + 20h], xmm2
108  movaps xmmword ptr [esp + 30h], xmm3
109  movaps xmmword ptr [esp + 40h], xmm4
110  movaps xmmword ptr [esp + 50h], xmm5
111  mov cr0, edx ; restore the original CR0
112 
113  push eax
114  call VmmVmExitHandler@4 ; bool vm_continue = VmmVmExitHandler(guest_context);
115 
116  ; restore XMM registers
117  mov ecx, cr0
118  mov edx, ecx ; save original CR0
119  and cl, 0f1h ; clear MP, EM, TS bits for floating point access
120  mov cr0, ecx ; update CR0
121  movaps xmm0, xmmword ptr [esp + 0h]
122  movaps xmm1, xmmword ptr [esp + 10h]
123  movaps xmm2, xmmword ptr [esp + 20h]
124  movaps xmm3, xmmword ptr [esp + 30h]
125  movaps xmm4, xmmword ptr [esp + 40h]
126  movaps xmm5, xmmword ptr [esp + 50h]
127  mov cr0, edx ; restore the original CR0
128  add esp, 68h ; +8 for alignment
129 
130  test al, al
131  jz exitVm ; if (!vm_continue) jmp exitVm
132 
133  popad
134  vmresume
135  jmp vmxError
136 
137 exitVm:
138  ; Executes vmxoff and ends virtualization
139  ; eax = Guest's eflags
140  ; edx = Guest's esp
141  ; ecx = Guest's eip for the next instruction
142  popad
143  vmxoff
144  jz vmxError ; if (ZF) jmp
145  jc vmxError ; if (CF) jmp
146  push eax
147  popfd ; eflags <= GurstFlags
148  mov esp, edx ; esp <= GuestRsp
149  push ecx
150  ret ; jmp AddressToReturn
151 
152 vmxError:
153  ; Diagnose a critical error
154  pushfd
155  pushad ; -4 * 8
156  mov ecx, esp ; all_regs
157  push ecx
158  call VmmVmxFailureHandler@4 ; VmmVmxFailureHandler(all_regs);
159  int 3
160 AsmVmmEntryPoint ENDP
161 
162 ; unsigned char __stdcall AsmVmxCall(_In_ ULONG_PTR hypercall_number,
163 ; _In_opt_ void *context);
164 AsmVmxCall PROC hypercall_number, context
165  mov ecx, hypercall_number
166  mov edx, context
167  vmcall ; vmcall(hypercall_number, context)
168  jz errorWithCode ; if (ZF) jmp
169  jc errorWithoutCode ; if (CF) jmp
170  xor eax, eax ; return VMX_OK
171  ret
172 
173 errorWithoutCode:
174  mov eax, VMX_ERROR_WITHOUT_STATUS
175  ret
176 
177 errorWithCode:
178  mov eax, VMX_ERROR_WITH_STATUS
179  ret
180 AsmVmxCall ENDP
181 
182 ; void __stdcall AsmWriteGDT(_In_ const GDTR *gdtr);
183 AsmWriteGDT PROC gdtr
184  mov ecx, gdtr
185  lgdt fword ptr [ecx]
186  ret
187 AsmWriteGDT ENDP
188 
189 ; void __stdcall AsmReadGDT(_Out_ GDTR *gdtr);
190 AsmReadGDT PROC gdtr
191  mov ecx, gdtr
192  sgdt [ecx]
193  ret
194 AsmReadGDT ENDP
195 
196 ; void __stdcall AsmWriteLDTR(_In_ USHORT local_segmeng_selector);
197 AsmWriteLDTR PROC local_segmeng_selector
198  mov ecx, local_segmeng_selector
199  lldt cx
200  ret
201 AsmWriteLDTR ENDP
202 
203 ; USHORT __stdcall AsmReadLDTR();
204 AsmReadLDTR PROC
205  sldt ax
206  ret
207 AsmReadLDTR ENDP
208 
209 ; void __stdcall AsmWriteTR(_In_ USHORT task_register);
210 AsmWriteTR PROC task_register
211  mov ecx, task_register
212  ltr cx
213  ret
214 AsmWriteTR ENDP
215 
216 ; USHORT __stdcall AsmReadTR();
217 AsmReadTR PROC
218  str ax
219  ret
220 AsmReadTR ENDP
221 
222 ; void __stdcall AsmWriteES(_In_ USHORT segment_selector);
223 AsmWriteES PROC segment_selector
224  mov ecx, segment_selector
225  mov es, cx
226  ret
227 AsmWriteES ENDP
228 
229 ; USHORT __stdcall AsmReadES();
230 AsmReadES PROC
231  mov ax, es
232  ret
233 AsmReadES ENDP
234 
235 ; void __stdcall AsmWriteCS(_In_ USHORT segment_selector);
236 AsmWriteCS PROC segment_selector
237  mov ecx, segment_selector
238  mov cs, cx
239  ret
240 AsmWriteCS ENDP
241 
242 ; USHORT __stdcall AsmReadCS();
243 AsmReadCS PROC
244  mov ax, cs
245  ret
246 AsmReadCS ENDP
247 
248 ; void __stdcall AsmWriteSS(_In_ USHORT segment_selector);
249 AsmWriteSS PROC segment_selector
250  mov ecx, segment_selector
251  mov ss, cx
252  ret
253 AsmWriteSS ENDP
254 
255 ; USHORT __stdcall AsmReadSS();
256 AsmReadSS PROC
257  mov ax, ss
258  ret
259 AsmReadSS ENDP
260 
261 ; void __stdcall AsmWriteDS(_In_ USHORT segment_selector);
262 AsmWriteDS PROC segment_selector
263  mov ecx, segment_selector
264  mov ds, cx
265  ret
266 AsmWriteDS ENDP
267 
268 ; USHORT __stdcall AsmReadDS();
269 AsmReadDS PROC
270  mov ax, ds
271  ret
272 AsmReadDS ENDP
273 
274 ; void __stdcall AsmWriteFS(_In_ USHORT segment_selector);
275 AsmWriteFS PROC segment_selector
276  mov ecx, segment_selector
277  mov fs, cx
278  ret
279 AsmWriteFS ENDP
280 
281 ; USHORT __stdcall AsmReadFS();
282 AsmReadFS PROC
283  mov ax, fs
284  ret
285 AsmReadFS ENDP
286 
287 ; void __stdcall AsmWriteGS(_In_ USHORT segment_selector);
288 AsmWriteGS PROC segment_selector
289  mov ecx, segment_selector
290  mov gs, cx
291  ret
292 AsmWriteGS ENDP
293 
294 ; USHORT __stdcall AsmReadGS();
295 AsmReadGS PROC
296  mov ax, gs
297  ret
298 AsmReadGS ENDP
299 
300 ; ULONG_PTR __stdcall AsmLoadAccessRightsByte(
301 ; _In_ ULONG_PTR segment_selector);
302 AsmLoadAccessRightsByte PROC segment_selector
303  mov ecx, segment_selector
304  lar eax, ecx
305  ret
306 AsmLoadAccessRightsByte ENDP
307 
308 ; void __stdcall AsmInvalidateInternalCaches();
309 AsmInvalidateInternalCaches PROC
310  invd
311  ret
312 AsmInvalidateInternalCaches ENDP
313 
314 ; void __stdcall AsmWriteCR2(_In_ ULONG_PTR cr2_value);
315 AsmWriteCR2 PROC cr2_value
316  mov ecx, cr2_value
317  mov cr2, ecx
318  ret
319 AsmWriteCR2 ENDP
320 
321 ; unsigned char __stdcall AsmInvept(
322 ; _In_ InvEptType invept_type,
323 ; _In_ const InvEptDescriptor *invept_descriptor);
324 AsmInvept PROC invept_type, invept_descriptor
325  mov ecx, invept_type
326  mov edx, invept_descriptor
327  ; invept ecx, oword ptr [edx]
328  db 66h, 0fh, 38h, 80h, 0ah
329  jz errorWithCode ; if (ZF) jmp
330  jc errorWithoutCode ; if (CF) jmp
331  xor eax, eax ; return VMX_OK
332  ret
333 
334 errorWithoutCode:
335  mov eax, VMX_ERROR_WITHOUT_STATUS
336  ret
337 
338 errorWithCode:
339  mov eax, VMX_ERROR_WITH_STATUS
340  ret
341 AsmInvept ENDP
342 
343 ; unsigned char __stdcall AsmInvvpid(
344 ; _In_ InvVpidType invvpid_type,
345 ; _In_ const InvVpidDescriptor *invvpid_descriptor);
346 AsmInvvpid PROC invvpid_type, invvpid_descriptor
347  mov ecx, invvpid_type
348  mov edx, invvpid_descriptor
349  ; invvpid ecx, oword ptr [rdx]
350  db 66h, 0fh, 38h, 81h, 0ah
351  jz errorWithCode ; if (ZF) jmp
352  jc errorWithoutCode ; if (CF) jmp
353  xor eax, eax ; return VMX_OK
354  ret
355 
356 errorWithoutCode:
357  mov eax, VMX_ERROR_WITHOUT_STATUS
358  ret
359 
360 errorWithCode:
361  mov eax, VMX_ERROR_WITH_STATUS
362  ret
363 AsmInvvpid ENDP
364 
365 
366 PURGE ASM_DUMP_REGISTERS
367 END