VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm@ 78338

Last change on this file since 78338 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.9 KB
Line 
1; $Id: VMMR0JmpA-amd64.asm 76553 2019-01-01 01:45:53Z vboxsync $
2;; @file
3; VMM - R0 SetJmp / LongJmp routines for AMD64.
4;
5
6;
7; Copyright (C) 2006-2019 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17
18;*******************************************************************************
19;* Header Files *
20;*******************************************************************************
21%define RT_ASM_WITH_SEH64
22%include "VBox/asmdefs.mac"
23%include "VMMInternal.mac"
24%include "VBox/err.mac"
25%include "VBox/param.mac"
26
27
28;*******************************************************************************
29;* Defined Constants And Macros *
30;*******************************************************************************
31%define RESUME_MAGIC 07eadf00dh
32%define STACK_PADDING 0eeeeeeeeeeeeeeeeh
33
34;; Workaround for linux 4.6 fast/slow syscall stack depth difference.
35%ifdef VMM_R0_SWITCH_STACK
36 %define STACK_FUZZ_SIZE 0
37%else
38 %define STACK_FUZZ_SIZE 128
39%endif
40
41
42BEGINCODE
43
44
45;;
46; The setjmp variant used for calling Ring-3.
47;
48; This differs from the normal setjmp in that it will resume VMMRZCallRing3 if we're
49; in the middle of a ring-3 call. Another differences is the function pointer and
50; argument. This has to do with resuming code and the stack frame of the caller.
51;
52; @returns VINF_SUCCESS on success or whatever is passed to vmmR0CallRing3LongJmp.
53; @param pJmpBuf msc:rcx gcc:rdi x86:[esp+0x04] Our jmp_buf.
54; @param pfn msc:rdx gcc:rsi x86:[esp+0x08] The function to be called when not resuming.
55; @param pvUser1 msc:r8 gcc:rdx x86:[esp+0x0c] The argument of that function.
56; @param pvUser2 msc:r9 gcc:rcx x86:[esp+0x10] The argument of that function.
57;
58BEGINPROC vmmR0CallRing3SetJmp
59GLOBALNAME vmmR0CallRing3SetJmp2
60GLOBALNAME vmmR0CallRing3SetJmpEx
61 ;
62 ; Save the registers.
63 ;
64 push rbp
65 SEH64_PUSH_xBP
66 mov rbp, rsp
67 SEH64_SET_FRAME_xBP 0
68 %ifdef ASM_CALL64_MSC
69 sub rsp, 30h + STACK_FUZZ_SIZE ; (10h is used by resume (??), 20h for callee spill area)
70 SEH64_ALLOCATE_STACK 30h + STACK_FUZZ_SIZE
71SEH64_END_PROLOGUE
72 mov r11, rdx ; pfn
73 mov rdx, rcx ; pJmpBuf;
74 %else
75 sub rsp, 10h + STACK_FUZZ_SIZE ; (10h is used by resume (??))
76 SEH64_ALLOCATE_STACK 10h + STACK_FUZZ_SIZE
77SEH64_END_PROLOGUE
78 mov r8, rdx ; pvUser1 (save it like MSC)
79 mov r9, rcx ; pvUser2 (save it like MSC)
80 mov r11, rsi ; pfn
81 mov rdx, rdi ; pJmpBuf
82 %endif
83 mov [xDX + VMMR0JMPBUF.rbx], rbx
84 %ifdef ASM_CALL64_MSC
85 mov [xDX + VMMR0JMPBUF.rsi], rsi
86 mov [xDX + VMMR0JMPBUF.rdi], rdi
87 %endif
88 mov [xDX + VMMR0JMPBUF.rbp], rbp
89 mov [xDX + VMMR0JMPBUF.r12], r12
90 mov [xDX + VMMR0JMPBUF.r13], r13
91 mov [xDX + VMMR0JMPBUF.r14], r14
92 mov [xDX + VMMR0JMPBUF.r15], r15
93 mov xAX, [rbp + 8] ; (not really necessary, except for validity check)
94 mov [xDX + VMMR0JMPBUF.rip], xAX
95 %ifdef ASM_CALL64_MSC
96 lea r10, [rsp + 20h] ; must save the spill area
97 %else
98 lea r10, [rsp]
99 %endif
100 mov [xDX + VMMR0JMPBUF.rsp], r10
101 %ifdef RT_OS_WINDOWS
102 movdqa [xDX + VMMR0JMPBUF.xmm6], xmm6
103 movdqa [xDX + VMMR0JMPBUF.xmm7], xmm7
104 movdqa [xDX + VMMR0JMPBUF.xmm8], xmm8
105 movdqa [xDX + VMMR0JMPBUF.xmm9], xmm9
106 movdqa [xDX + VMMR0JMPBUF.xmm10], xmm10
107 movdqa [xDX + VMMR0JMPBUF.xmm11], xmm11
108 movdqa [xDX + VMMR0JMPBUF.xmm12], xmm12
109 movdqa [xDX + VMMR0JMPBUF.xmm13], xmm13
110 movdqa [xDX + VMMR0JMPBUF.xmm14], xmm14
111 movdqa [xDX + VMMR0JMPBUF.xmm15], xmm15
112 %endif
113 pushf
114 pop xAX
115 mov [xDX + VMMR0JMPBUF.rflags], xAX
116
117 ;
118 ; If we're not in a ring-3 call, call pfn and return.
119 ;
120 test byte [xDX + VMMR0JMPBUF.fInRing3Call], 1
121 jnz .resume
122
123 %ifdef VMM_R0_SWITCH_STACK
124 mov r15, [xDX + VMMR0JMPBUF.pvSavedStack]
125 test r15, r15
126 jz .entry_error
127 %ifdef VBOX_STRICT
128 cmp dword [r15], 0h
129 jne .entry_error
130 mov rdi, r15
131 mov rcx, VMM_STACK_SIZE / 8
132 mov rax, qword 0eeeeeeeffeeeeeeeh
133 repne stosq
134 mov [rdi - 10h], rbx
135 %endif
136 lea r15, [r15 + VMM_STACK_SIZE - 40h]
137 mov rsp, r15 ; Switch stack!
138 %endif ; VMM_R0_SWITCH_STACK
139
140 mov r12, rdx ; Save pJmpBuf.
141 %ifdef ASM_CALL64_MSC
142 mov rcx, r8 ; pvUser -> arg0
143 mov rdx, r9
144 %else
145 mov rdi, r8 ; pvUser -> arg0
146 mov rsi, r9
147 %endif
148 call r11
149 mov rdx, r12 ; Restore pJmpBuf
150
151 %ifdef VMM_R0_SWITCH_STACK
152 %ifdef VBOX_STRICT
153 mov r15, [xDX + VMMR0JMPBUF.pvSavedStack]
154 mov dword [r15], 0h ; Reset the marker
155 %endif
156 %endif
157
158 ;
159 ; Return like in the long jump but clear eip, no shortcuts here.
160 ;
161.proper_return:
162%ifdef RT_OS_WINDOWS
163 movdqa xmm6, [xDX + VMMR0JMPBUF.xmm6 ]
164 movdqa xmm7, [xDX + VMMR0JMPBUF.xmm7 ]
165 movdqa xmm8, [xDX + VMMR0JMPBUF.xmm8 ]
166 movdqa xmm9, [xDX + VMMR0JMPBUF.xmm9 ]
167 movdqa xmm10, [xDX + VMMR0JMPBUF.xmm10]
168 movdqa xmm11, [xDX + VMMR0JMPBUF.xmm11]
169 movdqa xmm12, [xDX + VMMR0JMPBUF.xmm12]
170 movdqa xmm13, [xDX + VMMR0JMPBUF.xmm13]
171 movdqa xmm14, [xDX + VMMR0JMPBUF.xmm14]
172 movdqa xmm15, [xDX + VMMR0JMPBUF.xmm15]
173%endif
174 mov rbx, [xDX + VMMR0JMPBUF.rbx]
175%ifdef ASM_CALL64_MSC
176 mov rsi, [xDX + VMMR0JMPBUF.rsi]
177 mov rdi, [xDX + VMMR0JMPBUF.rdi]
178%endif
179 mov r12, [xDX + VMMR0JMPBUF.r12]
180 mov r13, [xDX + VMMR0JMPBUF.r13]
181 mov r14, [xDX + VMMR0JMPBUF.r14]
182 mov r15, [xDX + VMMR0JMPBUF.r15]
183 mov rbp, [xDX + VMMR0JMPBUF.rbp]
184 and qword [xDX + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
185 mov rsp, [xDX + VMMR0JMPBUF.rsp]
186 push qword [xDX + VMMR0JMPBUF.rflags]
187 popf
188 leave
189 ret
190
191.entry_error:
192 mov eax, VERR_VMM_SET_JMP_ERROR
193 jmp .proper_return
194
195.stack_overflow:
196 mov eax, VERR_VMM_SET_JMP_STACK_OVERFLOW
197 jmp .proper_return
198
199 ;
200 ; Aborting resume.
201 ; Note! No need to restore XMM registers here since we haven't touched them yet.
202 ;
203.bad:
204 and qword [xDX + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
205 mov rbx, [xDX + VMMR0JMPBUF.rbx]
206 %ifdef ASM_CALL64_MSC
207 mov rsi, [xDX + VMMR0JMPBUF.rsi]
208 mov rdi, [xDX + VMMR0JMPBUF.rdi]
209 %endif
210 mov r12, [xDX + VMMR0JMPBUF.r12]
211 mov r13, [xDX + VMMR0JMPBUF.r13]
212 mov r14, [xDX + VMMR0JMPBUF.r14]
213 mov r15, [xDX + VMMR0JMPBUF.r15]
214 mov eax, VERR_VMM_SET_JMP_ABORTED_RESUME
215 leave
216 ret
217
218 ;
219 ; Resume VMMRZCallRing3 the call.
220 ;
221.resume:
222 %ifndef VMM_R0_SWITCH_STACK
223 ; Sanity checks incoming stack, applying fuzz if needed.
224 sub r10, [xDX + VMMR0JMPBUF.SpCheck]
225 jz .resume_stack_checked_out
226 add r10, STACK_FUZZ_SIZE ; plus/minus STACK_FUZZ_SIZE is fine.
227 cmp r10, STACK_FUZZ_SIZE * 2
228 ja .bad
229
230 mov r10, [xDX + VMMR0JMPBUF.SpCheck]
231 mov [xDX + VMMR0JMPBUF.rsp], r10 ; Must be update in case of another long jump (used for save calc).
232
233.resume_stack_checked_out:
234 mov ecx, [xDX + VMMR0JMPBUF.cbSavedStack]
235 cmp rcx, VMM_STACK_SIZE
236 ja .bad
237 test rcx, 7
238 jnz .bad
239 mov rdi, [xDX + VMMR0JMPBUF.SpCheck]
240 sub rdi, [xDX + VMMR0JMPBUF.SpResume]
241 cmp rcx, rdi
242 jne .bad
243 %endif
244
245%ifdef VMM_R0_SWITCH_STACK
246 ; Switch stack.
247 mov rsp, [xDX + VMMR0JMPBUF.SpResume]
248%else
249 ; Restore the stack.
250 mov ecx, [xDX + VMMR0JMPBUF.cbSavedStack]
251 shr ecx, 3
252 mov rsi, [xDX + VMMR0JMPBUF.pvSavedStack]
253 mov rdi, [xDX + VMMR0JMPBUF.SpResume]
254 mov rsp, rdi
255 rep movsq
256%endif ; !VMM_R0_SWITCH_STACK
257 mov byte [xDX + VMMR0JMPBUF.fInRing3Call], 0
258
259 ;
260 ; Continue where we left off.
261 ;
262%ifdef VBOX_STRICT
263 pop rax ; magic
264 cmp rax, RESUME_MAGIC
265 je .magic_ok
266 mov ecx, 0123h
267 mov [ecx], edx
268.magic_ok:
269%endif
270%ifdef RT_OS_WINDOWS
271 movdqa xmm6, [rsp + 000h]
272 movdqa xmm7, [rsp + 010h]
273 movdqa xmm8, [rsp + 020h]
274 movdqa xmm9, [rsp + 030h]
275 movdqa xmm10, [rsp + 040h]
276 movdqa xmm11, [rsp + 050h]
277 movdqa xmm12, [rsp + 060h]
278 movdqa xmm13, [rsp + 070h]
279 movdqa xmm14, [rsp + 080h]
280 movdqa xmm15, [rsp + 090h]
281 add rsp, 0a0h
282%endif
283 popf
284 pop rbx
285%ifdef ASM_CALL64_MSC
286 pop rsi
287 pop rdi
288%endif
289 pop r12
290 pop r13
291 pop r14
292 pop r15
293 pop rbp
294 xor eax, eax ; VINF_SUCCESS
295 ret
296ENDPROC vmmR0CallRing3SetJmp
297
298
299;;
300; Worker for VMMRZCallRing3.
301; This will save the stack and registers.
302;
303; @param pJmpBuf msc:rcx gcc:rdi x86:[ebp+8] Pointer to the jump buffer.
304; @param rc msc:rdx gcc:rsi x86:[ebp+c] The return code.
305;
306BEGINPROC vmmR0CallRing3LongJmp
307 ;
308 ; Save the registers on the stack.
309 ;
310 push rbp
311 SEH64_PUSH_xBP
312 mov rbp, rsp
313 SEH64_SET_FRAME_xBP 0
314 push r15
315 SEH64_PUSH_GREG r15
316 push r14
317 SEH64_PUSH_GREG r14
318 push r13
319 SEH64_PUSH_GREG r13
320 push r12
321 SEH64_PUSH_GREG r12
322%ifdef ASM_CALL64_MSC
323 push rdi
324 SEH64_PUSH_GREG rdi
325 push rsi
326 SEH64_PUSH_GREG rsi
327%endif
328 push rbx
329 SEH64_PUSH_GREG rbx
330 pushf
331 SEH64_ALLOCATE_STACK 8
332%ifdef RT_OS_WINDOWS
333 sub rsp, 0a0h
334 SEH64_ALLOCATE_STACK 0a0h
335 movdqa [rsp + 000h], xmm6
336 movdqa [rsp + 010h], xmm7
337 movdqa [rsp + 020h], xmm8
338 movdqa [rsp + 030h], xmm9
339 movdqa [rsp + 040h], xmm10
340 movdqa [rsp + 050h], xmm11
341 movdqa [rsp + 060h], xmm12
342 movdqa [rsp + 070h], xmm13
343 movdqa [rsp + 080h], xmm14
344 movdqa [rsp + 090h], xmm15
345%endif
346%ifdef VBOX_STRICT
347 push RESUME_MAGIC
348 SEH64_ALLOCATE_STACK 8
349%endif
350SEH64_END_PROLOGUE
351
352 ;
353 ; Normalize the parameters.
354 ;
355%ifdef ASM_CALL64_MSC
356 mov eax, edx ; rc
357 mov rdx, rcx ; pJmpBuf
358%else
359 mov rdx, rdi ; pJmpBuf
360 mov eax, esi ; rc
361%endif
362
363 ;
364 ; Is the jump buffer armed?
365 ;
366 cmp qword [xDX + VMMR0JMPBUF.rip], byte 0
367 je .nok
368
369 ;
370 ; Sanity checks.
371 ;
372 mov rdi, [xDX + VMMR0JMPBUF.pvSavedStack]
373 test rdi, rdi ; darwin may set this to 0.
374 jz .nok
375 mov [xDX + VMMR0JMPBUF.SpResume], rsp
376 %ifndef VMM_R0_SWITCH_STACK
377 mov rsi, rsp
378 mov rcx, [xDX + VMMR0JMPBUF.rsp]
379 sub rcx, rsi
380
381 ; two sanity checks on the size.
382 cmp rcx, VMM_STACK_SIZE ; check max size.
383 jnbe .nok
384
385 ;
386 ; Copy the stack
387 ;
388 test ecx, 7 ; check alignment
389 jnz .nok
390 mov [xDX + VMMR0JMPBUF.cbSavedStack], ecx
391 shr ecx, 3
392 rep movsq
393
394 %endif ; !VMM_R0_SWITCH_STACK
395
396 ; Save a PC and return PC here to assist unwinding.
397.unwind_point:
398 lea rcx, [.unwind_point wrt RIP]
399 mov [xDX + VMMR0JMPBUF.SavedEipForUnwind], rcx
400 mov rcx, [xDX + VMMR0JMPBUF.rbp]
401 lea rcx, [rcx + 8]
402 mov [xDX + VMMR0JMPBUF.UnwindRetPcLocation], rcx
403 mov rcx, [rcx]
404 mov [xDX + VMMR0JMPBUF.UnwindRetPcValue], rcx
405
406 ; Save RSP & RBP to enable stack dumps
407 mov rcx, rbp
408 mov [xDX + VMMR0JMPBUF.SavedEbp], rcx
409 sub rcx, 8
410 mov [xDX + VMMR0JMPBUF.SavedEsp], rcx
411
412 ; store the last pieces of info.
413 mov rcx, [xDX + VMMR0JMPBUF.rsp]
414 mov [xDX + VMMR0JMPBUF.SpCheck], rcx
415 mov byte [xDX + VMMR0JMPBUF.fInRing3Call], 1
416
417 ;
418 ; Do the long jump.
419 ;
420%ifdef RT_OS_WINDOWS
421 movdqa xmm6, [xDX + VMMR0JMPBUF.xmm6 ]
422 movdqa xmm7, [xDX + VMMR0JMPBUF.xmm7 ]
423 movdqa xmm8, [xDX + VMMR0JMPBUF.xmm8 ]
424 movdqa xmm9, [xDX + VMMR0JMPBUF.xmm9 ]
425 movdqa xmm10, [xDX + VMMR0JMPBUF.xmm10]
426 movdqa xmm11, [xDX + VMMR0JMPBUF.xmm11]
427 movdqa xmm12, [xDX + VMMR0JMPBUF.xmm12]
428 movdqa xmm13, [xDX + VMMR0JMPBUF.xmm13]
429 movdqa xmm14, [xDX + VMMR0JMPBUF.xmm14]
430 movdqa xmm15, [xDX + VMMR0JMPBUF.xmm15]
431%endif
432 mov rbx, [xDX + VMMR0JMPBUF.rbx]
433%ifdef ASM_CALL64_MSC
434 mov rsi, [xDX + VMMR0JMPBUF.rsi]
435 mov rdi, [xDX + VMMR0JMPBUF.rdi]
436%endif
437 mov r12, [xDX + VMMR0JMPBUF.r12]
438 mov r13, [xDX + VMMR0JMPBUF.r13]
439 mov r14, [xDX + VMMR0JMPBUF.r14]
440 mov r15, [xDX + VMMR0JMPBUF.r15]
441 mov rbp, [xDX + VMMR0JMPBUF.rbp]
442 mov rsp, [xDX + VMMR0JMPBUF.rsp]
443 push qword [xDX + VMMR0JMPBUF.rflags]
444 popf
445 leave
446 ret
447
448 ;
449 ; Failure
450 ;
451.nok:
452%ifdef VBOX_STRICT
453 pop rax ; magic
454 cmp rax, RESUME_MAGIC
455 je .magic_ok
456 mov ecx, 0123h
457 mov [rcx], edx
458.magic_ok:
459%endif
460 mov eax, VERR_VMM_LONG_JMP_ERROR
461%ifdef RT_OS_WINDOWS
462 add rsp, 0a0h ; skip XMM registers since they are unmodified.
463%endif
464 popf
465 pop rbx
466%ifdef ASM_CALL64_MSC
467 pop rsi
468 pop rdi
469%endif
470 pop r12
471 pop r13
472 pop r14
473 pop r15
474 leave
475 ret
476ENDPROC vmmR0CallRing3LongJmp
477
478
479;;
480; Internal R0 logger worker: Logger wrapper.
481;
482; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
483;
484BEGINPROC_EXPORTED vmmR0LoggerWrapper
485SEH64_END_PROLOGUE
486 int3
487 int3
488 int3
489 ret
490ENDPROC vmmR0LoggerWrapper
491
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette