VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPLib.cpp@ 1045

Last change on this file since 1045 was 914, checked in by vboxsync, 18 years ago

PVMR0 changes for darwin.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.0 KB
Line 
1/** @file
2 *
3 * VBox host drivers - Ring-0 support drivers - Shared code:
4 * Support library that implements the basic lowlevel OS interfaces
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23/** @page pg_sup SUP - The Support Library
24 *
25 * The support library is responsible for providing facilities to load
26 * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
27 * code, and to pin down physical memory.
28 *
29 * The VMM Host Ring-0 code can be combined in the support driver if
30 * permitted by kernel module license policies. If it is not combined
31 * it will be externalized in a Win32 PE binary and will use the PDM
32 * PE loader to load it into memory.
33 *
34 * The Ring-0 calling is done thru a generic SUP interface which will
35 * tranfer an argument set and call a predefined entry point in the Host
36 * VMM Ring-0 code.
37 *
38 * See @ref grp_sup "SUP - Support APIs" for API details.
39 */
40
41
42/*******************************************************************************
43* Header Files *
44*******************************************************************************/
45#define LOG_GROUP LOG_GROUP_SUP
46#include <VBox/sup.h>
47#include <VBox/err.h>
48#include <VBox/param.h>
49#ifdef VBOX_WITHOUT_IDT_PATCHING
50# include <VBox/vmm.h>
51#endif
52#include <VBox/log.h>
53
54#include <iprt/assert.h>
55#include <iprt/alloc.h>
56#include <iprt/alloca.h>
57#include <iprt/ldr.h>
58#include <iprt/asm.h>
59#include <iprt/system.h>
60#include <iprt/thread.h>
61#include <iprt/process.h>
62#include <iprt/string.h>
63
64#include "SUPLibInternal.h"
65#include "SUPDRVIOC.h"
66
67#include <stdlib.h>
68
69
70
71/*******************************************************************************
72* Defined Constants And Macros *
73*******************************************************************************/
74/** R0 VMM module name. */
75#define VMMR0_NAME "VMMR0"
76
77
78/*******************************************************************************
79* Structures and Typedefs *
80*******************************************************************************/
81typedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
82typedef FNCALLVMMR0 *PFNCALLVMMR0;
83
84
85/*******************************************************************************
86* Global Variables *
87*******************************************************************************/
88/** Pointer to the Global Information Page.
89 *
90 * This pointer is valid as long as SUPLib has a open session. Anyone using
91 * the page must treat this pointer as higly volatile and not trust it beyond
92 * one transaction.
93 *
94 * @todo This will probably deserve it's own session or some other good solution...
95 */
96DECLEXPORT(PCSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
97/** Address of the ring-0 mapping of the GIP. */
98static PCSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0;
99/** The physical address of the GIP. */
100static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
101
102/** The negotiated cookie. */
103uint32_t g_u32Cookie = 0;
104/** The negotiated session cookie. */
105uint32_t g_u32SessionCookie;
106/** Session handle. */
107PSUPDRVSESSION g_pSession;
108/** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
109static PSUPQUERYFUNCS_OUT g_pFunctions;
110
111#ifndef VBOX_WITHOUT_IDT_PATCHING
112/** The negotiated interrupt number. */
113static uint8_t g_u8Interrupt = 3;
114/** Pointer to the generated code fore calling VMMR0. */
115static PFNCALLVMMR0 g_pfnCallVMMR0;
116#endif
117/** VMMR0 Load Address. */
118static void *g_pvVMMR0 = NULL;
119/** Init counter. */
120static unsigned g_cInits = 0;
121/** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
122static uint32_t g_u32FakeMode = ~0;
123
124
125/*******************************************************************************
126* Internal Functions *
127*******************************************************************************/
128static int supLoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase);
129#ifndef VBOX_WITHOUT_IDT_PATCHING
130static int supInstallIDTE(void);
131#endif
132static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
133
134
135SUPR3DECL(int) SUPInstall(void)
136{
137 return suplibOsInstall();
138}
139
140
141SUPR3DECL(int) SUPUninstall(void)
142{
143 return suplibOsUninstall();
144}
145
146
147SUPR3DECL(int) SUPInit(PSUPDRVSESSION *ppSession /* NULL */, size_t cbReserve /* 0 */)
148{
149 /*
150 * Check if already initialized.
151 */
152 if (ppSession)
153 *ppSession = g_pSession;
154 if (g_cInits++ > 0)
155 return VINF_SUCCESS;
156
157 /*
158 * Check for fake mode.
159 * Fake mode is used when we're doing smoke testing and debugging.
160 * It's also useful on platforms where we haven't root access or which
161 * we haven't ported the support driver to.
162 */
163 if (g_u32FakeMode == ~0U)
164 {
165 const char *psz = getenv("VBOX_SUPLIB_FAKE");
166 if (psz && !strcmp(psz, "fake"))
167 ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
168 else
169 ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
170 }
171 if (g_u32FakeMode)
172 {
173 Log(("SUP: Fake mode!\n"));
174
175 /* fake r0 functions. */
176 g_pFunctions = (PSUPQUERYFUNCS_OUT)RTMemAllocZ(RT_OFFSETOF(SUPQUERYFUNCS_OUT, aFunctions[8]));
177 if (g_pFunctions)
178 {
179 g_pFunctions->aFunctions[0].pfn = (void *)0xefefefef;
180 strcpy(g_pFunctions->aFunctions[0].szName, "SUPR0ContAlloc");
181 g_pFunctions->aFunctions[1].pfn = (void *)0xefefefdf;
182 strcpy(g_pFunctions->aFunctions[1].szName, "SUPR0ContFree");
183 g_pFunctions->aFunctions[2].pfn = (void *)0xefefefcf;
184 strcpy(g_pFunctions->aFunctions[2].szName, "SUPR0LockMem");
185 g_pFunctions->aFunctions[3].pfn = (void *)0xefefefbf;
186 strcpy(g_pFunctions->aFunctions[3].szName, "SUPR0UnlockMem");
187 g_pFunctions->aFunctions[4].pfn = (void *)0xefefefaf;
188 strcpy(g_pFunctions->aFunctions[4].szName, "SUPR0LockedAlloc");
189 g_pFunctions->aFunctions[5].pfn = (void *)0xefefef9f;
190 strcpy(g_pFunctions->aFunctions[5].szName, "SUPR0LockedFree");
191 g_pFunctions->aFunctions[6].pfn = (void *)0xefefef8f;
192 strcpy(g_pFunctions->aFunctions[6].szName, "SUPR0Printf");
193 g_pFunctions->cFunctions = 7;
194 g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
195 if (ppSession)
196 *ppSession = g_pSession;
197#ifndef VBOX_WITHOUT_IDT_PATCHING
198 Assert(g_u8Interrupt == 3);
199#endif
200 /* fake the GIP. */
201 g_pSUPGlobalInfoPage = (PCSUPGLOBALINFOPAGE)RTMemPageAlloc(PAGE_SIZE);
202 if (g_pSUPGlobalInfoPage)
203 {
204 g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;
205 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;
206 /* the page is supposed to be invalid, so don't set a correct magic. */
207 return VINF_SUCCESS;
208 }
209 RTMemFree(g_pFunctions);
210 g_pFunctions = NULL;
211 }
212 return VERR_NO_MEMORY;
213 }
214
215 /**
216 * Open the support driver.
217 */
218 int rc = suplibOsInit(cbReserve);
219 if (VBOX_SUCCESS(rc))
220 {
221 /*
222 * Negotiate the cookie.
223 */
224 SUPCOOKIE_IN In;
225 SUPCOOKIE_OUT Out = {0,0};
226 strcpy(In.szMagic, SUPCOOKIE_MAGIC);
227 In.u32Version = SUPDRVIOC_VERSION;
228 rc = suplibOsIOCtl(SUP_IOCTL_COOKIE, &In, sizeof(In), &Out, sizeof(Out));
229 if (VBOX_SUCCESS(rc))
230 {
231 if (Out.u32Version == SUPDRVIOC_VERSION)
232 {
233 /*
234 * Query the functions.
235 */
236 SUPQUERYFUNCS_IN FuncsIn;
237 FuncsIn.u32Cookie = Out.u32Cookie;
238 FuncsIn.u32SessionCookie = Out.u32SessionCookie;
239 unsigned cbFuncsOut = RT_OFFSETOF(SUPQUERYFUNCS_OUT, aFunctions[Out.cFunctions]);
240 PSUPQUERYFUNCS_OUT pFuncsOut = (PSUPQUERYFUNCS_OUT)RTMemAllocZ(cbFuncsOut);
241 if (pFuncsOut)
242 {
243 rc = suplibOsIOCtl(SUP_IOCTL_QUERY_FUNCS, &FuncsIn, sizeof(FuncsIn), pFuncsOut, cbFuncsOut);
244 if (VBOX_SUCCESS(rc))
245 {
246 g_u32Cookie = Out.u32Cookie;
247 g_u32SessionCookie = Out.u32SessionCookie;
248 g_pSession = Out.pSession;
249 g_pFunctions = pFuncsOut;
250 if (ppSession)
251 *ppSession = Out.pSession;
252
253 /*
254 * Map the GIP into userspace.
255 * This is an optional feature, so we will ignore any failures here.
256 */
257 if (!g_pSUPGlobalInfoPage)
258 {
259 SUPGIPMAP_IN GipIn = {0};
260 SUPGIPMAP_OUT GipOut = {NULL, 0};
261 GipIn.u32Cookie = Out.u32Cookie;
262 GipIn.u32SessionCookie = Out.u32SessionCookie;
263 rc = suplibOsIOCtl(SUP_IOCTL_GIP_MAP, &GipIn, sizeof(GipIn), &GipOut, sizeof(GipOut));
264 if (VBOX_SUCCESS(rc))
265 {
266 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipOut.HCPhysGip);
267 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, (void *)GipOut.pGipR3, NULL);
268 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipOut.pGipR0, NULL);
269 }
270 else
271 rc = VINF_SUCCESS;
272 }
273 return rc;
274 }
275 RTMemFree(pFuncsOut);
276 }
277 else
278 rc = VERR_NO_MEMORY;
279 }
280 else
281 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
282 }
283
284 suplibOsTerm();
285 }
286 AssertMsgFailed(("SUPInit() failed rc=%Vrc\n", rc));
287 g_cInits--;
288
289 return rc;
290}
291
292
293SUPR3DECL(int) SUPTerm(bool fForced)
294{
295 /*
296 * Verify state.
297 */
298 AssertMsg(g_cInits > 0, ("SUPTerm() is called before SUPInit()!\n"));
299 if (g_cInits == 0)
300 return VERR_WRONG_ORDER;
301 if (g_cInits == 1 || fForced)
302 {
303 /*
304 * NULL the GIP pointer.
305 */
306 if (g_pSUPGlobalInfoPage)
307 {
308 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, NULL);
309 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, NULL);
310 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);
311 /* just a little safe guard against threads using the page. */
312 RTThreadSleep(50);
313 }
314
315 /*
316 * Close the support driver.
317 */
318 int rc = suplibOsTerm();
319 if (rc)
320 return rc;
321
322 g_u32Cookie = 0;
323 g_u32SessionCookie = 0;
324#ifndef VBOX_WITHOUT_IDT_PATCHING
325 g_u8Interrupt = 3;
326#endif
327 g_cInits = 0;
328 }
329 else
330 g_cInits--;
331
332 return 0;
333}
334
335
336SUPR3DECL(SUPPAGINGMODE) SUPGetPagingMode(void)
337{
338 /*
339 * Issue IOCtl to the SUPDRV kernel module.
340 */
341 SUPGETPAGINGMODE_IN In;
342 In.u32Cookie = g_u32Cookie;
343 In.u32SessionCookie = g_u32SessionCookie;
344 SUPGETPAGINGMODE_OUT Out = {SUPPAGINGMODE_INVALID};
345 int rc;
346 if (!g_u32FakeMode)
347 {
348 rc = suplibOsIOCtl(SUP_IOCTL_GET_PAGING_MODE, &In, sizeof(In), &Out, sizeof(Out));
349 if (VBOX_FAILURE(rc))
350 Out.enmMode = SUPPAGINGMODE_INVALID;
351 }
352 else
353 Out.enmMode = SUPPAGINGMODE_32_BIT_GLOBAL;
354
355 return Out.enmMode;
356}
357
358SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, unsigned uOperation, void *pvArg, unsigned cbArg)
359{
360 /*
361 * Issue IOCtl to the SUPDRV kernel module.
362 */
363 SUPCALLVMMR0_IN In;
364 In.u32Cookie = g_u32Cookie;
365 In.u32SessionCookie = g_u32SessionCookie;
366 In.pVMR0 = pVMR0;
367 In.uOperation = uOperation;
368 In.cbArg = cbArg;
369 In.pvArg = pvArg;
370 Assert(!g_u32FakeMode);
371 SUPCALLVMMR0_OUT Out = {VINF_SUCCESS};
372 int rc = suplibOsIOCtl(SUP_IOCTL_CALL_VMMR0, &In, sizeof(In), &Out, sizeof(Out));
373 if (VBOX_SUCCESS(rc))
374 rc = Out.rc;
375 return rc;
376}
377
378
379SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg)
380{
381#ifndef VBOX_WITHOUT_IDT_PATCHING
382 return g_pfnCallVMMR0(pVMR0, uOperation, pvArg);
383
384#else
385 if (RT_LIKELY(uOperation == VMMR0_DO_RAW_RUN))
386 {
387 Assert(!pvArg);
388 return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_RAW_RUN);
389 }
390 if (RT_LIKELY(uOperation == VMMR0_DO_HWACC_RUN))
391 {
392 Assert(!pvArg);
393 return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_HWACC_RUN);
394 }
395 if (uOperation == VMMR0_DO_NOP)
396 {
397 Assert(!pvArg);
398 return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_NOP);
399 }
400 return SUPCallVMMR0Ex(pVMR0, uOperation, pvArg, pvArg ? sizeof(pvArg) : 0);
401#endif
402}
403
404
405SUPR3DECL(int) SUPSetVMForFastIOCtl(PVMR0 pVMR0)
406{
407 SUPSETVMFORFAST_IN In;
408 In.u32Cookie = g_u32Cookie;
409 In.u32SessionCookie = g_u32SessionCookie;
410 In.pVMR0 = pVMR0;
411 Assert(!g_u32FakeMode);
412 return suplibOsIOCtl(SUP_IOCTL_SET_VM_FOR_FAST, &In, sizeof(In), NULL, 0);
413}
414
415
416SUPR3DECL(int) SUPPageLock(void *pvStart, size_t cbMemory, PSUPPAGE paPages)
417{
418 /*
419 * Validate.
420 */
421 AssertPtr(pvStart);
422 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
423 AssertMsg(RT_ALIGN_Z(cbMemory, PAGE_SIZE) == cbMemory, ("cbMemory (%#zx) must be page aligned\n", cbMemory));
424 AssertPtr(paPages);
425
426 /*
427 * Issue IOCtl to the SUPDRV kernel module.
428 */
429 SUPPINPAGES_IN In;
430 In.u32Cookie = g_u32Cookie;
431 In.u32SessionCookie = g_u32SessionCookie;
432 In.pv = pvStart;
433 In.cb = (uint32_t)cbMemory; AssertRelease(In.cb == cbMemory);
434 PSUPPINPAGES_OUT pOut = (PSUPPINPAGES_OUT)(void*)paPages;
435 Assert(RT_OFFSETOF(SUPPINPAGES_OUT, aPages) == 0 && sizeof(paPages[0]) == sizeof(pOut->aPages[0]));
436 int rc;
437 if (!g_u32FakeMode)
438 rc = suplibOsIOCtl(SUP_IOCTL_PINPAGES, &In, sizeof(In), pOut, RT_OFFSETOF(SUPPINPAGES_OUT, aPages[cbMemory >> PAGE_SHIFT]));
439 else
440 {
441 /* fake a successfull result. */
442 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
443 unsigned iPage = (unsigned)cbMemory >> PAGE_SHIFT;
444 while (iPage-- > 0)
445 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
446 rc = VINF_SUCCESS;
447 }
448
449 return rc;
450}
451
452
453SUPR3DECL(int) SUPPageUnlock(void *pvStart)
454{
455 /*
456 * Validate.
457 */
458 AssertPtr(pvStart);
459 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
460
461 /*
462 * Issue IOCtl to the SUPDRV kernel module.
463 */
464 SUPUNPINPAGES_IN In;
465 In.u32Cookie = g_u32Cookie;
466 In.u32SessionCookie = g_u32SessionCookie;
467 In.pv = pvStart;
468 int rc;
469 if (!g_u32FakeMode)
470 rc = suplibOsIOCtl(SUP_IOCTL_UNPINPAGES, &In, sizeof(In), NULL, 0);
471 else
472 rc = VINF_SUCCESS;
473
474 return rc;
475}
476
477
478SUPR3DECL(void *) SUPContAlloc(unsigned cb, PRTHCPHYS pHCPhys)
479{
480 return SUPContAlloc2(cb, NIL_RTR0PTR, pHCPhys);
481}
482
483
484SUPR3DECL(void *) SUPContAlloc2(unsigned cb, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)
485{
486 /*
487 * Validate.
488 */
489 AssertMsg(cb > 64 && cb < PAGE_SIZE * 256, ("cb=%d must be > 64 and < %d (256 pages)\n", cb, PAGE_SIZE * 256));
490 AssertPtr(pHCPhys);
491 *pHCPhys = NIL_RTHCPHYS;
492 AssertPtrNull(pR0Ptr);
493 if (pR0Ptr)
494 *pR0Ptr = NIL_RTR0PTR;
495
496 /*
497 * Issue IOCtl to the SUPDRV kernel module.
498 */
499 SUPCONTALLOC_IN In;
500 In.u32Cookie = g_u32Cookie;
501 In.u32SessionCookie = g_u32SessionCookie;
502 In.cb = RT_ALIGN_32(cb, PAGE_SIZE);
503 SUPCONTALLOC_OUT Out;
504 int rc;
505 if (!g_u32FakeMode)
506 rc = suplibOsIOCtl(SUP_IOCTL_CONT_ALLOC, &In, sizeof(In), &Out, sizeof(Out));
507 else
508 {
509 rc = SUPPageAlloc(In.cb >> PAGE_SHIFT, &Out.pvR3);
510 Out.HCPhys = (uintptr_t)Out.pvR3 + (PAGE_SHIFT * 1024);
511 Out.pvR0 = (uintptr_t)Out.pvR3;
512 }
513 if (VBOX_SUCCESS(rc))
514 {
515 *pHCPhys = (RTHCPHYS)Out.HCPhys;
516 if (pR0Ptr)
517 *pR0Ptr = Out.pvR0;
518 return Out.pvR3;
519 }
520
521 return NULL;
522}
523
524
525SUPR3DECL(int) SUPContFree(void *pv)
526{
527 /*
528 * Validate.
529 */
530 AssertPtr(pv);
531 if (!pv)
532 return VINF_SUCCESS;
533
534 /*
535 * Issue IOCtl to the SUPDRV kernel module.
536 */
537 SUPCONTFREE_IN In;
538 In.u32Cookie = g_u32Cookie;
539 In.u32SessionCookie = g_u32SessionCookie;
540 In.pv = pv;
541 int rc;
542 if (!g_u32FakeMode)
543 rc = suplibOsIOCtl(SUP_IOCTL_CONT_FREE, &In, sizeof(In), NULL, 0);
544 else
545 rc = SUPPageFree(pv);
546
547 return rc;
548}
549
550
551SUPR3DECL(int) SUPLowAlloc(unsigned cPages, void **ppvPages, PSUPPAGE paPages)
552{
553 /*
554 * Validate.
555 */
556 AssertMsg(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages));
557 AssertPtr(ppvPages);
558 *ppvPages = NULL;
559 AssertPtr(paPages);
560
561 int rc;
562 if (!g_u32FakeMode)
563 {
564 /*
565 * Issue IOCtl to the SUPDRV kernel module.
566 */
567 SUPLOWALLOC_IN In;
568 In.u32Cookie = g_u32Cookie;
569 In.u32SessionCookie = g_u32SessionCookie;
570 In.cPages = cPages;
571 size_t cbOut = RT_OFFSETOF(SUPLOWALLOC_OUT, aPages[cPages]);
572 PSUPLOWALLOC_OUT pOut = (PSUPLOWALLOC_OUT)RTMemAllocZ(cbOut);
573 if (pOut)
574 {
575 rc = suplibOsIOCtl(SUP_IOCTL_LOW_ALLOC, &In, sizeof(In), pOut, cbOut);
576 if (VBOX_SUCCESS(rc))
577 {
578 *ppvPages = pOut->pvVirt;
579 AssertCompile(sizeof(paPages[0]) == sizeof(pOut->aPages[0]));
580 memcpy(paPages, &pOut->aPages[0], sizeof(paPages[0]) * cPages);
581#if HC_ARCH_BITS == 64 /* -> strict only */
582 for (unsigned i = 0; i < cPages; i++)
583 AssertReleaseMsg( paPages[i].Phys <= 0xfffff000
584 && !(paPages[i].Phys & PAGE_OFFSET_MASK)
585 && paPages[i].Phys > 0,
586 ("[%d]=%VHp\n", paPages[i].Phys));
587#endif
588 }
589 RTMemFree(pOut);
590 }
591 else
592 rc = VERR_NO_MEMORY;
593 }
594 else
595 {
596 rc = SUPPageAlloc(cPages, ppvPages);
597 if (VBOX_SUCCESS(rc))
598 {
599 /* fake physical addresses. */
600 RTHCPHYS Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;
601 unsigned iPage = cPages;
602 while (iPage-- > 0)
603 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
604 }
605 }
606
607 return rc;
608}
609
610
611SUPR3DECL(int) SUPLowFree(void *pv)
612{
613 /*
614 * Validate.
615 */
616 AssertPtr(pv);
617 if (!pv)
618 return VINF_SUCCESS;
619
620 /*
621 * Issue IOCtl to the SUPDRV kernel module.
622 */
623 SUPLOWFREE_IN In;
624 In.u32Cookie = g_u32Cookie;
625 In.u32SessionCookie = g_u32SessionCookie;
626 In.pv = pv;
627 int rc;
628 if (!g_u32FakeMode)
629 rc = suplibOsIOCtl(SUP_IOCTL_LOW_FREE, &In, sizeof(In), NULL, 0);
630 else
631 rc = SUPPageFree(pv);
632
633 return rc;
634}
635
636
637SUPR3DECL(int) SUPPageAlloc(size_t cPages, void **ppvPages)
638{
639 /*
640 * Validate.
641 */
642 if (cPages == 0)
643 {
644 AssertMsgFailed(("Invalid param cPages=0, must be > 0\n"));
645 return VERR_INVALID_PARAMETER;
646 }
647 AssertPtr(ppvPages);
648 if (!ppvPages)
649 return VERR_INVALID_PARAMETER;
650 *ppvPages = NULL;
651
652 /*
653 * Call OS specific worker.
654 */
655 return suplibOsPageAlloc(cPages, ppvPages);
656}
657
658
659SUPR3DECL(int) SUPPageFree(void *pvPages)
660{
661 /*
662 * Validate.
663 */
664 AssertPtr(pvPages);
665 if (!pvPages)
666 return VINF_SUCCESS;
667
668 /*
669 * Call OS specific worker.
670 */
671 return suplibOsPageFree(pvPages);
672}
673
674
675SUPR3DECL(int) SUPLoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase)
676{
677 /*
678 * Load the module.
679 * If it's VMMR0.r0 we need to install the IDTE.
680 */
681 int rc = supLoadModule(pszFilename, pszModule, ppvImageBase);
682#ifndef VBOX_WITHOUT_IDT_PATCHING
683 if ( VBOX_SUCCESS(rc)
684 && !strcmp(pszModule, "VMMR0.r0"))
685 {
686 rc = supInstallIDTE();
687 if (VBOX_FAILURE(rc))
688 SUPFreeModule(*ppvImageBase);
689 }
690#endif /* VBOX_WITHOUT_IDT_PATCHING */
691
692 return rc;
693}
694
695
696#ifndef VBOX_WITHOUT_IDT_PATCHING
697/**
698 * Generates the code for calling the interrupt gate.
699 *
700 * @returns VBox status code.
701 * g_pfnCallVMMR0 is changed on success.
702 * @param u8Interrupt The interrupt number.
703 */
704static int suplibGenerateCallVMMR0(uint8_t u8Interrupt)
705{
706 /*
707 * Allocate memory.
708 */
709 uint8_t *pb = (uint8_t *)RTMemExecAlloc(256);
710 AssertReturn(pb, VERR_NO_MEMORY);
711 memset(pb, 0xcc, 256);
712 Assert(!g_pfnCallVMMR0);
713 g_pfnCallVMMR0 = *(PFNCALLVMMR0*)&pb;
714
715 /*
716 * Generate the code.
717 */
718#ifdef __AMD64__
719 /*
720 * reg params:
721 * <GCC> <MSC> <argument>
722 * rdi rcx pVMR0
723 * esi edx uOperation
724 * rdx r8 pvArg
725 *
726 * eax eax [g_u32Gookie]
727 */
728 *pb++ = 0xb8; /* mov eax, <g_u32Cookie> */
729 *(uint32_t *)pb = g_u32Cookie;
730 pb += sizeof(uint32_t);
731
732 *pb++ = 0xcd; /* int <u8Interrupt> */
733 *pb++ = u8Interrupt;
734
735 *pb++ = 0xc3; /* ret */
736
737#else
738 /*
739 * x86 stack:
740 * 0 saved esi
741 * 0 4 ret
742 * 4 8 pVM
743 * 8 c uOperation
744 * c 10 pvArg
745 */
746 *pb++ = 0x56; /* push esi */
747
748 *pb++ = 0x8b; /* mov eax, [pVM] */
749 *pb++ = 0x44;
750 *pb++ = 0x24;
751 *pb++ = 0x08; /* esp+08h */
752
753 *pb++ = 0x8b; /* mov edx, [uOperation] */
754 *pb++ = 0x54;
755 *pb++ = 0x24;
756 *pb++ = 0x0c; /* esp+0ch */
757
758 *pb++ = 0x8b; /* mov ecx, [pvArg] */
759 *pb++ = 0x4c;
760 *pb++ = 0x24;
761 *pb++ = 0x10; /* esp+10h */
762
763 *pb++ = 0xbe; /* mov esi, <g_u32Cookie> */
764 *(uint32_t *)pb = g_u32Cookie;
765 pb += sizeof(uint32_t);
766
767 *pb++ = 0xcd; /* int <u8Interrupt> */
768 *pb++ = u8Interrupt;
769
770 *pb++ = 0x5e; /* pop esi */
771
772 *pb++ = 0xc3; /* ret */
773#endif
774
775 return VINF_SUCCESS;
776}
777
778
779/**
780 * Installs the IDTE patch.
781 *
782 * @return VBox status code.
783 */
784static int supInstallIDTE(void)
785{
786 /* already installed? */
787 if (g_u8Interrupt != 3 || g_u32FakeMode)
788 return VINF_SUCCESS;
789
790 int rc = VINF_SUCCESS;
791 const unsigned cCpus = RTSystemProcessorGetCount();
792 if (cCpus <= 1)
793 {
794 /* UNI */
795 SUPIDTINSTALL_IN In;
796 In.u32Cookie = g_u32Cookie;
797 In.u32SessionCookie = g_u32SessionCookie;
798 SUPIDTINSTALL_OUT Out = {3};
799
800 rc = suplibOsIOCtl(SUP_IOCTL_IDT_INSTALL, &In, sizeof(In), &Out, sizeof(Out));
801 if (VBOX_SUCCESS(rc))
802 {
803 g_u8Interrupt = Out.u8Idt;
804 rc = suplibGenerateCallVMMR0(Out.u8Idt);
805 }
806 }
807 else
808 {
809 /* SMP */
810 uint64_t u64AffMaskSaved = RTThreadGetAffinity();
811 uint64_t u64AffMaskPatched = RTSystemProcessorGetActiveMask() & u64AffMaskSaved;
812 unsigned cCpusPatched = 0;
813
814 for (int i = 0; i < 64; i++)
815 {
816 /* Skip absent and inactive processors. */
817 uint64_t u64Mask = 1ULL << i;
818 if (!(u64Mask & u64AffMaskPatched))
819 continue;
820
821 /* Change CPU */
822 int rc2 = RTThreadSetAffinity(u64Mask);
823 if (VBOX_FAILURE(rc2))
824 {
825 u64AffMaskPatched &= ~u64Mask;
826 Log(("SUPLoadVMM: Failed to set affinity to cpu no. %d, rc=%Vrc.\n", i, rc2));
827 continue;
828 }
829
830 /* Patch the CPU. */
831 SUPIDTINSTALL_IN In;
832 In.u32Cookie = g_u32Cookie;
833 In.u32SessionCookie = g_u32SessionCookie;
834 SUPIDTINSTALL_OUT Out = {3};
835
836 rc2 = suplibOsIOCtl(SUP_IOCTL_IDT_INSTALL, &In, sizeof(In), &Out, sizeof(Out));
837 if (VBOX_SUCCESS(rc2))
838 {
839 if (!cCpusPatched)
840 {
841 g_u8Interrupt = Out.u8Idt;
842 rc2 = suplibGenerateCallVMMR0(Out.u8Idt);
843 if (VBOX_FAILURE(rc))
844 rc2 = rc;
845 }
846 else
847 Assert(g_u8Interrupt == Out.u8Idt);
848 cCpusPatched++;
849 }
850 else
851 {
852
853 Log(("SUPLoadVMM: Failed to patch cpu no. %d, rc=%Vrc.\n", i, rc2));
854 if (VBOX_SUCCESS(rc))
855 rc = rc2;
856 }
857 }
858
859 /* Fail if no CPUs was patched! */
860 if (VBOX_SUCCESS(rc) && cCpusPatched <= 0)
861 rc = VERR_GENERAL_FAILURE;
862 /* Ignore failures if a CPU was patched. */
863 else if (VBOX_FAILURE(rc) && cCpusPatched > 0)
864 {
865 /** @todo add an eventlog/syslog line out this. */
866 rc = VINF_SUCCESS;
867 }
868
869 /* Set/restore the thread affinity. */
870 if (VBOX_SUCCESS(rc))
871 {
872 rc = RTThreadSetAffinity(u64AffMaskPatched);
873 AssertRC(rc);
874 }
875 else
876 {
877 int rc2 = RTThreadSetAffinity(u64AffMaskSaved);
878 AssertRC(rc2);
879 }
880 }
881 return rc;
882}
883#endif /* !VBOX_WITHOUT_IDT_PATCHING */
884
885
886/**
887 * Resolve an external symbol during RTLdrGetBits().
888 *
889 * @returns VBox status code.
890 * @param hLdrMod The loader module handle.
891 * @param pszModule Module name.
892 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
893 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
894 * @param pValue Where to store the symbol value (address).
895 * @param pvUser User argument.
896 */
897static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
898 const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
899{
900 AssertPtr(pValue);
901 AssertPtr(pvUser);
902
903 /*
904 * Only SUPR0 and VMMR0.r0
905 */
906 if ( pszModule
907 && *pszModule
908 && strcmp(pszModule, "SUPR0.dll")
909 && strcmp(pszModule, "VMMR0.r0"))
910 {
911 AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitiv)\n", pvUser, pszModule));
912 return VERR_SYMBOL_NOT_FOUND;
913 }
914
915 /*
916 * No ordinals.
917 */
918 if (pszSymbol < (const char*)0x10000)
919 {
920 AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
921 return VERR_SYMBOL_NOT_FOUND;
922 }
923
924 /*
925 * Lookup symbol.
926 */
927 /* skip the 64-bit ELF import prefix first. */
928 if (!strncmp(pszSymbol, "SUPR0$", sizeof("SUPR0$") - 1))
929 pszSymbol += sizeof("SUPR0$") - 1;
930
931 /* iterate the function table. */
932 int c = g_pFunctions->cFunctions;
933 PSUPFUNC pFunc = &g_pFunctions->aFunctions[0];
934 while (c-- > 0)
935 {
936 if (!strcmp(pFunc->szName, pszSymbol))
937 {
938 *pValue = (uintptr_t)pFunc->pfn;
939 return VINF_SUCCESS;
940 }
941 pFunc++;
942 }
943
944 /*
945 * Check the VMMR0.r0 module if loaded.
946 */
947 /** @todo call the SUPLoadModule caller.... */
948 /** @todo proper reference counting and such. */
949 if (g_pvVMMR0)
950 {
951 void *pvValue;
952 if (!SUPGetSymbolR0(g_pvVMMR0, pszSymbol, &pvValue))
953 {
954 *pValue = (uintptr_t)pvValue;
955 return VINF_SUCCESS;
956 }
957 }
958
959 /*
960 * The GIP.
961 */
962 /** @todo R0 mapping? */
963 if ( pszSymbol
964 && g_pSUPGlobalInfoPage
965 && g_pSUPGlobalInfoPageR0
966 && !strcmp(pszSymbol, "g_SUPGlobalInfoPage"))
967 {
968 *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
969 return VINF_SUCCESS;
970 }
971
972 /*
973 * Despair.
974 */
975 c = g_pFunctions->cFunctions;
976 pFunc = &g_pFunctions->aFunctions[0];
977 while (c-- > 0)
978 {
979 AssertMsg2("%d: %s\n", g_pFunctions->cFunctions - c, pFunc->szName);
980 pFunc++;
981 }
982
983 AssertMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
984 return VERR_SYMBOL_NOT_FOUND;
985}
986
987
988/** Argument package for supLoadModuleCalcSizeCB. */
989typedef struct SUPLDRCALCSIZEARGS
990{
991 size_t cbStrings;
992 uint32_t cSymbols;
993 size_t cbImage;
994} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
995
996/**
997 * Callback used to calculate the image size.
998 * @return VINF_SUCCESS
999 */
1000static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1001{
1002 PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
1003 if ( pszSymbol != NULL
1004 && *pszSymbol
1005 && Value <= pArgs->cbImage)
1006 {
1007 pArgs->cSymbols++;
1008 pArgs->cbStrings += strlen(pszSymbol) + 1;
1009 }
1010 return VINF_SUCCESS;
1011}
1012
1013
1014/** Argument package for supLoadModuleCreateTabsCB. */
1015typedef struct SUPLDRCREATETABSARGS
1016{
1017 size_t cbImage;
1018 PSUPLDRSYM pSym;
1019 char *pszBase;
1020 char *psz;
1021} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
1022
1023/**
1024 * Callback used to calculate the image size.
1025 * @return VINF_SUCCESS
1026 */
1027static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1028{
1029 PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
1030 if ( pszSymbol != NULL
1031 && *pszSymbol
1032 && Value <= pArgs->cbImage)
1033 {
1034 pArgs->pSym->offSymbol = (uint32_t)Value;
1035 pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
1036 pArgs->pSym++;
1037
1038 size_t cbCopy = strlen(pszSymbol) + 1;
1039 memcpy(pArgs->psz, pszSymbol, cbCopy);
1040 pArgs->psz += cbCopy;
1041 }
1042 return VINF_SUCCESS;
1043}
1044
1045
1046/**
1047 * Worker for SUPLoadModule().
1048 *
1049 * @returns VBox status code.
1050 * @param pszFilename Name of the VMMR0 image file
1051 */
1052static int supLoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase)
1053{
1054 /*
1055 * Validate input.
1056 */
1057 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1058 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
1059 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
1060 AssertReturn(strlen(pszModule) < SIZEOFMEMB(SUPLDROPEN_IN, szName), VERR_FILENAME_TOO_LONG);
1061
1062 const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
1063 *ppvImageBase = NULL;
1064
1065 /*
1066 * Open image file and figure its size.
1067 */
1068 RTLDRMOD hLdrMod;
1069 int rc = RTLdrOpen(pszFilename, &hLdrMod);
1070 if (!VBOX_SUCCESS(rc))
1071 return rc;
1072
1073 SUPLDRCALCSIZEARGS CalcArgs;
1074 CalcArgs.cbStrings = 0;
1075 CalcArgs.cSymbols = 0;
1076 CalcArgs.cbImage = RTLdrSize(hLdrMod);
1077 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
1078 if (VBOX_SUCCESS(rc))
1079 {
1080 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
1081 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
1082 const uint32_t cbImage = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
1083
1084 /*
1085 * Open the R0 image.
1086 */
1087 SUPLDROPEN_IN OpenIn;
1088 OpenIn.u32Cookie = g_u32Cookie;
1089 OpenIn.u32SessionCookie = g_u32SessionCookie;
1090 OpenIn.cbImage = cbImage;
1091 strcpy(OpenIn.szName, pszModule);
1092 SUPLDROPEN_OUT OpenOut;
1093 if (!g_u32FakeMode)
1094 rc = suplibOsIOCtl(SUP_IOCTL_LDR_OPEN, &OpenIn, sizeof(OpenIn), &OpenOut, sizeof(OpenOut));
1095 else
1096 {
1097 OpenOut.fNeedsLoading = true;
1098 OpenOut.pvImageBase = (void *)0xef423420;
1099 }
1100 *ppvImageBase = OpenOut.pvImageBase;
1101 if ( VBOX_SUCCESS(rc)
1102 && OpenOut.fNeedsLoading)
1103 {
1104 /*
1105 * We need to load it.
1106 * Allocate memory for the image bits.
1107 */
1108 unsigned cbIn = RT_OFFSETOF(SUPLDRLOAD_IN, achImage[cbImage]);
1109 PSUPLDRLOAD_IN pIn = (PSUPLDRLOAD_IN)RTMemTmpAlloc(cbIn);
1110 if (pIn)
1111 {
1112 /*
1113 * Get the image bits.
1114 */
1115 rc = RTLdrGetBits(hLdrMod, &pIn->achImage[0], (uintptr_t)OpenOut.pvImageBase,
1116 supLoadModuleResolveImport, (void *)pszModule);
1117
1118 /*
1119 * Get the entry points.
1120 */
1121 RTUINTPTR VMMR0Entry = 0;
1122 RTUINTPTR ModuleInit = 0;
1123 RTUINTPTR ModuleTerm = 0;
1124 if (fIsVMMR0 && VBOX_SUCCESS(rc))
1125 rc = RTLdrGetSymbolEx(hLdrMod, &pIn->achImage[0], (uintptr_t)OpenOut.pvImageBase, "VMMR0Entry", &VMMR0Entry);
1126 if (VBOX_SUCCESS(rc))
1127 {
1128 rc = RTLdrGetSymbolEx(hLdrMod, &pIn->achImage[0], (uintptr_t)OpenOut.pvImageBase, "ModuleInit", &ModuleInit);
1129 if (VBOX_FAILURE(rc))
1130 ModuleInit = 0;
1131
1132 rc = RTLdrGetSymbolEx(hLdrMod, &pIn->achImage[0], (uintptr_t)OpenOut.pvImageBase, "ModuleTerm", &ModuleTerm);
1133 if (VBOX_FAILURE(rc))
1134 ModuleTerm = 0;
1135 }
1136
1137 /*
1138 * Create the symbol and string tables.
1139 */
1140 SUPLDRCREATETABSARGS CreateArgs;
1141 CreateArgs.cbImage = CalcArgs.cbImage;
1142 CreateArgs.pSym = (PSUPLDRSYM)&pIn->achImage[offSymTab];
1143 CreateArgs.pszBase = (char *)&pIn->achImage[offStrTab];
1144 CreateArgs.psz = CreateArgs.pszBase;
1145 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
1146 if (VBOX_SUCCESS(rc))
1147 {
1148 AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
1149 AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pIn->achImage[offSymTab]) <= CalcArgs.cSymbols);
1150
1151 /*
1152 * Upload the image.
1153 */
1154 pIn->u32Cookie = g_u32Cookie;
1155 pIn->u32SessionCookie = g_u32SessionCookie;
1156 pIn->pfnModuleInit = (PFNR0MODULEINIT)(uintptr_t)ModuleInit;
1157 pIn->pfnModuleTerm = (PFNR0MODULETERM)(uintptr_t)ModuleTerm;
1158 if (fIsVMMR0)
1159 {
1160 pIn->eEPType = pIn->EP_VMMR0;
1161 pIn->EP.VMMR0.pvVMMR0 = OpenOut.pvImageBase;
1162 pIn->EP.VMMR0.pvVMMR0Entry = (void *)(uintptr_t)VMMR0Entry;
1163 }
1164 else
1165 pIn->eEPType = pIn->EP_NOTHING;
1166 pIn->offStrTab = offStrTab;
1167 pIn->cbStrTab = CalcArgs.cbStrings;
1168 pIn->offSymbols = offSymTab;
1169 pIn->cSymbols = CalcArgs.cSymbols;
1170 pIn->cbImage = cbImage;
1171 pIn->pvImageBase = OpenOut.pvImageBase;
1172 if (!g_u32FakeMode)
1173 rc = suplibOsIOCtl(SUP_IOCTL_LDR_LOAD, pIn, cbIn, NULL, 0);
1174 else
1175 rc = VINF_SUCCESS;
1176 if ( VBOX_SUCCESS(rc)
1177 || rc == VERR_ALREADY_LOADED /* this is because of a competing process. */
1178 )
1179 {
1180 if (fIsVMMR0)
1181 g_pvVMMR0 = OpenOut.pvImageBase;
1182 RTMemTmpFree(pIn);
1183 RTLdrClose(hLdrMod);
1184 return VINF_SUCCESS;
1185 }
1186 }
1187 RTMemTmpFree(pIn);
1188 }
1189 else
1190 {
1191 AssertMsgFailed(("failed to allocated %d bytes for SUPLDRLOAD_IN structure!\n", cbIn));
1192 rc = VERR_NO_TMP_MEMORY;
1193 }
1194 }
1195 }
1196 RTLdrClose(hLdrMod);
1197 return rc;
1198}
1199
1200
1201SUPR3DECL(int) SUPFreeModule(void *pvImageBase)
1202{
1203 /*
1204 * There is one special module. When this is freed we'll
1205 * free the IDT entry that goes with it.
1206 *
1207 * Note that we don't keep count of VMMR0.r0 loads here, so the
1208 * first unload will free it.
1209 */
1210 if (pvImageBase == g_pvVMMR0)
1211 {
1212 /*
1213 * This is the point where we remove the IDT hook. We do
1214 * that before unloading the R0 VMM part.
1215 */
1216 if (g_u32FakeMode)
1217 {
1218#ifndef VBOX_WITHOUT_IDT_PATCHING
1219 g_u8Interrupt = 3;
1220 RTMemExecFree(*(void **)&g_pfnCallVMMR0);
1221 g_pfnCallVMMR0 = NULL;
1222#endif
1223 g_pvVMMR0 = NULL;
1224 return VINF_SUCCESS;
1225 }
1226
1227#ifndef VBOX_WITHOUT_IDT_PATCHING
1228 /*
1229 * Uninstall IDT entry.
1230 */
1231 int rc = 0;
1232 if (g_u8Interrupt != 3)
1233 {
1234 SUPIDTREMOVE_IN In;
1235 In.u32Cookie = g_u32Cookie;
1236 In.u32SessionCookie = g_u32SessionCookie;
1237 rc = suplibOsIOCtl(SUP_IOCTL_IDT_REMOVE, &In, sizeof(In), NULL, 0);
1238 g_u8Interrupt = 3;
1239 RTMemExecFree(*(void **)&g_pfnCallVMMR0);
1240 g_pfnCallVMMR0 = NULL;
1241 }
1242#endif
1243 }
1244
1245 /*
1246 * Free the requested module.
1247 */
1248 SUPLDRFREE_IN In;
1249 In.u32Cookie = g_u32Cookie;
1250 In.u32SessionCookie = g_u32SessionCookie;
1251 In.pvImageBase = pvImageBase;
1252 int rc = VINF_SUCCESS;
1253 if (!g_u32FakeMode)
1254 rc = suplibOsIOCtl(SUP_IOCTL_LDR_FREE, &In, sizeof(In), NULL, 0);
1255 if ( VBOX_SUCCESS(rc)
1256 && pvImageBase == g_pvVMMR0)
1257 g_pvVMMR0 = NULL;
1258 return rc;
1259}
1260
1261
1262SUPR3DECL(int) SUPGetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
1263{
1264 *ppvValue = NULL;
1265
1266 /*
1267 * Do ioctl.
1268 */
1269 size_t cchSymbol = strlen(pszSymbol);
1270 const size_t cbIn = RT_OFFSETOF(SUPLDRGETSYMBOL_IN, szSymbol[cchSymbol + 1]);
1271 SUPLDRGETSYMBOL_OUT Out = { NULL };
1272 PSUPLDRGETSYMBOL_IN pIn = (PSUPLDRGETSYMBOL_IN)alloca(cbIn);
1273 pIn->u32Cookie = g_u32Cookie;
1274 pIn->u32SessionCookie = g_u32SessionCookie;
1275 pIn->pvImageBase = pvImageBase;
1276 memcpy(pIn->szSymbol, pszSymbol, cchSymbol + 1);
1277 int rc = suplibOsIOCtl(SUP_IOCTL_LDR_GET_SYMBOL, pIn, cbIn, &Out, sizeof(Out));
1278 if (VBOX_SUCCESS(rc))
1279 *ppvValue = Out.pvSymbol;
1280 return rc;
1281}
1282
1283
1284SUPR3DECL(int) SUPLoadVMM(const char *pszFilename)
1285{
1286 void *pvImageBase;
1287 return SUPLoadModule(pszFilename, "VMMR0.r0", &pvImageBase);
1288}
1289
1290
1291SUPR3DECL(int) SUPUnloadVMM(void)
1292{
1293 return SUPFreeModule(g_pvVMMR0);
1294}
1295
1296
1297SUPR3DECL(int) SUPGipGetPhys(PRTHCPHYS pHCPhys)
1298{
1299 if (g_pSUPGlobalInfoPage)
1300 {
1301 *pHCPhys = g_HCPhysSUPGlobalInfoPage;
1302 return VINF_SUCCESS;
1303 }
1304 *pHCPhys = NIL_RTHCPHYS;
1305 return VERR_WRONG_ORDER;
1306}
1307
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette