VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/VMMR0A.asm@ 19420

Last change on this file since 19420 was 18849, checked in by vboxsync, 15 years ago

VMMR0A.asm: Implemented stack switching for 64-bit machines as well (i.e. snow leopard)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1; $Id: VMMR0A.asm 18849 2009-04-08 16:34:39Z vboxsync $
2;; @file
3; VMM - R0 assembly routines.
4;
5
6;
7; Copyright (C) 2006-2007 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
29
30%ifdef RT_ARCH_X86 ; The other architecture(s) use(s) C99 variadict macros.
31extern NAME(RTLogLogger)
32%endif
33
34%ifdef RT_OS_DARWIN
35 %define VMM_R0_SWITCH_STACK
36%endif
37
38
39BEGINCODE
40
41
42;;
43; The setjmp variant used for calling Ring-3.
44;
45; This differs from the normal setjmp in that it will resume VMMR0CallHost if we're
46; in the middle of a ring-3 call. Another differences is the function pointer and
47; argument. This has to do with resuming code and the stack frame of the caller.
48;
49; @returns VINF_SUCCESS on success or whatever is passed to vmmR0CallHostLongJmp.
50; @param pJmpBuf msc:rcx gcc:rdi x86:[esp+0x04] Our jmp_buf.
51; @param pfn msc:rdx gcc:rsi x86:[esp+0x08] The function to be called when not resuming.
52; @param pvUser1 msc:r8 gcc:rdx x86:[esp+0x0c] The argument of that function.
53; @param pvUser2 msc:r9 gcc:rcx x86:[esp+0x10] The argument of that function.
54;
55BEGINPROC vmmR0CallHostSetJmp
56GLOBALNAME vmmR0CallHostSetJmpEx
57%ifdef RT_ARCH_X86
58 ;
59 ; Save the registers.
60 ;
61 mov edx, [esp + 4h] ; pJmpBuf
62 mov [edx + VMMR0JMPBUF.ebx], ebx
63 mov [edx + VMMR0JMPBUF.esi], esi
64 mov [edx + VMMR0JMPBUF.edi], edi
65 mov [edx + VMMR0JMPBUF.ebp], ebp
66 mov eax, [esp]
67 mov [edx + VMMR0JMPBUF.eip], eax
68 lea ecx, [esp + 4] ; (used in resume)
69 mov [edx + VMMR0JMPBUF.esp], ecx
70
71 ;
72 ; If we're not in a ring-3 call, call pfn and return.
73 ;
74 test byte [edx + VMMR0JMPBUF.fInRing3Call], 1
75 jnz .resume
76
77 mov ebx, edx ; pJmpBuf -> ebx (persistent reg)
78%ifdef VMM_R0_SWITCH_STACK
79 mov esi, [ebx + VMMR0JMPBUF.pvSavedStack]
80 test esi, esi
81 jz .entry_error
82 %ifdef VBOX_STRICT
83 mov edx, esi
84 mov edi, esi
85 mov ecx, 2048
86 mov eax, 0eeeeeeeeh
87 repne stosd
88 %endif
89 lea esi, [esi + 8192 - 32]
90 mov [esi + 1ch], dword 0deadbeefh ; Marker 1.
91 mov [esi + 18h], ebx ; Save pJmpBuf pointer.
92 mov [esi + 14h], dword 00c00ffeeh ; Marker 2.
93 mov [esi + 10h], dword 0f00dbeefh ; Marker 3.
94 mov edx, [esp + 10h] ; pvArg2
95 mov [esi + 04h], edx
96 mov ecx, [esp + 0ch] ; pvArg1
97 mov [esi ], ecx
98 mov eax, [esp + 08h] ; pfn
99 mov esp, esi ; Switch stack!
100 call eax
101 and dword [esi + 1ch], byte 0 ; clear marker.
102
103%else ; !VMM_R0_SWITCH_STACK
104 mov ecx, [esp + 0ch] ; pvArg1
105 mov edx, [esp + 10h] ; pvArg2
106 mov eax, [esp + 08h] ; pfn
107 sub esp, 12 ; align the stack on a 16-byte boundrary.
108 mov [esp ], ecx
109 mov [esp + 04h], edx
110 call eax
111%endif ; !VMM_R0_SWITCH_STACK
112 mov edx, ebx ; pJmpBuf -> edx (volatile reg)
113
114 ;
115 ; Return like in the long jump but clear eip, no short cuts here.
116 ;
117.proper_return:
118 mov ebx, [edx + VMMR0JMPBUF.ebx]
119 mov esi, [edx + VMMR0JMPBUF.esi]
120 mov edi, [edx + VMMR0JMPBUF.edi]
121 mov ebp, [edx + VMMR0JMPBUF.ebp]
122 mov ecx, [edx + VMMR0JMPBUF.eip]
123 and dword [edx + VMMR0JMPBUF.eip], byte 0 ; used for valid check.
124 mov esp, [edx + VMMR0JMPBUF.esp]
125 jmp ecx
126
127.entry_error:
128 mov eax, VERR_INTERNAL_ERROR_2
129 jmp .proper_return
130
131 ;
132 ; Resume VMMR0CallHost the call.
133 ;
134.resume:
135%ifdef VMM_R0_SWITCH_STACK
136 ; Switch stack.
137 mov esp, [edx + VMMR0JMPBUF.SpResume]
138%else ; !VMM_R0_SWITCH_STACK
139 ; Sanity checks.
140 cmp ecx, [edx + VMMR0JMPBUF.SpCheck]
141 je .espCheck_ok
142.bad:
143 and dword [edx + VMMR0JMPBUF.eip], byte 0 ; used for valid check.
144 mov edi, [edx + VMMR0JMPBUF.edi]
145 mov esi, [edx + VMMR0JMPBUF.esi]
146 mov ebx, [edx + VMMR0JMPBUF.ebx]
147 mov eax, VERR_INTERNAL_ERROR_3 ; todo better return code!
148 ret
149
150.espCheck_ok:
151 mov ecx, [edx + VMMR0JMPBUF.cbSavedStack]
152 cmp ecx, 8192
153 ja .bad
154 test ecx, 3
155 jnz .bad
156 mov edi, [edx + VMMR0JMPBUF.esp]
157 sub edi, [edx + VMMR0JMPBUF.SpResume]
158 cmp ecx, edi
159 jne .bad
160
161 ;
162 ; Restore the stack.
163 ;
164 mov ecx, [edx + VMMR0JMPBUF.cbSavedStack]
165 shr ecx, 2
166 mov esi, [edx + VMMR0JMPBUF.pvSavedStack]
167 mov edi, [edx + VMMR0JMPBUF.SpResume]
168 mov esp, edi
169 rep movsd
170%endif ; !VMM_R0_SWITCH_STACK
171 mov byte [edx + VMMR0JMPBUF.fInRing3Call], 0
172
173 ;
174 ; Continue where we left off.
175 ;
176%ifdef VBOX_STRICT
177 pop eax ; magic
178 cmp eax, 0f00dbed0h
179 je .magic_ok
180 mov ecx, 0123h
181 mov [ecx], edx
182.magic_ok:
183%endif
184 popf
185 pop ebx
186 pop esi
187 pop edi
188 pop ebp
189 xor eax, eax ; VINF_SUCCESS
190 ret
191%endif ; RT_ARCH_X86
192
193%ifdef RT_ARCH_AMD64
194 ;
195 ; Save the registers.
196 ;
197 push rbp
198 mov rbp, rsp
199 %ifdef ASM_CALL64_MSC
200 sub rsp, 30h
201 mov r11, rdx ; pfn
202 mov rdx, rcx ; pJmpBuf;
203 %else
204 sub rsp, 10h
205 mov r8, rdx ; pvUser1 (save it like MSC)
206 mov r9, rcx ; pvUser2 (save it like MSC)
207 mov r11, rsi ; pfn
208 mov rdx, rdi ; pJmpBuf
209 %endif
210 mov [rdx + VMMR0JMPBUF.rbx], rbx
211 %ifdef ASM_CALL64_MSC
212 mov [rdx + VMMR0JMPBUF.rsi], rsi
213 mov [rdx + VMMR0JMPBUF.rdi], rdi
214 %endif
215 mov r10, [rbp]
216 mov [rdx + VMMR0JMPBUF.rbp], r10
217 mov [rdx + VMMR0JMPBUF.r12], r12
218 mov [rdx + VMMR0JMPBUF.r13], r13
219 mov [rdx + VMMR0JMPBUF.r14], r14
220 mov [rdx + VMMR0JMPBUF.r15], r15
221 mov rax, [rbp + 8]
222 mov [rdx + VMMR0JMPBUF.rip], rax
223 lea r10, [rbp + 10h] ; (used in resume)
224 mov [rdx + VMMR0JMPBUF.rsp], r10
225
226 ;
227 ; If we're not in a ring-3 call, call pfn and return.
228 ;
229 test byte [rdx + VMMR0JMPBUF.fInRing3Call], 1
230 jnz .resume
231
232 %ifdef VMM_R0_SWITCH_STACK
233 mov r15, [rdx + VMMR0JMPBUF.pvSavedStack]
234 test r15, r15
235 jz .entry_error
236 %ifdef VBOX_STRICT
237 mov rdi, r15
238 mov rcx, 1024
239 mov rax, 00eeeeeeeffeeeeeeeh
240 repne stosq
241 mov [rdi - 10h], rbx
242 %endif
243 lea r15, [r15 + 8192 - 40h]
244 mov rsp, r15 ; Switch stack!
245 %endif ; VMM_R0_SWITCH_STACK
246
247 mov r12, rdx ; Save pJmpBuf.
248 %ifdef ASM_CALL64_MSC
249 mov rcx, r8 ; pvUser -> arg0
250 mov rdx, r9
251 %else
252 mov rdi, r8 ; pvUser -> arg0
253 mov rsi, r9
254 %endif
255 call r11
256 mov rdx, r12 ; Restore pJmpBuf
257
258 ;
259 ; Return like in the long jump but clear eip, no short cuts here.
260 ;
261.proper_return:
262 mov rbx, [rdx + VMMR0JMPBUF.rbx]
263 %ifdef ASM_CALL64_MSC
264 mov rsi, [rdx + VMMR0JMPBUF.rsi]
265 mov rdi, [rdx + VMMR0JMPBUF.rdi]
266 %endif
267 mov r12, [rdx + VMMR0JMPBUF.r12]
268 mov r13, [rdx + VMMR0JMPBUF.r13]
269 mov r14, [rdx + VMMR0JMPBUF.r14]
270 mov r15, [rdx + VMMR0JMPBUF.r15]
271 mov rbp, [rdx + VMMR0JMPBUF.rbp]
272 mov rcx, [rdx + VMMR0JMPBUF.rip]
273 and qword [rdx + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
274 mov rsp, [rdx + VMMR0JMPBUF.rsp]
275 jmp rcx
276
277.entry_error:
278 mov eax, VERR_INTERNAL_ERROR_2
279 jmp .proper_return
280
281 ;
282 ; Resume VMMR0CallHost the call.
283 ;
284.resume:
285 %ifdef VMM_R0_SWITCH_STACK
286 ; Switch stack.
287 mov rsp, [rdx + VMMR0JMPBUF.SpResume]
288 %else ; !VMM_R0_SWITCH_STACK
289 ; Sanity checks.
290 cmp r10, [rdx + VMMR0JMPBUF.SpCheck]
291 je .rspCheck_ok
292.bad:
293 and qword [rdx + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
294 mov rbx, [rdx + VMMR0JMPBUF.rbx]
295 %ifdef ASM_CALL64_MSC
296 mov rsi, [rdx + VMMR0JMPBUF.rsi]
297 mov rdi, [rdx + VMMR0JMPBUF.rdi]
298 %endif
299 mov r12, [rdx + VMMR0JMPBUF.r12]
300 mov r13, [rdx + VMMR0JMPBUF.r13]
301 mov r14, [rdx + VMMR0JMPBUF.r14]
302 mov r15, [rdx + VMMR0JMPBUF.r15]
303 mov eax, VERR_INTERNAL_ERROR_2
304 leave
305 ret
306
307.rspCheck_ok:
308 mov ecx, [rdx + VMMR0JMPBUF.cbSavedStack]
309 cmp rcx, 8192
310 ja .bad
311 test rcx, 3
312 jnz .bad
313 mov rdi, [rdx + VMMR0JMPBUF.rsp]
314 sub rdi, [rdx + VMMR0JMPBUF.SpResume]
315 cmp rcx, rdi
316 jne .bad
317
318 ;
319 ; Restore the stack.
320 ;
321 mov ecx, [rdx + VMMR0JMPBUF.cbSavedStack]
322 shr ecx, 3
323 mov rsi, [rdx + VMMR0JMPBUF.pvSavedStack]
324 mov rdi, [rdx + VMMR0JMPBUF.SpResume]
325 mov rsp, rdi
326 rep movsq
327 %endif ; !VMM_R0_SWITCH_STACK
328 mov byte [rdx + VMMR0JMPBUF.fInRing3Call], 0
329
330 ;
331 ; Continue where we left off.
332 ;
333 popf
334 pop rbx
335 %ifdef ASM_CALL64_MSC
336 pop rsi
337 pop rdi
338 %endif
339 pop r12
340 pop r13
341 pop r14
342 pop r15
343 pop rbp
344 xor eax, eax ; VINF_SUCCESS
345 ret
346%endif
347ENDPROC vmmR0CallHostSetJmp
348
349
350;;
351; Worker for VMMR0CallHost.
352; This will save the stack and registers.
353;
354; @param pJmpBuf msc:rcx gcc:rdi x86:[ebp+8] Pointer to the jump buffer.
355; @param rc msc:rdx gcc:rsi x86:[ebp+c] The return code.
356;
357BEGINPROC vmmR0CallHostLongJmp
358%ifdef RT_ARCH_X86
359 ;
360 ; Save the registers on the stack.
361 ;
362 push ebp
363 mov ebp, esp
364 push edi
365 push esi
366 push ebx
367 pushf
368%ifdef VBOX_STRICT
369 push dword 0f00dbed0h
370%endif
371
372 ;
373 ; Load parameters.
374 ;
375 mov edx, [ebp + 08h] ; pJmpBuf
376 mov eax, [ebp + 0ch] ; rc
377
378 ;
379 ; Is the jump buffer armed?
380 ;
381 cmp dword [edx + VMMR0JMPBUF.eip], byte 0
382 je .nok
383
384 ;
385 ; Sanity checks.
386 ;
387 mov edi, [edx + VMMR0JMPBUF.pvSavedStack]
388 test edi, edi ; darwin may set this to 0.
389 jz .nok
390 mov [edx + VMMR0JMPBUF.SpResume], esp
391%ifndef VMM_R0_SWITCH_STACK
392 mov esi, esp
393 mov ecx, [edx + VMMR0JMPBUF.esp]
394 sub ecx, esi
395
396 ; two sanity checks on the size.
397 cmp ecx, 8192 ; check max size.
398 jnbe .nok
399
400 ;
401 ; Copy the stack.
402 ;
403 test ecx, 3 ; check alignment
404 jnz .nok
405 mov [edx + VMMR0JMPBUF.cbSavedStack], ecx
406 shr ecx, 2
407 rep movsd
408%endif ; !VMM_R0_SWITCH_STACK
409
410 ; store the last pieces of info.
411 mov ecx, [edx + VMMR0JMPBUF.esp]
412 mov [edx + VMMR0JMPBUF.SpCheck], ecx
413 mov byte [edx + VMMR0JMPBUF.fInRing3Call], 1
414
415 ;
416 ; Do the long jump.
417 ;
418 mov ebx, [edx + VMMR0JMPBUF.ebx]
419 mov esi, [edx + VMMR0JMPBUF.esi]
420 mov edi, [edx + VMMR0JMPBUF.edi]
421 mov ebp, [edx + VMMR0JMPBUF.ebp]
422 mov ecx, [edx + VMMR0JMPBUF.eip]
423 mov esp, [edx + VMMR0JMPBUF.esp]
424 jmp ecx
425
426 ;
427 ; Failure
428 ;
429.nok:
430%ifdef VBOX_STRICT
431 pop eax ; magic
432 cmp eax, 0f00dbed0h
433 je .magic_ok
434 mov ecx, 0123h
435 mov [ecx], edx
436.magic_ok:
437%endif
438 popf
439 pop ebx
440 pop esi
441 pop edi
442 mov eax, VERR_INTERNAL_ERROR_4
443 leave
444 ret
445%endif ; RT_ARCH_X86
446
447%ifdef RT_ARCH_AMD64
448 ;
449 ; Save the registers on the stack.
450 ;
451 push rbp
452 mov rbp, rsp
453 push r15
454 push r14
455 push r13
456 push r12
457 %ifdef ASM_CALL64_MSC
458 push rdi
459 push rsi
460 %endif
461 push rbx
462 pushf
463
464 ;
465 ; Normalize the parameters.
466 ;
467 %ifdef ASM_CALL64_MSC
468 mov eax, edx ; rc
469 mov rdx, rcx ; pJmpBuf
470 %else
471 mov rdx, rdi ; pJmpBuf
472 mov eax, esi ; rc
473 %endif
474
475 ;
476 ; Is the jump buffer armed?
477 ;
478 cmp qword [rdx + VMMR0JMPBUF.rip], byte 0
479 je .nok
480
481 ;
482 ; Sanity checks.
483 ;
484 mov rdi, [rdx + VMMR0JMPBUF.pvSavedStack]
485 test rdi, rdi ; darwin may set this to 0.
486 jz .nok
487 mov [rdx + VMMR0JMPBUF.SpResume], rsp
488 %ifndef VMM_R0_SWITCH_STACK
489 mov rsi, rsp
490 mov rcx, [rdx + VMMR0JMPBUF.rsp]
491 sub rcx, rsi
492
493 ; two sanity checks on the size.
494 cmp rcx, 8192 ; check max size.
495 jnbe .nok
496
497 ;
498 ; Copy the stack
499 ;
500 test ecx, 7 ; check alignment
501 jnz .nok
502 mov [rdx + VMMR0JMPBUF.cbSavedStack], ecx
503 shr ecx, 3
504 rep movsq
505
506 %endif ; !VMM_R0_SWITCH_STACK
507
508 ; store the last pieces of info.
509 mov rcx, [rdx + VMMR0JMPBUF.rsp]
510 mov [rdx + VMMR0JMPBUF.SpCheck], rcx
511 mov byte [rdx + VMMR0JMPBUF.fInRing3Call], 1
512
513 ;
514 ; Do the long jump.
515 ;
516 mov rbx, [rdx + VMMR0JMPBUF.rbx]
517 %ifdef ASM_CALL64_MSC
518 mov rsi, [rdx + VMMR0JMPBUF.rsi]
519 mov rdi, [rdx + VMMR0JMPBUF.rdi]
520 %endif
521 mov r12, [rdx + VMMR0JMPBUF.r12]
522 mov r13, [rdx + VMMR0JMPBUF.r13]
523 mov r14, [rdx + VMMR0JMPBUF.r14]
524 mov r15, [rdx + VMMR0JMPBUF.r15]
525 mov rbp, [rdx + VMMR0JMPBUF.rbp]
526 mov rcx, [rdx + VMMR0JMPBUF.rip]
527 mov rsp, [rdx + VMMR0JMPBUF.rsp]
528 jmp rcx
529
530 ;
531 ; Failure
532 ;
533.nok:
534 mov eax, VERR_INTERNAL_ERROR_4
535 popf
536 pop rbx
537 %ifdef ASM_CALL64_MSC
538 pop rsi
539 pop rdi
540 %endif
541 pop r12
542 pop r13
543 pop r14
544 pop r15
545 leave
546 ret
547
548%endif
549ENDPROC vmmR0CallHostLongJmp
550
551
552;;
553; Internal R0 logger worker: Logger wrapper.
554;
555; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
556;
557EXPORTEDNAME vmmR0LoggerWrapper
558%ifdef RT_ARCH_X86 ; The other architecture(s) use(s) C99 variadict macros.
559 push 0 ; assumes we're the wrapper for a default instance.
560 call NAME(RTLogLogger)
561 add esp, byte 4
562 ret
563%else
564 int3
565 int3
566 int3
567 ret
568%endif
569ENDPROC vmmR0LoggerWrapper
570
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