VirtualBox

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

Last change on this file since 5474 was 4979, checked in by vboxsync, 17 years ago

New ring-0 assertion avoidance, now for all platforms.

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