VirtualBox

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

Last change on this file since 22898 was 20992, checked in by vboxsync, 15 years ago

VMMR0JmpA-amd64.asm: Save non-volatile XMM registers on Windows/AMD64.

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