VirtualBox

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

Last change on this file since 36822 was 35333, checked in by vboxsync, 14 years ago

VMM source reorg.

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