VirtualBox

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

Last change on this file since 39402 was 39402, checked in by vboxsync, 13 years ago

VMM: don't use generic IPE status codes, use specific ones. Part 1.

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