VirtualBox

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

Last change on this file since 20374 was 19575, checked in by vboxsync, 16 years ago

Updates for ring 0 call stack dumping. (not enabled nor tested)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 15.2 KB
Line 
1; $Id: VMMR0A.asm 19575 2009-05-11 12:42:46Z 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 ; Save ESP & EBP to enable stack dumps
411 mov ecx, ebp
412 mov [edx + VMMR0JMPBUF.SavedEbp], ecx
413 sub ecx, 4
414 mov [edx + VMMR0JMPBUF.SavedEsp], ecx
415
416 ; store the last pieces of info.
417 mov ecx, [edx + VMMR0JMPBUF.esp]
418 mov [edx + VMMR0JMPBUF.SpCheck], ecx
419 mov byte [edx + VMMR0JMPBUF.fInRing3Call], 1
420
421 ;
422 ; Do the long jump.
423 ;
424 mov ebx, [edx + VMMR0JMPBUF.ebx]
425 mov esi, [edx + VMMR0JMPBUF.esi]
426 mov edi, [edx + VMMR0JMPBUF.edi]
427 mov ebp, [edx + VMMR0JMPBUF.ebp]
428 mov ecx, [edx + VMMR0JMPBUF.eip]
429 mov esp, [edx + VMMR0JMPBUF.esp]
430 jmp ecx
431
432 ;
433 ; Failure
434 ;
435.nok:
436%ifdef VBOX_STRICT
437 pop eax ; magic
438 cmp eax, 0f00dbed0h
439 je .magic_ok
440 mov ecx, 0123h
441 mov [ecx], edx
442.magic_ok:
443%endif
444 popf
445 pop ebx
446 pop esi
447 pop edi
448 mov eax, VERR_INTERNAL_ERROR_4
449 leave
450 ret
451%endif ; RT_ARCH_X86
452
453%ifdef RT_ARCH_AMD64
454 ;
455 ; Save the registers on the stack.
456 ;
457 push rbp
458 mov rbp, rsp
459 push r15
460 push r14
461 push r13
462 push r12
463 %ifdef ASM_CALL64_MSC
464 push rdi
465 push rsi
466 %endif
467 push rbx
468 pushf
469
470 ;
471 ; Normalize the parameters.
472 ;
473 %ifdef ASM_CALL64_MSC
474 mov eax, edx ; rc
475 mov rdx, rcx ; pJmpBuf
476 %else
477 mov rdx, rdi ; pJmpBuf
478 mov eax, esi ; rc
479 %endif
480
481 ;
482 ; Is the jump buffer armed?
483 ;
484 cmp qword [rdx + VMMR0JMPBUF.rip], byte 0
485 je .nok
486
487 ;
488 ; Sanity checks.
489 ;
490 mov rdi, [rdx + VMMR0JMPBUF.pvSavedStack]
491 test rdi, rdi ; darwin may set this to 0.
492 jz .nok
493 mov [rdx + VMMR0JMPBUF.SpResume], rsp
494 %ifndef VMM_R0_SWITCH_STACK
495 mov rsi, rsp
496 mov rcx, [rdx + VMMR0JMPBUF.rsp]
497 sub rcx, rsi
498
499 ; two sanity checks on the size.
500 cmp rcx, 8192 ; check max size.
501 jnbe .nok
502
503 ;
504 ; Copy the stack
505 ;
506 test ecx, 7 ; check alignment
507 jnz .nok
508 mov [rdx + VMMR0JMPBUF.cbSavedStack], ecx
509 shr ecx, 3
510 rep movsq
511
512 %endif ; !VMM_R0_SWITCH_STACK
513
514 ; Save RSP & RBP to enable stack dumps
515 mov rcx, rbp
516 mov [rdx + VMMR0JMPBUF.SavedEbp], rcx
517 sub rcx, 8
518 mov [rdx + VMMR0JMPBUF.SavedEsp], rcx
519
520 ; store the last pieces of info.
521 mov rcx, [rdx + VMMR0JMPBUF.rsp]
522 mov [rdx + VMMR0JMPBUF.SpCheck], rcx
523 mov byte [rdx + VMMR0JMPBUF.fInRing3Call], 1
524
525 ;
526 ; Do the long jump.
527 ;
528 mov rbx, [rdx + VMMR0JMPBUF.rbx]
529 %ifdef ASM_CALL64_MSC
530 mov rsi, [rdx + VMMR0JMPBUF.rsi]
531 mov rdi, [rdx + VMMR0JMPBUF.rdi]
532 %endif
533 mov r12, [rdx + VMMR0JMPBUF.r12]
534 mov r13, [rdx + VMMR0JMPBUF.r13]
535 mov r14, [rdx + VMMR0JMPBUF.r14]
536 mov r15, [rdx + VMMR0JMPBUF.r15]
537 mov rbp, [rdx + VMMR0JMPBUF.rbp]
538 mov rcx, [rdx + VMMR0JMPBUF.rip]
539 mov rsp, [rdx + VMMR0JMPBUF.rsp]
540 jmp rcx
541
542 ;
543 ; Failure
544 ;
545.nok:
546 mov eax, VERR_INTERNAL_ERROR_4
547 popf
548 pop rbx
549 %ifdef ASM_CALL64_MSC
550 pop rsi
551 pop rdi
552 %endif
553 pop r12
554 pop r13
555 pop r14
556 pop r15
557 leave
558 ret
559
560%endif
561ENDPROC vmmR0CallHostLongJmp
562
563
564;;
565; Internal R0 logger worker: Logger wrapper.
566;
567; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
568;
569EXPORTEDNAME vmmR0LoggerWrapper
570%ifdef RT_ARCH_X86 ; The other architecture(s) use(s) C99 variadict macros.
571 push 0 ; assumes we're the wrapper for a default instance.
572 call NAME(RTLogLogger)
573 add esp, byte 4
574 ret
575%else
576 int3
577 int3
578 int3
579 ret
580%endif
581ENDPROC vmmR0LoggerWrapper
582
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