VirtualBox

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

Last change on this file since 7476 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.9 KB
Line 
1; $Id: VMMR0A.asm 5999 2007-12-07 15:05:06Z vboxsync $
2;; @file
3; VMM - R0 assembly routines.
4;
5
6;
7; Copyright (C) 2006-2007 innotek GmbH
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
25
26%ifdef RT_ARCH_X86 ; The other architecture(s) use(s) C99 variadict macros.
27extern IMPNAME(RTLogLogger)
28%endif
29
30
31BEGINCODE
32
33
34;;
35; The setjmp variant used for calling Ring-3.
36;
37; This differs from the normal setjmp in that it will resume VMMR0CallHost if we're
38; in the middle of a ring-3 call. Another differences is the function pointer and
39; argument. This has to do with resuming code and the stack frame of the caller.
40;
41; @returns VINF_SUCCESS on success or whatever is passed to vmmR0CallHostLongJmp.
42; @param pJmpBuf msc:rcx gcc:rdi x86:[esp+4] Our jmp_buf.
43; @param pfn msc:rdx gcc:rsi x86:[esp+8] The function to be called when not resuming.
44; @param pvUser msc:r8 gcc:rdx x86:[esp+c] The argument of that function.
45;
46BEGINPROC vmmR0CallHostSetJmp
47GLOBALNAME vmmR0CallHostSetJmpEx
48%ifdef RT_ARCH_X86
49 ;
50 ; Save the registers.
51 ;
52 mov edx, [esp + 4h] ; pJmpBuf
53 mov [edx + VMMR0JMPBUF.ebx], ebx
54 mov [edx + VMMR0JMPBUF.esi], esi
55 mov [edx + VMMR0JMPBUF.edi], edi
56 mov [edx + VMMR0JMPBUF.ebp], ebp
57 mov eax, [esp]
58 mov [edx + VMMR0JMPBUF.eip], eax
59 lea ecx, [esp + 4] ; (used in resume)
60 mov [edx + VMMR0JMPBUF.esp], ecx
61
62 ;
63 ; If we're not in a ring-3 call, call pfn and return.
64 ;
65 test byte [edx + VMMR0JMPBUF.fInRing3Call], 1
66 jnz .resume
67
68 mov ecx, [esp + 0ch] ; pvArg
69 mov eax, [esp + 08h] ; pfn
70 sub esp, 12 ; align the stack on a 16-byte boundrary.
71 mov [esp], ecx
72 call eax
73 add esp, 12
74 mov edx, [esp + 4h] ; pJmpBuf
75 and dword [edx + VMMR0JMPBUF.eip], byte 0 ; used for valid check.
76 ret
77
78 ;
79 ; Resume VMMR0CallHost the call.
80 ;
81.resume:
82 ; Sanity checks.
83 cmp ecx, [edx + VMMR0JMPBUF.SpCheck]
84 je .espCheck_ok
85.bad:
86 and dword [edx + VMMR0JMPBUF.eip], byte 0 ; used for valid check.
87 mov edi, [edx + VMMR0JMPBUF.edi]
88 mov esi, [edx + VMMR0JMPBUF.esi]
89 mov ebx, [edx + VMMR0JMPBUF.ebx]
90 mov eax, VERR_INTERNAL_ERROR ; todo better return code!
91 ret
92
93.espCheck_ok:
94 mov ecx, [edx + VMMR0JMPBUF.cbSavedStack]
95 cmp ecx, 8192
96 ja .bad
97 test ecx, 3
98 jnz .bad
99 mov edi, [edx + VMMR0JMPBUF.esp]
100 sub edi, [edx + VMMR0JMPBUF.SpResume]
101 cmp ecx, edi
102 jne .bad
103
104 ;
105 ; Restore the stack.
106 ;
107 mov byte [edx + VMMR0JMPBUF.fInRing3Call], 0
108 mov ecx, [edx + VMMR0JMPBUF.cbSavedStack]
109 shr ecx, 2
110 mov esi, [edx + VMMR0JMPBUF.pvSavedStack]
111 mov edi, [edx + VMMR0JMPBUF.SpResume]
112 mov esp, edi
113 rep movsd
114
115 ;
116 ; Continue where we left off.
117 ;
118 popf
119 pop ebx
120 pop esi
121 pop edi
122 pop ebp
123 xor eax, eax ; VINF_SUCCESS
124 ret
125%endif ; RT_ARCH_X86
126
127%ifdef RT_ARCH_AMD64
128 ;
129 ; Save the registers.
130 ;
131 push rbp
132 mov rbp, rsp
133 %ifdef ASM_CALL64_MSC
134 sub rsp, 30h
135 mov r11, rdx ; pfn
136 mov rdx, rcx ; pJmpBuf;
137 %else
138 sub rsp, 10h
139 mov r8, rdx ; pvUser (save it like MSC)
140 mov r11, rsi ; pfn
141 mov rdx, rdi ; pJmpBuf
142 %endif
143 mov [rdx + VMMR0JMPBUF.rbx], rbx
144 %ifdef ASM_CALL64_MSC
145 mov [rdx + VMMR0JMPBUF.rsi], rsi
146 mov [rdx + VMMR0JMPBUF.rdi], rdi
147 %endif
148 mov r10, [rbp]
149 mov [rdx + VMMR0JMPBUF.rbp], r10
150 mov [rdx + VMMR0JMPBUF.r12], r12
151 mov [rdx + VMMR0JMPBUF.r13], r13
152 mov [rdx + VMMR0JMPBUF.r14], r14
153 mov [rdx + VMMR0JMPBUF.r15], r15
154 mov rax, [rbp + 8]
155 mov [rdx + VMMR0JMPBUF.rip], rax
156 lea r10, [rbp + 10h] ; (used in resume)
157 mov [rdx + VMMR0JMPBUF.rsp], r10
158
159 ;
160 ; If we're not in a ring-3 call, call pfn and return.
161 ;
162 test byte [rdx + VMMR0JMPBUF.fInRing3Call], 1
163 jnz .resume
164
165 mov [rbp - 8], rdx ; Save it and fix stack alignment (16).
166 %ifdef ASM_CALL64_MSC
167 mov rcx, r8 ; pvUser -> arg0
168 %else
169 mov rdi, r8 ; pvUser -> arg0
170 %endif
171 call r11
172 mov rdx, [rbp - 8] ; pJmpBuf
173 and qword [rdx + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
174 leave
175 ret
176
177 ;
178 ; Resume VMMR0CallHost the call.
179 ;
180.resume:
181 ; Sanity checks.
182 cmp r10, [rdx + VMMR0JMPBUF.SpCheck]
183 je .rspCheck_ok
184.bad:
185 and qword [rdx + VMMR0JMPBUF.rip], byte 0 ; used for valid check.
186 mov rbx, [rdx + VMMR0JMPBUF.rbx]
187 %ifdef ASM_CALL64_MSC
188 mov rsi, [rdx + VMMR0JMPBUF.rsi]
189 mov rdi, [rdx + VMMR0JMPBUF.rdi]
190 %endif
191 mov r12, [rdx + VMMR0JMPBUF.r12]
192 mov r13, [rdx + VMMR0JMPBUF.r13]
193 mov r14, [rdx + VMMR0JMPBUF.r14]
194 mov r15, [rdx + VMMR0JMPBUF.r15]
195 mov eax, VERR_INTERNAL_ERROR ; todo better return code!
196 leave
197 ret
198
199.rspCheck_ok:
200 mov ecx, [rdx + VMMR0JMPBUF.cbSavedStack]
201 cmp rcx, 8192
202 ja .bad
203 test rcx, 3
204 jnz .bad
205 mov rdi, [rdx + VMMR0JMPBUF.rsp]
206 sub rdi, [rdx + VMMR0JMPBUF.SpResume]
207 cmp rcx, rdi
208 jne .bad
209
210 ;
211 ; Restore the stack.
212 ;
213 mov byte [rdx + VMMR0JMPBUF.fInRing3Call], 0
214 mov ecx, [rdx + VMMR0JMPBUF.cbSavedStack]
215 shr ecx, 3
216 mov rsi, [rdx + VMMR0JMPBUF.pvSavedStack]
217 mov rdi, [rdx + VMMR0JMPBUF.SpResume]
218 mov rsp, rdi
219 rep movsq
220
221 ;
222 ; Continue where we left off.
223 ;
224 popf
225 pop rbx
226 %ifdef ASM_CALL64_MSC
227 pop rsi
228 pop rdi
229 %endif
230 pop r12
231 pop r13
232 pop r14
233 pop r15
234 pop rbp
235 xor eax, eax ; VINF_SUCCESS
236 ret
237%endif
238ENDPROC vmmR0CallHostSetJmp
239
240
241;;
242; Worker for VMMR0CallHost.
243; This will save the stack and registers.
244;
245; @param pJmpBuf msc:rcx gcc:rdi x86:[ebp+8] Pointer to the jump buffer.
246; @param rc msc:rdx gcc:rsi x86:[ebp+c] The return code.
247;
248BEGINPROC vmmR0CallHostLongJmp
249%ifdef RT_ARCH_X86
250 ;
251 ; Save the registers on the stack.
252 ;
253 push ebp
254 mov ebp, esp
255 push edi
256 push esi
257 push ebx
258 pushf
259
260 ;
261 ; Load parameters.
262 ;
263 mov edx, [ebp + 08h] ; pJmpBuf
264 mov eax, [ebp + 0ch] ; rc
265
266 ;
267 ; Is the jump buffer armed?
268 ;
269 cmp dword [edx + VMMR0JMPBUF.eip], byte 0
270 je .nok
271
272 ;
273 ; Save the stack.
274 ;
275 mov edi, [edx + VMMR0JMPBUF.pvSavedStack]
276 mov [edx + VMMR0JMPBUF.SpResume], esp
277 mov esi, esp
278 mov ecx, [edx + VMMR0JMPBUF.esp]
279 sub ecx, esi
280
281 ; two sanity checks on the size.
282 cmp ecx, 8192 ; check max size.
283 jbe .ok
284.nok:
285 mov eax, VERR_INTERNAL_ERROR
286 popf
287 pop ebx
288 pop esi
289 pop edi
290 leave
291 ret
292.ok:
293 test ecx, 3 ; check alignment
294 jnz .nok
295 mov [edx + VMMR0JMPBUF.cbSavedStack], ecx
296 shr ecx, 2
297 rep movsd
298
299 ; store the last pieces of info.
300 mov ecx, [edx + VMMR0JMPBUF.esp]
301 mov [edx + VMMR0JMPBUF.SpCheck], ecx
302 mov byte [edx + VMMR0JMPBUF.fInRing3Call], 1
303
304 ;
305 ; Do the long jump.
306 ;
307 mov ebx, [edx + VMMR0JMPBUF.ebx]
308 mov esi, [edx + VMMR0JMPBUF.esi]
309 mov edi, [edx + VMMR0JMPBUF.edi]
310 mov ebp, [edx + VMMR0JMPBUF.ebp]
311 mov ecx, [edx + VMMR0JMPBUF.eip]
312 mov esp, [edx + VMMR0JMPBUF.esp]
313 jmp ecx
314%endif ; RT_ARCH_X86
315
316%ifdef RT_ARCH_AMD64
317 ;
318 ; Save the registers on the stack.
319 ;
320 push rbp
321 mov rbp, rsp
322 push r15
323 push r14
324 push r13
325 push r12
326 %ifdef ASM_CALL64_MSC
327 push rdi
328 push rsi
329 %endif
330 push rbx
331 pushf
332
333 ;
334 ; Normalize the parameters.
335 ;
336 %ifdef ASM_CALL64_MSC
337 mov eax, edx ; rc
338 mov rdx, rcx ; pJmpBuf
339 %else
340 mov rdx, rdi ; pJmpBuf
341 mov eax, esi ; rc
342 %endif
343
344 ;
345 ; Is the jump buffer armed?
346 ;
347 cmp qword [rdx + VMMR0JMPBUF.rip], byte 0
348 je .nok
349
350 ;
351 ; Save the stack.
352 ;
353 mov rdi, [rdx + VMMR0JMPBUF.pvSavedStack]
354 mov [rdx + VMMR0JMPBUF.SpResume], rsp
355 mov rsi, rsp
356 mov rcx, [rdx + VMMR0JMPBUF.rsp]
357 sub rcx, rsi
358
359 ; two sanity checks on the size.
360 cmp rcx, 8192 ; check max size.
361 jbe .ok
362.nok:
363 mov eax, VERR_INTERNAL_ERROR
364 popf
365 pop rbx
366 %ifdef ASM_CALL64_MSC
367 pop rsi
368 pop rdi
369 %endif
370 pop r12
371 pop r13
372 pop r14
373 pop r15
374 leave
375 ret
376
377.ok:
378 test ecx, 7 ; check alignment
379 jnz .nok
380 mov [rdx + VMMR0JMPBUF.cbSavedStack], ecx
381 shr ecx, 3
382 rep movsq
383
384 ; store the last pieces of info.
385 mov rcx, [rdx + VMMR0JMPBUF.rsp]
386 mov [rdx + VMMR0JMPBUF.SpCheck], rcx
387 mov byte [rdx + VMMR0JMPBUF.fInRing3Call], 1
388
389 ;
390 ; Do the long jump.
391 ;
392 mov rbx, [rdx + VMMR0JMPBUF.rbx]
393 %ifdef ASM_CALL64_MSC
394 mov rsi, [rdx + VMMR0JMPBUF.rsi]
395 mov rdi, [rdx + VMMR0JMPBUF.rdi]
396 %endif
397 mov r12, [rdx + VMMR0JMPBUF.r12]
398 mov r13, [rdx + VMMR0JMPBUF.r13]
399 mov r14, [rdx + VMMR0JMPBUF.r14]
400 mov r15, [rdx + VMMR0JMPBUF.r15]
401 mov rbp, [rdx + VMMR0JMPBUF.rbp]
402 mov rcx, [rdx + VMMR0JMPBUF.rip]
403 mov rsp, [rdx + VMMR0JMPBUF.rsp]
404 jmp rcx
405%endif
406ENDPROC vmmR0CallHostLongJmp
407
408
409;;
410; Internal R0 logger worker: Logger wrapper.
411;
412; @cproto VMMR0DECL(void) vmmR0LoggerWrapper(const char *pszFormat, ...)
413;
414EXPORTEDNAME vmmR0LoggerWrapper
415%ifdef RT_ARCH_X86 ; The other architecture(s) use(s) C99 variadict macros.
416 push 0 ; assumes we're the wrapper for a default instance.
417 call IMP(RTLogLogger)
418 add esp, byte 4
419 ret
420%else
421 int3
422 int3
423 int3
424 ret
425%endif
426ENDPROC vmmR0LoggerWrapper
427
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