VirtualBox

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

最後變更 在這個檔案從90970是 90970,由 vboxsync 提交於 4 年 前

VMM,SUPDrv: Use 4 buffers for each EMT logger in ring-0, making it very likely that we can avoid having to wait for the flush thread. Bumped the min supdrv version, as we require the log.cpp changes from the previous commit. bugref:10086

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 82.6 KB
 
1/* $Id: SUPLib.cpp 90970 2021-08-27 22:14:33Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Common code.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/** @page pg_sup SUP - The Support Library
28 *
29 * The support library is responsible for providing facilities to load
30 * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
31 * code, to pin down physical memory, and more.
32 *
33 * The VMM Host Ring-0 code can be combined in the support driver if
34 * permitted by kernel module license policies. If it is not combined
35 * it will be externalized in a .r0 module that will be loaded using
36 * the IPRT loader.
37 *
38 * The Ring-0 calling is done thru a generic SUP interface which will
39 * transfer an argument set and call a predefined entry point in the Host
40 * VMM Ring-0 code.
41 *
42 * See @ref grp_sup "SUP - Support APIs" for API details.
43 */
44
45
46/*********************************************************************************************************************************
47* Header Files *
48*********************************************************************************************************************************/
49#define LOG_GROUP LOG_GROUP_SUP
50#include <VBox/sup.h>
51#include <VBox/err.h>
52#include <VBox/param.h>
53#include <VBox/log.h>
54#include <VBox/VBoxTpG.h>
55
56#include <iprt/assert.h>
57#include <iprt/alloc.h>
58#include <iprt/alloca.h>
59#include <iprt/ldr.h>
60#include <iprt/asm.h>
61#include <iprt/mp.h>
62#include <iprt/cpuset.h>
63#include <iprt/thread.h>
64#include <iprt/process.h>
65#include <iprt/path.h>
66#include <iprt/string.h>
67#include <iprt/env.h>
68#include <iprt/rand.h>
69#include <iprt/x86.h>
70
71#include "SUPDrvIOC.h"
72#include "SUPLibInternal.h"
73
74
75/*********************************************************************************************************************************
76* Defined Constants And Macros *
77*********************************************************************************************************************************/
78/** R0 VMM module name. */
79#define VMMR0_NAME "VMMR0"
80
81
82/*********************************************************************************************************************************
83* Structures and Typedefs *
84*********************************************************************************************************************************/
85typedef DECLCALLBACKTYPE(int, FNCALLVMMR0,(PVMR0 pVMR0, unsigned uOperation, void *pvArg));
86typedef FNCALLVMMR0 *PFNCALLVMMR0;
87
88
89/*********************************************************************************************************************************
90* Global Variables *
91*********************************************************************************************************************************/
92/** Init counter. */
93static uint32_t g_cInits = 0;
94/** Whether we've been preinitied. */
95static bool g_fPreInited = false;
96/** The SUPLib instance data.
97 * Well, at least parts of it, specifically the parts that are being handed over
98 * via the pre-init mechanism from the hardened executable stub. */
99DECL_HIDDEN_DATA(SUPLIBDATA) g_supLibData =
100{
101 /*.hDevice = */ SUP_HDEVICE_NIL,
102 /*.fUnrestricted = */ true
103#if defined(RT_OS_DARWIN)
104 ,/* .uConnection = */ 0
105#elif defined(RT_OS_LINUX)
106 ,/* .fSysMadviseWorks = */ false
107#endif
108};
109
110/** Pointer to the Global Information Page.
111 *
112 * This pointer is valid as long as SUPLib has a open session. Anyone using
113 * the page must treat this pointer as highly volatile and not trust it beyond
114 * one transaction.
115 *
116 * @todo This will probably deserve it's own session or some other good solution...
117 */
118DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
119/** Address of the ring-0 mapping of the GIP. */
120PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0;
121/** The physical address of the GIP. */
122static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
123
124/** The negotiated cookie. */
125DECL_HIDDEN_DATA(uint32_t) g_u32Cookie = 0;
126/** The negotiated session cookie. */
127DECL_HIDDEN_DATA(uint32_t) g_u32SessionCookie;
128/** The session version. */
129DECL_HIDDEN_DATA(uint32_t) g_uSupSessionVersion = 0;
130/** Session handle. */
131DECL_HIDDEN_DATA(PSUPDRVSESSION) g_pSession;
132/** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
133DECL_HIDDEN_DATA(PSUPQUERYFUNCS) g_pSupFunctions;
134
135/** PAGE_ALLOC_EX sans kernel mapping support indicator. */
136static bool g_fSupportsPageAllocNoKernel = true;
137/** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
138DECL_HIDDEN_DATA(uint32_t) g_uSupFakeMode = UINT32_MAX;
139
140
141/*********************************************************************************************************************************
142* Internal Functions *
143*********************************************************************************************************************************/
144static int supInitFake(PSUPDRVSESSION *ppSession);
145
146
147/** Touch a range of pages. */
148DECLINLINE(void) supR3TouchPages(void *pv, size_t cPages)
149{
150 uint32_t volatile *pu32 = (uint32_t volatile *)pv;
151 while (cPages-- > 0)
152 {
153 ASMAtomicCmpXchgU32(pu32, 0, 0);
154 pu32 += PAGE_SIZE / sizeof(uint32_t);
155 }
156}
157
158
159SUPR3DECL(int) SUPR3Install(void)
160{
161 return suplibOsInstall();
162}
163
164
165SUPR3DECL(int) SUPR3Uninstall(void)
166{
167 return suplibOsUninstall();
168}
169
170
171DECL_NOTHROW(DECLEXPORT(int)) supR3PreInit(PSUPPREINITDATA pPreInitData, uint32_t fFlags)
172{
173 /*
174 * The caller is kind of trustworthy, just perform some basic checks.
175 *
176 * Note! Do not do any fancy stuff here because IPRT has NOT been
177 * initialized at this point.
178 */
179 if (!RT_VALID_PTR(pPreInitData))
180 return VERR_INVALID_POINTER;
181 if (g_fPreInited || g_cInits > 0)
182 return VERR_WRONG_ORDER;
183
184 if ( pPreInitData->u32Magic != SUPPREINITDATA_MAGIC
185 || pPreInitData->u32EndMagic != SUPPREINITDATA_MAGIC)
186 return VERR_INVALID_MAGIC;
187 if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
188 && pPreInitData->Data.hDevice == SUP_HDEVICE_NIL)
189 return VERR_INVALID_HANDLE;
190 if ( (fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
191 && pPreInitData->Data.hDevice != SUP_HDEVICE_NIL)
192 return VERR_INVALID_PARAMETER;
193
194 /*
195 * Hand out the data.
196 */
197 int rc = supR3HardenedRecvPreInitData(pPreInitData);
198 if (RT_FAILURE(rc))
199 return rc;
200
201 /** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */
202 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
203 {
204 g_supLibData = pPreInitData->Data;
205 g_fPreInited = true;
206 }
207
208 return VINF_SUCCESS;
209}
210
211
212SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession)
213{
214 /*
215 * Perform some sanity checks.
216 * (Got some trouble with compile time member alignment assertions.)
217 */
218 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz) & 0x7));
219 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs) & 0x1f));
220 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[1]) & 0x1f));
221 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64NanoTS) & 0x7));
222 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64TSC) & 0x7));
223 Assert(!(RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64CpuHz) & 0x7));
224
225 /*
226 * Check if already initialized.
227 */
228 if (ppSession)
229 *ppSession = g_pSession;
230 if (g_cInits++ > 0)
231 {
232 if (fUnrestricted && !g_supLibData.fUnrestricted)
233 {
234 g_cInits--;
235 if (ppSession)
236 *ppSession = NIL_RTR0PTR;
237 return VERR_VM_DRIVER_NOT_ACCESSIBLE; /** @todo different status code? */
238 }
239 return VINF_SUCCESS;
240 }
241
242 /*
243 * Check for fake mode.
244 *
245 * Fake mode is used when we're doing smoke testing and debugging.
246 * It's also useful on platforms where we haven't root access or which
247 * we haven't ported the support driver to.
248 */
249 if (g_uSupFakeMode == ~0U)
250 {
251 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
252 if (psz && !strcmp(psz, "fake"))
253 ASMAtomicCmpXchgU32(&g_uSupFakeMode, 1, ~0U);
254 else
255 ASMAtomicCmpXchgU32(&g_uSupFakeMode, 0, ~0U);
256 }
257 if (RT_UNLIKELY(g_uSupFakeMode))
258 return supInitFake(ppSession);
259
260 /*
261 * Open the support driver.
262 */
263 SUPINITOP enmWhat = kSupInitOp_Driver;
264 int rc = suplibOsInit(&g_supLibData, g_fPreInited, fUnrestricted, &enmWhat, NULL);
265 if (RT_SUCCESS(rc))
266 {
267 /*
268 * Negotiate the cookie.
269 */
270 SUPCOOKIE CookieReq;
271 memset(&CookieReq, 0xff, sizeof(CookieReq));
272 CookieReq.Hdr.u32Cookie = SUPCOOKIE_INITIAL_COOKIE;
273 CookieReq.Hdr.u32SessionCookie = RTRandU32();
274 CookieReq.Hdr.cbIn = SUP_IOCTL_COOKIE_SIZE_IN;
275 CookieReq.Hdr.cbOut = SUP_IOCTL_COOKIE_SIZE_OUT;
276 CookieReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
277 CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
278 strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
279 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
280 const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00300000
281 ? 0x00310001
282 : SUPDRV_IOC_VERSION & 0xffff0000;
283 CookieReq.u.In.u32MinVersion = uMinVersion;
284 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
285 if ( RT_SUCCESS(rc)
286 && RT_SUCCESS(CookieReq.Hdr.rc))
287 {
288 g_uSupSessionVersion = CookieReq.u.Out.u32SessionVersion;
289 if ( (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)
290 && CookieReq.u.Out.u32SessionVersion >= uMinVersion)
291 {
292 /*
293 * Query the functions.
294 */
295 PSUPQUERYFUNCS pFuncsReq = NULL;
296 if (g_supLibData.fUnrestricted)
297 {
298 pFuncsReq = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
299 if (pFuncsReq)
300 {
301 pFuncsReq->Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
302 pFuncsReq->Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
303 pFuncsReq->Hdr.cbIn = SUP_IOCTL_QUERY_FUNCS_SIZE_IN;
304 pFuncsReq->Hdr.cbOut = SUP_IOCTL_QUERY_FUNCS_SIZE_OUT(CookieReq.u.Out.cFunctions);
305 pFuncsReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
306 pFuncsReq->Hdr.rc = VERR_INTERNAL_ERROR;
307 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_QUERY_FUNCS(CookieReq.u.Out.cFunctions), pFuncsReq,
308 SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
309 if (RT_SUCCESS(rc))
310 rc = pFuncsReq->Hdr.rc;
311 if (RT_SUCCESS(rc))
312 {
313 /*
314 * Map the GIP into userspace.
315 */
316 Assert(!g_pSUPGlobalInfoPage);
317 SUPGIPMAP GipMapReq;
318 GipMapReq.Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
319 GipMapReq.Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
320 GipMapReq.Hdr.cbIn = SUP_IOCTL_GIP_MAP_SIZE_IN;
321 GipMapReq.Hdr.cbOut = SUP_IOCTL_GIP_MAP_SIZE_OUT;
322 GipMapReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
323 GipMapReq.Hdr.rc = VERR_INTERNAL_ERROR;
324 GipMapReq.u.Out.HCPhysGip = NIL_RTHCPHYS;
325 GipMapReq.u.Out.pGipR0 = NIL_RTR0PTR;
326 GipMapReq.u.Out.pGipR3 = NULL;
327 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_MAP, &GipMapReq, SUP_IOCTL_GIP_MAP_SIZE);
328 if (RT_SUCCESS(rc))
329 rc = GipMapReq.Hdr.rc;
330 if (RT_SUCCESS(rc))
331 {
332 /*
333 * Set the GIP globals.
334 */
335 AssertRelease(GipMapReq.u.Out.pGipR3->u32Magic == SUPGLOBALINFOPAGE_MAGIC);
336 AssertRelease(GipMapReq.u.Out.pGipR3->u32Version >= SUPGLOBALINFOPAGE_VERSION);
337
338 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipMapReq.u.Out.HCPhysGip);
339 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, GipMapReq.u.Out.pGipR3, NULL);
340 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);
341 }
342 }
343 }
344 else
345 rc = VERR_NO_MEMORY;
346 }
347
348 if (RT_SUCCESS(rc))
349 {
350 /*
351 * Set the globals and return success.
352 */
353 g_u32Cookie = CookieReq.u.Out.u32Cookie;
354 g_u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
355 g_pSession = CookieReq.u.Out.pSession;
356 g_pSupFunctions = pFuncsReq;
357 if (ppSession)
358 *ppSession = CookieReq.u.Out.pSession;
359 return VINF_SUCCESS;
360 }
361
362 /* bailout */
363 RTMemFree(pFuncsReq);
364 }
365 else
366 {
367 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
368 CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, uMinVersion));
369 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
370 }
371 }
372 else
373 {
374 if (RT_SUCCESS(rc))
375 {
376 rc = CookieReq.Hdr.rc;
377 LogRel(("Support driver version mismatch: DriverVersion=%#x ClientVersion=%#x rc=%Rrc\n",
378 CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, rc));
379 if (rc != VERR_VM_DRIVER_VERSION_MISMATCH)
380 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
381 }
382 else
383 {
384 /* for pre 0x00060000 drivers */
385 LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));
386 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
387 }
388 }
389
390 suplibOsTerm(&g_supLibData);
391 }
392 g_cInits--;
393
394 return rc;
395}
396
397
398SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession)
399{
400 return SUPR3InitEx(true, ppSession);
401}
402
403/**
404 * Fake mode init.
405 */
406static int supInitFake(PSUPDRVSESSION *ppSession)
407{
408 Log(("SUP: Fake mode!\n"));
409 static const SUPFUNC s_aFakeFunctions[] =
410 {
411 /* name function */
412 { "SUPR0AbsIs64bit", 0 },
413 { "SUPR0Abs64bitKernelCS", 0 },
414 { "SUPR0Abs64bitKernelSS", 0 },
415 { "SUPR0Abs64bitKernelDS", 0 },
416 { "SUPR0AbsKernelCS", 8 },
417 { "SUPR0AbsKernelSS", 16 },
418 { "SUPR0AbsKernelDS", 16 },
419 { "SUPR0AbsKernelES", 16 },
420 { "SUPR0AbsKernelFS", 24 },
421 { "SUPR0AbsKernelGS", 32 },
422 { "SUPR0ComponentRegisterFactory", 0xefeefffd },
423 { "SUPR0ComponentDeregisterFactory", 0xefeefffe },
424 { "SUPR0ComponentQueryFactory", 0xefeeffff },
425 { "SUPR0ObjRegister", 0xefef0000 },
426 { "SUPR0ObjAddRef", 0xefef0001 },
427 { "SUPR0ObjAddRefEx", 0xefef0001 },
428 { "SUPR0ObjRelease", 0xefef0002 },
429 { "SUPR0ObjVerifyAccess", 0xefef0003 },
430 { "SUPR0LockMem", 0xefef0004 },
431 { "SUPR0UnlockMem", 0xefef0005 },
432 { "SUPR0ContAlloc", 0xefef0006 },
433 { "SUPR0ContFree", 0xefef0007 },
434 { "SUPR0MemAlloc", 0xefef0008 },
435 { "SUPR0MemGetPhys", 0xefef0009 },
436 { "SUPR0MemFree", 0xefef000a },
437 { "SUPR0Printf", 0xefef000b },
438 { "SUPR0GetPagingMode", 0xefef000c },
439 { "SUPR0EnableVTx", 0xefef000e },
440 { "RTMemAlloc", 0xefef000f },
441 { "RTMemAllocZ", 0xefef0010 },
442 { "RTMemFree", 0xefef0011 },
443 { "RTR0MemObjAddress", 0xefef0012 },
444 { "RTR0MemObjAddressR3", 0xefef0013 },
445 { "RTR0MemObjAllocPage", 0xefef0014 },
446 { "RTR0MemObjAllocPhysNC", 0xefef0015 },
447 { "RTR0MemObjAllocLow", 0xefef0016 },
448 { "RTR0MemObjEnterPhys", 0xefef0017 },
449 { "RTR0MemObjFree", 0xefef0018 },
450 { "RTR0MemObjGetPagePhysAddr", 0xefef0019 },
451 { "RTR0MemObjMapUser", 0xefef001a },
452 { "RTR0MemObjMapKernel", 0xefef001b },
453 { "RTR0MemObjMapKernelEx", 0xefef001c },
454 { "RTMpGetArraySize", 0xefef001c },
455 { "RTProcSelf", 0xefef001d },
456 { "RTR0ProcHandleSelf", 0xefef001e },
457 { "RTSemEventCreate", 0xefef001f },
458 { "RTSemEventSignal", 0xefef0020 },
459 { "RTSemEventWait", 0xefef0021 },
460 { "RTSemEventWaitNoResume", 0xefef0022 },
461 { "RTSemEventDestroy", 0xefef0023 },
462 { "RTSemEventMultiCreate", 0xefef0024 },
463 { "RTSemEventMultiSignal", 0xefef0025 },
464 { "RTSemEventMultiReset", 0xefef0026 },
465 { "RTSemEventMultiWait", 0xefef0027 },
466 { "RTSemEventMultiWaitNoResume", 0xefef0028 },
467 { "RTSemEventMultiDestroy", 0xefef0029 },
468 { "RTSemFastMutexCreate", 0xefef002a },
469 { "RTSemFastMutexDestroy", 0xefef002b },
470 { "RTSemFastMutexRequest", 0xefef002c },
471 { "RTSemFastMutexRelease", 0xefef002d },
472 { "RTSpinlockCreate", 0xefef002e },
473 { "RTSpinlockDestroy", 0xefef002f },
474 { "RTSpinlockAcquire", 0xefef0030 },
475 { "RTSpinlockRelease", 0xefef0031 },
476 { "RTSpinlockAcquireNoInts", 0xefef0032 },
477 { "RTTimeNanoTS", 0xefef0034 },
478 { "RTTimeMillieTS", 0xefef0035 },
479 { "RTTimeSystemNanoTS", 0xefef0036 },
480 { "RTTimeSystemMillieTS", 0xefef0037 },
481 { "RTThreadNativeSelf", 0xefef0038 },
482 { "RTThreadSleep", 0xefef0039 },
483 { "RTThreadYield", 0xefef003a },
484 { "RTTimerCreate", 0xefef003a },
485 { "RTTimerCreateEx", 0xefef003a },
486 { "RTTimerDestroy", 0xefef003a },
487 { "RTTimerStart", 0xefef003a },
488 { "RTTimerStop", 0xefef003a },
489 { "RTTimerChangeInterval", 0xefef003a },
490 { "RTTimerGetSystemGranularity", 0xefef003a },
491 { "RTTimerRequestSystemGranularity", 0xefef003a },
492 { "RTTimerReleaseSystemGranularity", 0xefef003a },
493 { "RTTimerCanDoHighResolution", 0xefef003a },
494 { "RTLogDefaultInstance", 0xefef003b },
495 { "RTLogRelGetDefaultInstance", 0xefef003c },
496 { "RTLogSetDefaultInstanceThread", 0xefef003d },
497 { "RTLogLogger", 0xefef003e },
498 { "RTLogLoggerEx", 0xefef003f },
499 { "RTLogLoggerExV", 0xefef0040 },
500 { "RTAssertMsg1", 0xefef0041 },
501 { "RTAssertMsg2", 0xefef0042 },
502 { "RTAssertMsg2V", 0xefef0043 },
503 { "SUPR0QueryVTCaps", 0xefef0044 },
504 };
505
506 /* fake r0 functions. */
507 g_pSupFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
508 if (g_pSupFunctions)
509 {
510 g_pSupFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
511 memcpy(&g_pSupFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
512 g_pSession = (PSUPDRVSESSION)(void *)g_pSupFunctions;
513 if (ppSession)
514 *ppSession = g_pSession;
515
516 /* fake the GIP. */
517 g_pSUPGlobalInfoPage = (PSUPGLOBALINFOPAGE)RTMemPageAllocZ(PAGE_SIZE);
518 if (g_pSUPGlobalInfoPage)
519 {
520 g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;
521 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;
522 /* the page is supposed to be invalid, so don't set the magic. */
523 return VINF_SUCCESS;
524 }
525
526 RTMemFree(g_pSupFunctions);
527 g_pSupFunctions = NULL;
528 }
529 return VERR_NO_MEMORY;
530}
531
532
533SUPR3DECL(int) SUPR3Term(bool fForced)
534{
535 /*
536 * Verify state.
537 */
538 AssertMsg(g_cInits > 0, ("SUPR3Term() is called before SUPR3Init()!\n"));
539 if (g_cInits == 0)
540 return VERR_WRONG_ORDER;
541 if (g_cInits == 1 || fForced)
542 {
543 /*
544 * NULL the GIP pointer.
545 */
546 if (g_pSUPGlobalInfoPage)
547 {
548 ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPage);
549 ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPageR0);
550 ASMAtomicWriteU64(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);
551 /* just a little safe guard against threads using the page. */
552 RTThreadSleep(50);
553 }
554
555 /*
556 * Close the support driver.
557 */
558 int rc = suplibOsTerm(&g_supLibData);
559 if (rc)
560 return rc;
561
562 g_u32Cookie = 0;
563 g_u32SessionCookie = 0;
564 g_cInits = 0;
565 }
566 else
567 g_cInits--;
568
569 return 0;
570}
571
572
573SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
574{
575 /* fake */
576 if (RT_UNLIKELY(g_uSupFakeMode))
577#ifdef RT_ARCH_AMD64
578 return SUPPAGINGMODE_AMD64_GLOBAL_NX;
579#else
580 return SUPPAGINGMODE_32_BIT_GLOBAL;
581#endif
582
583 /*
584 * Issue IOCtl to the SUPDRV kernel module.
585 */
586 SUPGETPAGINGMODE Req;
587 Req.Hdr.u32Cookie = g_u32Cookie;
588 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
589 Req.Hdr.cbIn = SUP_IOCTL_GET_PAGING_MODE_SIZE_IN;
590 Req.Hdr.cbOut = SUP_IOCTL_GET_PAGING_MODE_SIZE_OUT;
591 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
592 Req.Hdr.rc = VERR_INTERNAL_ERROR;
593 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);
594 if ( RT_FAILURE(rc)
595 || RT_FAILURE(Req.Hdr.rc))
596 {
597 LogRel(("SUPR3GetPagingMode: %Rrc %Rrc\n", rc, Req.Hdr.rc));
598 Req.u.Out.enmMode = SUPPAGINGMODE_INVALID;
599 }
600
601 return Req.u.Out.enmMode;
602}
603
604
605/**
606 * For later.
607 */
608static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
609{
610 AssertMsgFailed(("%d\n", uOperation)); NOREF(pVMR0); NOREF(uOperation); NOREF(u64Arg); NOREF(pReqHdr);
611 return VERR_NOT_SUPPORTED;
612}
613
614
615SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
616{
617 NOREF(pVMR0);
618 static const uintptr_t s_auFunctions[3] =
619 {
620 SUP_IOCTL_FAST_DO_HM_RUN,
621 SUP_IOCTL_FAST_DO_NEM_RUN,
622 SUP_IOCTL_FAST_DO_NOP,
623 };
624 AssertCompile(SUP_VMMR0_DO_HM_RUN == 0);
625 AssertCompile(SUP_VMMR0_DO_NEM_RUN == 1);
626 AssertCompile(SUP_VMMR0_DO_NOP == 2);
627 AssertMsgReturn(uOperation < RT_ELEMENTS(s_auFunctions), ("%#x\n", uOperation), VERR_INTERNAL_ERROR);
628 return suplibOsIOCtlFast(&g_supLibData, s_auFunctions[uOperation], idCpu);
629}
630
631
632SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
633{
634 /*
635 * The following operations don't belong here.
636 */
637 AssertMsgReturn( uOperation != SUP_VMMR0_DO_HM_RUN
638 && uOperation != SUP_VMMR0_DO_NEM_RUN
639 && uOperation != SUP_VMMR0_DO_NOP,
640 ("%#x\n", uOperation),
641 VERR_INTERNAL_ERROR);
642
643 /* fake */
644 if (RT_UNLIKELY(g_uSupFakeMode))
645 return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
646
647 int rc;
648 if (!pReqHdr)
649 {
650 /* no data. */
651 SUPCALLVMMR0 Req;
652 Req.Hdr.u32Cookie = g_u32Cookie;
653 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
654 Req.Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(0);
655 Req.Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(0);
656 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
657 Req.Hdr.rc = VERR_INTERNAL_ERROR;
658 Req.u.In.pVMR0 = pVMR0;
659 Req.u.In.idCpu = idCpu;
660 Req.u.In.uOperation = uOperation;
661 Req.u.In.u64Arg = u64Arg;
662 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(0), &Req, SUP_IOCTL_CALL_VMMR0_SIZE(0));
663 if (RT_SUCCESS(rc))
664 rc = Req.Hdr.rc;
665 }
666 else if (SUP_IOCTL_CALL_VMMR0_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
667 {
668 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
669 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
670 const size_t cbReq = pReqHdr->cbReq;
671
672 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)alloca(SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
673 pReq->Hdr.u32Cookie = g_u32Cookie;
674 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
675 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(cbReq);
676 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(cbReq);
677 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
678 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
679 pReq->u.In.pVMR0 = pVMR0;
680 pReq->u.In.idCpu = idCpu;
681 pReq->u.In.uOperation = uOperation;
682 pReq->u.In.u64Arg = u64Arg;
683 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
684 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
685 if (RT_SUCCESS(rc))
686 rc = pReq->Hdr.rc;
687 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
688 }
689 else if (pReqHdr->cbReq <= _512K)
690 {
691 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
692 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
693 const size_t cbReq = pReqHdr->cbReq;
694
695 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)RTMemTmpAlloc(SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));
696 pReq->Hdr.u32Cookie = g_u32Cookie;
697 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
698 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_IN(cbReq);
699 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_OUT(cbReq);
700 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
701 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
702 pReq->u.In.pVMR0 = pVMR0;
703 pReq->u.In.idCpu = idCpu;
704 pReq->u.In.uOperation = uOperation;
705 pReq->u.In.u64Arg = u64Arg;
706 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
707 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0_BIG, pReq, SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));
708 if (RT_SUCCESS(rc))
709 rc = pReq->Hdr.rc;
710 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
711 RTMemTmpFree(pReq);
712 }
713 else
714 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_OUT_OF_RANGE);
715 return rc;
716}
717
718
719SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg)
720{
721 /*
722 * The following operations don't belong here.
723 */
724 AssertMsgReturn( uOperation != SUP_VMMR0_DO_HM_RUN
725 && uOperation != SUP_VMMR0_DO_NEM_RUN
726 && uOperation != SUP_VMMR0_DO_NOP,
727 ("%#x\n", uOperation),
728 VERR_INTERNAL_ERROR);
729 return SUPR3CallVMMR0Ex(pVMR0, idCpu, uOperation, (uintptr_t)pvArg, NULL);
730}
731
732
733SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)
734{
735 if (RT_UNLIKELY(g_uSupFakeMode))
736 return VINF_SUCCESS;
737
738 SUPSETVMFORFAST Req;
739 Req.Hdr.u32Cookie = g_u32Cookie;
740 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
741 Req.Hdr.cbIn = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_IN;
742 Req.Hdr.cbOut = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_OUT;
743 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
744 Req.Hdr.rc = VERR_INTERNAL_ERROR;
745 Req.u.In.pVMR0 = pVMR0;
746 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);
747 if (RT_SUCCESS(rc))
748 rc = Req.Hdr.rc;
749 return rc;
750}
751
752
753SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
754{
755 AssertReturn(cchService < RT_SIZEOFMEMB(SUPCALLSERVICE, u.In.szName), VERR_INVALID_PARAMETER);
756 Assert(strlen(pszService) == cchService);
757
758 /* fake */
759 if (RT_UNLIKELY(g_uSupFakeMode))
760 return VERR_NOT_SUPPORTED;
761
762 int rc;
763 if (!pReqHdr)
764 {
765 /* no data. */
766 SUPCALLSERVICE Req;
767 Req.Hdr.u32Cookie = g_u32Cookie;
768 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
769 Req.Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(0);
770 Req.Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(0);
771 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
772 Req.Hdr.rc = VERR_INTERNAL_ERROR;
773 memcpy(Req.u.In.szName, pszService, cchService);
774 Req.u.In.szName[cchService] = '\0';
775 Req.u.In.uOperation = uOperation;
776 Req.u.In.u64Arg = u64Arg;
777 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(0), &Req, SUP_IOCTL_CALL_SERVICE_SIZE(0));
778 if (RT_SUCCESS(rc))
779 rc = Req.Hdr.rc;
780 }
781 else if (SUP_IOCTL_CALL_SERVICE_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
782 {
783 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
784 AssertReturn(pReqHdr->u32Magic == SUPR0SERVICEREQHDR_MAGIC, VERR_INVALID_MAGIC);
785 const size_t cbReq = pReqHdr->cbReq;
786
787 PSUPCALLSERVICE pReq = (PSUPCALLSERVICE)alloca(SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
788 pReq->Hdr.u32Cookie = g_u32Cookie;
789 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
790 pReq->Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(cbReq);
791 pReq->Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(cbReq);
792 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
793 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
794 memcpy(pReq->u.In.szName, pszService, cchService);
795 pReq->u.In.szName[cchService] = '\0';
796 pReq->u.In.uOperation = uOperation;
797 pReq->u.In.u64Arg = u64Arg;
798 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
799 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
800 if (RT_SUCCESS(rc))
801 rc = pReq->Hdr.rc;
802 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
803 }
804 else /** @todo may have to remove the size limits one this request... */
805 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
806 return rc;
807}
808
809
810/**
811 * Worker for the SUPR3Logger* APIs.
812 *
813 * @returns VBox status code.
814 * @param enmWhich Which logger.
815 * @param fWhat What to do with the logger.
816 * @param pszFlags The flags settings.
817 * @param pszGroups The groups settings.
818 * @param pszDest The destination specificier.
819 */
820static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)
821{
822 uint32_t const cchFlags = pszFlags ? (uint32_t)strlen(pszFlags) : 0;
823 uint32_t const cchGroups = pszGroups ? (uint32_t)strlen(pszGroups) : 0;
824 uint32_t const cchDest = pszDest ? (uint32_t)strlen(pszDest) : 0;
825 uint32_t const cbStrTab = cchFlags + !!cchFlags
826 + cchGroups + !!cchGroups
827 + cchDest + !!cchDest
828 + (!cchFlags && !cchGroups && !cchDest);
829
830 PSUPLOGGERSETTINGS pReq = (PSUPLOGGERSETTINGS)alloca(SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
831 pReq->Hdr.u32Cookie = g_u32Cookie;
832 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
833 pReq->Hdr.cbIn = SUP_IOCTL_LOGGER_SETTINGS_SIZE_IN(cbStrTab);
834 pReq->Hdr.cbOut = SUP_IOCTL_LOGGER_SETTINGS_SIZE_OUT;
835 pReq->Hdr.fFlags= SUPREQHDR_FLAGS_DEFAULT;
836 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
837 switch (enmWhich)
838 {
839 case SUPLOGGER_DEBUG: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_DEBUG; break;
840 case SUPLOGGER_RELEASE: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_RELEASE; break;
841 default:
842 return VERR_INVALID_PARAMETER;
843 }
844 pReq->u.In.fWhat = fWhat;
845
846 uint32_t off = 0;
847 if (cchFlags)
848 {
849 pReq->u.In.offFlags = off;
850 memcpy(&pReq->u.In.szStrings[off], pszFlags, cchFlags + 1);
851 off += cchFlags + 1;
852 }
853 else
854 pReq->u.In.offFlags = cbStrTab - 1;
855
856 if (cchGroups)
857 {
858 pReq->u.In.offGroups = off;
859 memcpy(&pReq->u.In.szStrings[off], pszGroups, cchGroups + 1);
860 off += cchGroups + 1;
861 }
862 else
863 pReq->u.In.offGroups = cbStrTab - 1;
864
865 if (cchDest)
866 {
867 pReq->u.In.offDestination = off;
868 memcpy(&pReq->u.In.szStrings[off], pszDest, cchDest + 1);
869 off += cchDest + 1;
870 }
871 else
872 pReq->u.In.offDestination = cbStrTab - 1;
873
874 if (!off)
875 {
876 pReq->u.In.szStrings[0] = '\0';
877 off++;
878 }
879 Assert(off == cbStrTab);
880 Assert(pReq->u.In.szStrings[cbStrTab - 1] == '\0');
881
882
883 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
884 if (RT_SUCCESS(rc))
885 rc = pReq->Hdr.rc;
886 return rc;
887}
888
889
890SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
891{
892 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);
893}
894
895
896SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
897{
898 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_CREATE, pszFlags, pszGroups, pszDest);
899}
900
901
902SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich)
903{
904 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_DESTROY, NULL, NULL, NULL);
905}
906
907
908SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages)
909{
910 /*
911 * Validate.
912 */
913 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
914 *ppvPages = NULL;
915 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
916
917 /*
918 * Call OS specific worker.
919 */
920 return suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
921}
922
923
924SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages)
925{
926 /*
927 * Validate.
928 */
929 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
930 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
931
932 /*
933 * Call OS specific worker.
934 */
935 return suplibOsPageFree(&g_supLibData, pvPages, cPages);
936}
937
938
939/**
940 * Locks down the physical memory backing a virtual memory
941 * range in the current process.
942 *
943 * @returns VBox status code.
944 * @param pvStart Start of virtual memory range.
945 * Must be page aligned.
946 * @param cPages Number of pages.
947 * @param paPages Where to store the physical page addresses returned.
948 * On entry this will point to an array of with cbMemory >> PAGE_SHIFT entries.
949 */
950SUPR3DECL(int) supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages)
951{
952 /*
953 * Validate.
954 */
955 AssertPtr(pvStart);
956 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
957 AssertPtr(paPages);
958
959 /* fake */
960 if (RT_UNLIKELY(g_uSupFakeMode))
961 {
962 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
963 size_t iPage = cPages;
964 while (iPage-- > 0)
965 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
966 return VINF_SUCCESS;
967 }
968
969 /*
970 * Issue IOCtl to the SUPDRV kernel module.
971 */
972 int rc;
973 PSUPPAGELOCK pReq = (PSUPPAGELOCK)RTMemTmpAllocZ(SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
974 if (RT_LIKELY(pReq))
975 {
976 pReq->Hdr.u32Cookie = g_u32Cookie;
977 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
978 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_LOCK_SIZE_IN;
979 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_LOCK_SIZE_OUT(cPages);
980 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
981 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
982 pReq->u.In.pvR3 = pvStart;
983 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
984 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_LOCK, pReq, SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
985 if (RT_SUCCESS(rc))
986 rc = pReq->Hdr.rc;
987 if (RT_SUCCESS(rc))
988 {
989 for (uint32_t iPage = 0; iPage < cPages; iPage++)
990 {
991 paPages[iPage].uReserved = 0;
992 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
993 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
994 }
995 }
996 RTMemTmpFree(pReq);
997 }
998 else
999 rc = VERR_NO_TMP_MEMORY;
1000
1001 return rc;
1002}
1003
1004
1005/**
1006 * Releases locked down pages.
1007 *
1008 * @returns VBox status code.
1009 * @param pvStart Start of virtual memory range previously locked
1010 * down by SUPPageLock().
1011 */
1012SUPR3DECL(int) supR3PageUnlock(void *pvStart)
1013{
1014 /*
1015 * Validate.
1016 */
1017 AssertPtr(pvStart);
1018 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
1019
1020 /* fake */
1021 if (RT_UNLIKELY(g_uSupFakeMode))
1022 return VINF_SUCCESS;
1023
1024 /*
1025 * Issue IOCtl to the SUPDRV kernel module.
1026 */
1027 SUPPAGEUNLOCK Req;
1028 Req.Hdr.u32Cookie = g_u32Cookie;
1029 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1030 Req.Hdr.cbIn = SUP_IOCTL_PAGE_UNLOCK_SIZE_IN;
1031 Req.Hdr.cbOut = SUP_IOCTL_PAGE_UNLOCK_SIZE_OUT;
1032 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1033 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1034 Req.u.In.pvR3 = pvStart;
1035 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_UNLOCK, &Req, SUP_IOCTL_PAGE_UNLOCK_SIZE);
1036 if (RT_SUCCESS(rc))
1037 rc = Req.Hdr.rc;
1038 return rc;
1039}
1040
1041
1042SUPR3DECL(int) SUPR3LockDownLoader(PRTERRINFO pErrInfo)
1043{
1044 /* fake */
1045 if (RT_UNLIKELY(g_uSupFakeMode))
1046 return VINF_SUCCESS;
1047
1048 /*
1049 * Lock down the module loader interface.
1050 */
1051 SUPREQHDR ReqHdr;
1052 ReqHdr.u32Cookie = g_u32Cookie;
1053 ReqHdr.u32SessionCookie = g_u32SessionCookie;
1054 ReqHdr.cbIn = SUP_IOCTL_LDR_LOCK_DOWN_SIZE_IN;
1055 ReqHdr.cbOut = SUP_IOCTL_LDR_LOCK_DOWN_SIZE_OUT;
1056 ReqHdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1057 ReqHdr.rc = VERR_INTERNAL_ERROR;
1058 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOCK_DOWN, &ReqHdr, SUP_IOCTL_LDR_LOCK_DOWN_SIZE);
1059 if (RT_FAILURE(rc))
1060 return RTErrInfoSetF(pErrInfo, rc,
1061 "SUPR3LockDownLoader: SUP_IOCTL_LDR_LOCK_DOWN ioctl returned %Rrc", rc);
1062
1063 return ReqHdr.rc;
1064}
1065
1066
1067/**
1068 * Fallback for SUPR3PageAllocEx on systems where RTR0MemObjPhysAllocNC isn't
1069 * supported.
1070 */
1071static int supPagePageAllocNoKernelFallback(size_t cPages, void **ppvPages, PSUPPAGE paPages)
1072{
1073 int rc = suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
1074 if (RT_SUCCESS(rc))
1075 {
1076 if (!paPages)
1077 paPages = (PSUPPAGE)alloca(sizeof(paPages[0]) * cPages);
1078 rc = supR3PageLock(*ppvPages, cPages, paPages);
1079 if (RT_FAILURE(rc))
1080 suplibOsPageFree(&g_supLibData, *ppvPages, cPages);
1081 }
1082 return rc;
1083}
1084
1085
1086SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)
1087{
1088 /*
1089 * Validate.
1090 */
1091 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
1092 *ppvPages = NULL;
1093 AssertPtrNullReturn(pR0Ptr, VERR_INVALID_POINTER);
1094 if (pR0Ptr)
1095 *pR0Ptr = NIL_RTR0PTR;
1096 AssertPtrNullReturn(paPages, VERR_INVALID_POINTER);
1097 AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1098 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1099
1100 /* fake */
1101 if (RT_UNLIKELY(g_uSupFakeMode))
1102 {
1103 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1104 if (!pv)
1105 return VERR_NO_MEMORY;
1106 *ppvPages = pv;
1107 if (pR0Ptr)
1108 *pR0Ptr = (RTR0PTR)pv;
1109 if (paPages)
1110 for (size_t iPage = 0; iPage < cPages; iPage++)
1111 {
1112 paPages[iPage].uReserved = 0;
1113 paPages[iPage].Phys = (iPage + 4321) << PAGE_SHIFT;
1114 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1115 }
1116 return VINF_SUCCESS;
1117 }
1118
1119 /* Check that we've got a kernel connection so rtMemSaferSupR3AllocPages
1120 can do fallback without first having to hit assertions. */
1121 if (g_supLibData.hDevice != SUP_HDEVICE_NIL)
1122 { /* likely */ }
1123 else
1124 return VERR_WRONG_ORDER;
1125
1126 /*
1127 * Use fallback for non-R0 mapping?
1128 */
1129 if ( !pR0Ptr
1130 && !g_fSupportsPageAllocNoKernel)
1131 return supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1132
1133 /*
1134 * Issue IOCtl to the SUPDRV kernel module.
1135 */
1136 int rc;
1137 PSUPPAGEALLOCEX pReq = (PSUPPAGEALLOCEX)RTMemTmpAllocZ(SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1138 if (pReq)
1139 {
1140 pReq->Hdr.u32Cookie = g_u32Cookie;
1141 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1142 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_IN;
1143 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_OUT(cPages);
1144 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1145 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1146 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1147 pReq->u.In.fKernelMapping = pR0Ptr != NULL;
1148 pReq->u.In.fUserMapping = true;
1149 pReq->u.In.fReserved0 = false;
1150 pReq->u.In.fReserved1 = false;
1151 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1152 if (RT_SUCCESS(rc))
1153 {
1154 rc = pReq->Hdr.rc;
1155 if (RT_SUCCESS(rc))
1156 {
1157 *ppvPages = pReq->u.Out.pvR3;
1158 if (pR0Ptr)
1159 *pR0Ptr = pReq->u.Out.pvR0;
1160 if (paPages)
1161 for (size_t iPage = 0; iPage < cPages; iPage++)
1162 {
1163 paPages[iPage].uReserved = 0;
1164 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1165 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1166 }
1167#ifdef RT_OS_DARWIN /* HACK ALERT! */
1168 supR3TouchPages(pReq->u.Out.pvR3, cPages);
1169#endif
1170 }
1171 else if ( rc == VERR_NOT_SUPPORTED
1172 && !pR0Ptr)
1173 {
1174 g_fSupportsPageAllocNoKernel = false;
1175 rc = supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1176 }
1177 }
1178
1179 RTMemTmpFree(pReq);
1180 }
1181 else
1182 rc = VERR_NO_TMP_MEMORY;
1183 return rc;
1184
1185}
1186
1187
1188SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)
1189{
1190 /*
1191 * Validate.
1192 */
1193 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
1194 AssertPtrReturn(pR0Ptr, VERR_INVALID_POINTER);
1195 Assert(!(off & PAGE_OFFSET_MASK));
1196 Assert(!(cb & PAGE_OFFSET_MASK) && cb);
1197 Assert(!fFlags);
1198 *pR0Ptr = NIL_RTR0PTR;
1199
1200 /* fake */
1201 if (RT_UNLIKELY(g_uSupFakeMode))
1202 return VERR_NOT_SUPPORTED;
1203
1204 /*
1205 * Issue IOCtl to the SUPDRV kernel module.
1206 */
1207 SUPPAGEMAPKERNEL Req;
1208 Req.Hdr.u32Cookie = g_u32Cookie;
1209 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1210 Req.Hdr.cbIn = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_IN;
1211 Req.Hdr.cbOut = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_OUT;
1212 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1213 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1214 Req.u.In.pvR3 = pvR3;
1215 Req.u.In.offSub = off;
1216 Req.u.In.cbSub = cb;
1217 Req.u.In.fFlags = fFlags;
1218 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);
1219 if (RT_SUCCESS(rc))
1220 rc = Req.Hdr.rc;
1221 if (RT_SUCCESS(rc))
1222 *pR0Ptr = Req.u.Out.pvR0;
1223 return rc;
1224}
1225
1226
1227SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt)
1228{
1229 /*
1230 * Validate.
1231 */
1232 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
1233 Assert(!(off & PAGE_OFFSET_MASK));
1234 Assert(!(cb & PAGE_OFFSET_MASK) && cb);
1235 AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
1236
1237 /* fake */
1238 if (RT_UNLIKELY(g_uSupFakeMode))
1239 return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
1240
1241 /*
1242 * Some OSes can do this from ring-3, so try that before we
1243 * issue the IOCtl to the SUPDRV kernel module.
1244 * (Yea, this isn't very nice, but just try get the job done for now.)
1245 */
1246#if !defined(RT_OS_SOLARIS)
1247 RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
1248#endif
1249
1250 SUPPAGEPROTECT Req;
1251 Req.Hdr.u32Cookie = g_u32Cookie;
1252 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1253 Req.Hdr.cbIn = SUP_IOCTL_PAGE_PROTECT_SIZE_IN;
1254 Req.Hdr.cbOut = SUP_IOCTL_PAGE_PROTECT_SIZE_OUT;
1255 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1256 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1257 Req.u.In.pvR3 = pvR3;
1258 Req.u.In.pvR0 = R0Ptr;
1259 Req.u.In.offSub = off;
1260 Req.u.In.cbSub = cb;
1261 Req.u.In.fProt = fProt;
1262 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_PROTECT, &Req, SUP_IOCTL_PAGE_PROTECT_SIZE);
1263 if (RT_SUCCESS(rc))
1264 rc = Req.Hdr.rc;
1265 return rc;
1266}
1267
1268
1269SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
1270{
1271 /*
1272 * Validate.
1273 */
1274 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
1275 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1276
1277 /* fake */
1278 if (RT_UNLIKELY(g_uSupFakeMode))
1279 {
1280 RTMemPageFree(pvPages, cPages * PAGE_SIZE);
1281 return VINF_SUCCESS;
1282 }
1283
1284 /*
1285 * Try normal free first, then if it fails check if we're using the fallback
1286 * for the allocations without kernel mappings and attempt unlocking it.
1287 */
1288 NOREF(cPages);
1289 SUPPAGEFREE Req;
1290 Req.Hdr.u32Cookie = g_u32Cookie;
1291 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1292 Req.Hdr.cbIn = SUP_IOCTL_PAGE_FREE_SIZE_IN;
1293 Req.Hdr.cbOut = SUP_IOCTL_PAGE_FREE_SIZE_OUT;
1294 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1295 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1296 Req.u.In.pvR3 = pvPages;
1297 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_FREE, &Req, SUP_IOCTL_PAGE_FREE_SIZE);
1298 if (RT_SUCCESS(rc))
1299 {
1300 rc = Req.Hdr.rc;
1301 if ( rc == VERR_INVALID_PARAMETER
1302 && !g_fSupportsPageAllocNoKernel)
1303 {
1304 int rc2 = supR3PageUnlock(pvPages);
1305 if (RT_SUCCESS(rc2))
1306 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);
1307 }
1308 }
1309 return rc;
1310}
1311
1312
1313SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)
1314{
1315 /*
1316 * Validate.
1317 */
1318 AssertPtrReturn(pHCPhys, NULL);
1319 *pHCPhys = NIL_RTHCPHYS;
1320 AssertPtrNullReturn(pR0Ptr, NULL);
1321 if (pR0Ptr)
1322 *pR0Ptr = NIL_RTR0PTR;
1323 AssertPtrNullReturn(pHCPhys, NULL);
1324 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), NULL);
1325
1326 /* fake */
1327 if (RT_UNLIKELY(g_uSupFakeMode))
1328 {
1329 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1330 if (pR0Ptr)
1331 *pR0Ptr = (RTR0PTR)pv;
1332 if (pHCPhys)
1333 *pHCPhys = (uintptr_t)pv + (PAGE_SHIFT * 1024);
1334 return pv;
1335 }
1336
1337 /*
1338 * Issue IOCtl to the SUPDRV kernel module.
1339 */
1340 SUPCONTALLOC Req;
1341 Req.Hdr.u32Cookie = g_u32Cookie;
1342 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1343 Req.Hdr.cbIn = SUP_IOCTL_CONT_ALLOC_SIZE_IN;
1344 Req.Hdr.cbOut = SUP_IOCTL_CONT_ALLOC_SIZE_OUT;
1345 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1346 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1347 Req.u.In.cPages = (uint32_t)cPages;
1348 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_ALLOC, &Req, SUP_IOCTL_CONT_ALLOC_SIZE);
1349 if ( RT_SUCCESS(rc)
1350 && RT_SUCCESS(Req.Hdr.rc))
1351 {
1352 *pHCPhys = Req.u.Out.HCPhys;
1353 if (pR0Ptr)
1354 *pR0Ptr = Req.u.Out.pvR0;
1355#ifdef RT_OS_DARWIN /* HACK ALERT! */
1356 supR3TouchPages(Req.u.Out.pvR3, cPages);
1357#endif
1358 return Req.u.Out.pvR3;
1359 }
1360
1361 return NULL;
1362}
1363
1364
1365SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages)
1366{
1367 /*
1368 * Validate.
1369 */
1370 if (!pv)
1371 return VINF_SUCCESS;
1372 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1373 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1374
1375 /* fake */
1376 if (RT_UNLIKELY(g_uSupFakeMode))
1377 {
1378 RTMemPageFree(pv, cPages * PAGE_SIZE);
1379 return VINF_SUCCESS;
1380 }
1381
1382 /*
1383 * Issue IOCtl to the SUPDRV kernel module.
1384 */
1385 SUPCONTFREE Req;
1386 Req.Hdr.u32Cookie = g_u32Cookie;
1387 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1388 Req.Hdr.cbIn = SUP_IOCTL_CONT_FREE_SIZE_IN;
1389 Req.Hdr.cbOut = SUP_IOCTL_CONT_FREE_SIZE_OUT;
1390 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1391 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1392 Req.u.In.pvR3 = pv;
1393 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_FREE, &Req, SUP_IOCTL_CONT_FREE_SIZE);
1394 if (RT_SUCCESS(rc))
1395 rc = Req.Hdr.rc;
1396 return rc;
1397}
1398
1399
1400SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages)
1401{
1402 /*
1403 * Validate.
1404 */
1405 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
1406 *ppvPages = NULL;
1407 AssertPtrReturn(paPages, VERR_INVALID_POINTER);
1408 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1409
1410 /* fake */
1411 if (RT_UNLIKELY(g_uSupFakeMode))
1412 {
1413 *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
1414 if (!*ppvPages)
1415 return VERR_NO_LOW_MEMORY;
1416
1417 /* fake physical addresses. */
1418 RTHCPHYS Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;
1419 size_t iPage = cPages;
1420 while (iPage-- > 0)
1421 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
1422 return VINF_SUCCESS;
1423 }
1424
1425 /*
1426 * Issue IOCtl to the SUPDRV kernel module.
1427 */
1428 int rc;
1429 PSUPLOWALLOC pReq = (PSUPLOWALLOC)RTMemTmpAllocZ(SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1430 if (pReq)
1431 {
1432 pReq->Hdr.u32Cookie = g_u32Cookie;
1433 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1434 pReq->Hdr.cbIn = SUP_IOCTL_LOW_ALLOC_SIZE_IN;
1435 pReq->Hdr.cbOut = SUP_IOCTL_LOW_ALLOC_SIZE_OUT(cPages);
1436 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1437 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1438 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1439 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_ALLOC, pReq, SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1440 if (RT_SUCCESS(rc))
1441 rc = pReq->Hdr.rc;
1442 if (RT_SUCCESS(rc))
1443 {
1444 *ppvPages = pReq->u.Out.pvR3;
1445 if (ppvPagesR0)
1446 *ppvPagesR0 = pReq->u.Out.pvR0;
1447 if (paPages)
1448 for (size_t iPage = 0; iPage < cPages; iPage++)
1449 {
1450 paPages[iPage].uReserved = 0;
1451 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1452 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1453 Assert(paPages[iPage].Phys <= UINT32_C(0xfffff000));
1454 }
1455#ifdef RT_OS_DARWIN /* HACK ALERT! */
1456 supR3TouchPages(pReq->u.Out.pvR3, cPages);
1457#endif
1458 }
1459 RTMemTmpFree(pReq);
1460 }
1461 else
1462 rc = VERR_NO_TMP_MEMORY;
1463
1464 return rc;
1465}
1466
1467
1468SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages)
1469{
1470 /*
1471 * Validate.
1472 */
1473 if (!pv)
1474 return VINF_SUCCESS;
1475 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1476 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1477
1478 /* fake */
1479 if (RT_UNLIKELY(g_uSupFakeMode))
1480 {
1481 RTMemPageFree(pv, cPages * PAGE_SIZE);
1482 return VINF_SUCCESS;
1483 }
1484
1485 /*
1486 * Issue IOCtl to the SUPDRV kernel module.
1487 */
1488 SUPCONTFREE Req;
1489 Req.Hdr.u32Cookie = g_u32Cookie;
1490 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1491 Req.Hdr.cbIn = SUP_IOCTL_LOW_FREE_SIZE_IN;
1492 Req.Hdr.cbOut = SUP_IOCTL_LOW_FREE_SIZE_OUT;
1493 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1494 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1495 Req.u.In.pvR3 = pv;
1496 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_FREE, &Req, SUP_IOCTL_LOW_FREE_SIZE);
1497 if (RT_SUCCESS(rc))
1498 rc = Req.Hdr.rc;
1499 return rc;
1500}
1501
1502
1503SUPR3DECL(int) SUPR3HardenedVerifyInit(void)
1504{
1505#ifdef RT_OS_WINDOWS
1506 if (g_cInits == 0)
1507 return suplibOsHardenedVerifyInit();
1508#endif
1509 return VINF_SUCCESS;
1510}
1511
1512
1513SUPR3DECL(int) SUPR3HardenedVerifyTerm(void)
1514{
1515#ifdef RT_OS_WINDOWS
1516 if (g_cInits == 0)
1517 return suplibOsHardenedVerifyTerm();
1518#endif
1519 return VINF_SUCCESS;
1520}
1521
1522
1523SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszMsg, PRTFILE phFile)
1524{
1525 /*
1526 * Quick input validation.
1527 */
1528 AssertPtr(pszFilename);
1529 AssertPtr(pszMsg);
1530 AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the
1531 file is the same we verified after opening it. */
1532 RT_NOREF2(pszFilename, pszMsg);
1533
1534 /*
1535 * Only do the actual check in hardened builds.
1536 */
1537#ifdef VBOX_WITH_HARDENING
1538 int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
1539 if (RT_FAILURE(rc))
1540 LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));
1541 return rc;
1542#else
1543 return VINF_SUCCESS;
1544#endif
1545}
1546
1547
1548SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo)
1549{
1550 /*
1551 * Quick input validation.
1552 */
1553 AssertPtr(pszArgv0);
1554 RTErrInfoClear(pErrInfo);
1555
1556 /*
1557 * Get the executable image path as we need it for all the tests here.
1558 */
1559 char szExecPath[RTPATH_MAX];
1560 if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
1561 return RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_2, "RTProcGetExecutablePath failed");
1562
1563 int rc;
1564 if (fInternal)
1565 {
1566 /*
1567 * Internal applications must be launched directly without any PATH
1568 * searching involved.
1569 */
1570 if (RTPathCompare(pszArgv0, szExecPath) != 0)
1571 return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,
1572 "argv[0] does not match the executable image path: '%s' != '%s'", pszArgv0, szExecPath);
1573
1574 /*
1575 * Internal applications must reside in or under the
1576 * RTPathAppPrivateArch directory.
1577 */
1578 char szAppPrivateArch[RTPATH_MAX];
1579 rc = RTPathAppPrivateArch(szAppPrivateArch, sizeof(szAppPrivateArch));
1580 if (RT_FAILURE(rc))
1581 return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,
1582 "RTPathAppPrivateArch failed with rc=%Rrc", rc);
1583 size_t cchAppPrivateArch = strlen(szAppPrivateArch);
1584 if ( cchAppPrivateArch >= strlen(szExecPath)
1585 || !RTPATH_IS_SLASH(szExecPath[cchAppPrivateArch]))
1586 return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,
1587 "Internal executable does reside under RTPathAppPrivateArch");
1588 szExecPath[cchAppPrivateArch] = '\0';
1589 if (RTPathCompare(szExecPath, szAppPrivateArch) != 0)
1590 return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,
1591 "Internal executable does reside under RTPathAppPrivateArch");
1592 szExecPath[cchAppPrivateArch] = RTPATH_SLASH;
1593 }
1594
1595#ifdef VBOX_WITH_HARDENING
1596 /*
1597 * Verify that the image file and parent directories are sane.
1598 */
1599 rc = supR3HardenedVerifyFile(szExecPath, RTHCUINTPTR_MAX, false /*fMaybe3rdParty*/, pErrInfo);
1600 if (RT_FAILURE(rc))
1601 return rc;
1602#endif
1603
1604 return VINF_SUCCESS;
1605}
1606
1607
1608SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
1609{
1610 /*
1611 * Quick input validation
1612 */
1613 AssertPtr(pszDirPath);
1614 RTErrInfoClear(pErrInfo);
1615
1616 /*
1617 * Only do the actual check in hardened builds.
1618 */
1619#ifdef VBOX_WITH_HARDENING
1620 int rc = supR3HardenedVerifyDir(pszDirPath, fRecursive, fCheckFiles, pErrInfo);
1621 if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
1622 LogRel(("supR3HardenedVerifyDir: Verification of \"%s\" failed, rc=%Rrc\n", pszDirPath, rc));
1623 return rc;
1624#else
1625 NOREF(pszDirPath); NOREF(fRecursive); NOREF(fCheckFiles);
1626 return VINF_SUCCESS;
1627#endif
1628}
1629
1630
1631SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo)
1632{
1633 /*
1634 * Quick input validation
1635 */
1636 AssertPtr(pszFilename);
1637 RTErrInfoClear(pErrInfo);
1638
1639 /*
1640 * Only do the actual check in hardened builds.
1641 */
1642#ifdef VBOX_WITH_HARDENING
1643 int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, true /*fMaybe3rdParty*/, pErrInfo);
1644 if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
1645 LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
1646 return rc;
1647#else
1648 RT_NOREF1(pszFilename);
1649 return VINF_SUCCESS;
1650#endif
1651}
1652
1653
1654SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
1655{
1656 if (g_pSUPGlobalInfoPage)
1657 {
1658 *pHCPhys = g_HCPhysSUPGlobalInfoPage;
1659 return VINF_SUCCESS;
1660 }
1661 *pHCPhys = NIL_RTHCPHYS;
1662 return VERR_WRONG_ORDER;
1663}
1664
1665
1666SUPR3DECL(int) SUPR3QueryVTxSupported(const char **ppszWhy)
1667{
1668 *ppszWhy = NULL;
1669#ifdef RT_OS_LINUX
1670 return suplibOsQueryVTxSupported(ppszWhy);
1671#else
1672 return VINF_SUCCESS;
1673#endif
1674}
1675
1676
1677SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps)
1678{
1679 AssertPtrReturn(pfCaps, VERR_INVALID_POINTER);
1680
1681 *pfCaps = 0;
1682
1683 /* fake */
1684 if (RT_UNLIKELY(g_uSupFakeMode))
1685 return VINF_SUCCESS;
1686
1687 /*
1688 * Issue IOCtl to the SUPDRV kernel module.
1689 */
1690 SUPVTCAPS Req;
1691 Req.Hdr.u32Cookie = g_u32Cookie;
1692 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1693 Req.Hdr.cbIn = SUP_IOCTL_VT_CAPS_SIZE_IN;
1694 Req.Hdr.cbOut = SUP_IOCTL_VT_CAPS_SIZE_OUT;
1695 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1696 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1697 Req.u.Out.fCaps = 0;
1698 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_VT_CAPS, &Req, SUP_IOCTL_VT_CAPS_SIZE);
1699 if (RT_SUCCESS(rc))
1700 {
1701 rc = Req.Hdr.rc;
1702 if (RT_SUCCESS(rc))
1703 *pfCaps = Req.u.Out.fCaps;
1704 }
1705 return rc;
1706}
1707
1708
1709SUPR3DECL(bool) SUPR3IsNemSupportedWhenNoVtxOrAmdV(void)
1710{
1711#ifdef RT_OS_WINDOWS
1712 return suplibOsIsNemSupportedWhenNoVtxOrAmdV();
1713#else
1714 return false;
1715#endif
1716}
1717
1718
1719SUPR3DECL(int) SUPR3QueryMicrocodeRev(uint32_t *uMicrocodeRev)
1720{
1721 AssertPtrReturn(uMicrocodeRev, VERR_INVALID_POINTER);
1722
1723 *uMicrocodeRev = 0;
1724
1725 /* fake */
1726 if (RT_UNLIKELY(g_uSupFakeMode))
1727 return VINF_SUCCESS;
1728
1729 /*
1730 * Issue IOCtl to the SUPDRV kernel module.
1731 */
1732 SUPUCODEREV Req;
1733 Req.Hdr.u32Cookie = g_u32Cookie;
1734 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1735 Req.Hdr.cbIn = SUP_IOCTL_UCODE_REV_SIZE_IN;
1736 Req.Hdr.cbOut = SUP_IOCTL_UCODE_REV_SIZE_OUT;
1737 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1738 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1739 Req.u.Out.MicrocodeRev = 0;
1740 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_UCODE_REV, &Req, SUP_IOCTL_UCODE_REV_SIZE);
1741 if (RT_SUCCESS(rc))
1742 {
1743 rc = Req.Hdr.rc;
1744 if (RT_SUCCESS(rc))
1745 *uMicrocodeRev = Req.u.Out.MicrocodeRev;
1746 }
1747 return rc;
1748}
1749
1750
1751SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg)
1752{
1753 /* fake */
1754 if (RT_UNLIKELY(g_uSupFakeMode))
1755 return VINF_SUCCESS;
1756
1757 /*
1758 * Issue IOCtl to the SUPDRV kernel module.
1759 */
1760 SUPTRACEROPEN Req;
1761 Req.Hdr.u32Cookie = g_u32Cookie;
1762 Req.Hdr.u32SessionCookie= g_u32SessionCookie;
1763 Req.Hdr.cbIn = SUP_IOCTL_TRACER_OPEN_SIZE_IN;
1764 Req.Hdr.cbOut = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;
1765 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1766 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1767 Req.u.In.uCookie = uCookie;
1768 Req.u.In.uArg = uArg;
1769 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_OPEN, &Req, SUP_IOCTL_TRACER_OPEN_SIZE);
1770 if (RT_SUCCESS(rc))
1771 rc = Req.Hdr.rc;
1772 return rc;
1773}
1774
1775
1776SUPR3DECL(int) SUPR3TracerClose(void)
1777{
1778 /* fake */
1779 if (RT_UNLIKELY(g_uSupFakeMode))
1780 return VINF_SUCCESS;
1781
1782 /*
1783 * Issue IOCtl to the SUPDRV kernel module.
1784 */
1785 SUPREQHDR Req;
1786 Req.u32Cookie = g_u32Cookie;
1787 Req.u32SessionCookie= g_u32SessionCookie;
1788 Req.cbIn = SUP_IOCTL_TRACER_OPEN_SIZE_IN;
1789 Req.cbOut = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;
1790 Req.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1791 Req.rc = VERR_INTERNAL_ERROR;
1792 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_CLOSE, &Req, SUP_IOCTL_TRACER_CLOSE_SIZE);
1793 if (RT_SUCCESS(rc))
1794 rc = Req.rc;
1795 return rc;
1796}
1797
1798
1799SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
1800{
1801 /* fake */
1802 if (RT_UNLIKELY(g_uSupFakeMode))
1803 {
1804 *piRetVal = -1;
1805 return VERR_NOT_SUPPORTED;
1806 }
1807
1808 /*
1809 * Issue IOCtl to the SUPDRV kernel module.
1810 */
1811 SUPTRACERIOCTL Req;
1812 Req.Hdr.u32Cookie = g_u32Cookie;
1813 Req.Hdr.u32SessionCookie= g_u32SessionCookie;
1814 Req.Hdr.cbIn = SUP_IOCTL_TRACER_IOCTL_SIZE_IN;
1815 Req.Hdr.cbOut = SUP_IOCTL_TRACER_IOCTL_SIZE_OUT;
1816 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1817 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1818 Req.u.In.uCmd = uCmd;
1819 Req.u.In.uArg = uArg;
1820 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_IOCTL, &Req, SUP_IOCTL_TRACER_IOCTL_SIZE);
1821 if (RT_SUCCESS(rc))
1822 {
1823 rc = Req.Hdr.rc;
1824 *piRetVal = Req.u.Out.iRetVal;
1825 }
1826 return rc;
1827}
1828
1829
1830
1831typedef struct SUPDRVTRACERSTRTAB
1832{
1833 /** Pointer to the string table. */
1834 char *pchStrTab;
1835 /** The actual string table size. */
1836 uint32_t cbStrTab;
1837 /** The original string pointers. */
1838 RTUINTPTR apszOrgFunctions[1];
1839} SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB;
1840
1841
1842/**
1843 * Destroys a string table, restoring the original pszFunction member valus.
1844 *
1845 * @param pThis The string table structure.
1846 * @param paProbeLocs32 The probe location array, 32-bit type variant.
1847 * @param paProbeLocs64 The probe location array, 64-bit type variant.
1848 * @param cProbeLocs The number of elements in the array.
1849 * @param f32Bit Set if @a paProbeLocs32 should be used, when
1850 * clear use @a paProbeLocs64.
1851 */
1852static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,
1853 uint32_t cProbeLocs, bool f32Bit)
1854{
1855 /* Restore. */
1856 size_t i = cProbeLocs;
1857 if (f32Bit)
1858 while (i--)
1859 paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i];
1860 else
1861 while (i--)
1862 paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i];
1863
1864 /* Free. */
1865 RTMemFree(pThis->pchStrTab);
1866 RTMemFree(pThis);
1867}
1868
1869
1870/**
1871 * Creates a string table for the pszFunction members in the probe location
1872 * array.
1873 *
1874 * This will save and replace the pszFunction members with offsets.
1875 *
1876 * @returns Pointer to a string table structure. NULL on failure.
1877 * @param paProbeLocs32 The probe location array, 32-bit type variant.
1878 * @param paProbeLocs64 The probe location array, 64-bit type variant.
1879 * @param cProbeLocs The number of elements in the array.
1880 * @param offDelta Relocation offset for the string pointers.
1881 * @param f32Bit Set if @a paProbeLocs32 should be used, when
1882 * clear use @a paProbeLocs64.
1883 */
1884static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32,
1885 PVTGPROBELOC64 paProbeLocs64,
1886 uint32_t cProbeLocs,
1887 RTUINTPTR offDelta,
1888 bool f32Bit)
1889{
1890 if (cProbeLocs > _128K)
1891 return NULL;
1892
1893 /*
1894 * Allocate the string table structures.
1895 */
1896 size_t cbThis = RT_UOFFSETOF_DYN(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]);
1897 PSUPDRVTRACERSTRTAB pThis = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis);
1898 if (!pThis)
1899 return NULL;
1900
1901 uint32_t const cHashBits = cProbeLocs * 2 - 1;
1902 uint32_t *pbmHash = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 );
1903 if (!pbmHash)
1904 {
1905 RTMemFree(pThis);
1906 return NULL;
1907 }
1908
1909 /*
1910 * Calc the max string table size and save the orignal pointers so we can
1911 * replace them later.
1912 */
1913 size_t cbMax = 1;
1914 for (uint32_t i = 0; i < cProbeLocs; i++)
1915 {
1916 pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction;
1917 const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
1918 size_t cch = strlen(pszFunction);
1919 if (cch > _1K)
1920 {
1921 cbMax = 0;
1922 break;
1923 }
1924 cbMax += cch + 1;
1925 }
1926
1927 /* Alloc space for it. */
1928 if (cbMax > 0)
1929 pThis->pchStrTab = (char *)RTMemAlloc(cbMax);
1930 else
1931 pThis->pchStrTab = NULL;
1932 if (!pThis->pchStrTab)
1933 {
1934 RTMemFree(pbmHash);
1935 RTMemFree(pThis);
1936 return NULL;
1937 }
1938
1939 /*
1940 * Create the string table.
1941 */
1942 uint32_t off = 0;
1943 uint32_t offPrev = 0;
1944
1945 for (uint32_t i = 0; i < cProbeLocs; i++)
1946 {
1947 const char * const psz = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
1948 size_t const cch = strlen(psz);
1949 uint32_t const iHashBit = RTStrHash1(psz) % cHashBits;
1950 if (ASMBitTestAndSet(pbmHash, iHashBit))
1951 {
1952 /* Often it's the most recent string. */
1953 if ( off - offPrev < cch + 1
1954 || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
1955 {
1956 /* It wasn't, search the entire string table. (lazy bird) */
1957 offPrev = 0;
1958 while (offPrev < off)
1959 {
1960 size_t cchCur = strlen(&pThis->pchStrTab[offPrev]);
1961 if ( cchCur == cch
1962 && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
1963 break;
1964 offPrev += (uint32_t)cchCur + 1;
1965 }
1966 }
1967 }
1968 else
1969 offPrev = off;
1970
1971 /* Add the string to the table. */
1972 if (offPrev >= off)
1973 {
1974 memcpy(&pThis->pchStrTab[off], psz, cch + 1);
1975 offPrev = off;
1976 off += (uint32_t)cch + 1;
1977 }
1978
1979 /* Update the entry */
1980 if (f32Bit)
1981 paProbeLocs32[i].pszFunction = offPrev;
1982 else
1983 paProbeLocs64[i].pszFunction = offPrev;
1984 }
1985
1986 pThis->cbStrTab = off;
1987 RTMemFree(pbmHash);
1988 return pThis;
1989}
1990
1991
1992
1993SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
1994 RTUINTPTR uVtgHdrAddr, uint32_t fFlags)
1995{
1996 /* Validate input. */
1997 NOREF(hModNative);
1998 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
1999 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
2000 AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
2001 size_t cchModule = strlen(pszModule);
2002 AssertReturn(cchModule < RT_SIZEOFMEMB(SUPTRACERUMODREG, u.In.szName), VERR_FILENAME_TOO_LONG);
2003 AssertReturn(!RTPathHavePath(pszModule), VERR_INVALID_PARAMETER);
2004 AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);
2005
2006 /*
2007 * Set the probe location array offset and size members. If the size is
2008 * zero, don't bother ring-0 with it.
2009 */
2010 if (!pVtgHdr->offProbeLocs)
2011 {
2012 uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
2013 if (u64Tmp >= UINT32_MAX)
2014 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
2015 pVtgHdr->cbProbeLocs = (uint32_t)u64Tmp;
2016
2017 u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;
2018 if ((int64_t)u64Tmp != (int32_t)u64Tmp)
2019 {
2020 LogRel(("SUPR3TracerRegisterModule: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",
2021 u64Tmp, pVtgHdr->uProbeLocs.u64, uVtgHdrAddr));
2022 return VERR_SUPDRV_VTG_BAD_HDR_PTR;
2023 }
2024 pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
2025 }
2026
2027 if ( !pVtgHdr->cbProbeLocs
2028 || !pVtgHdr->cbProbes)
2029 return VINF_SUCCESS;
2030
2031 /*
2032 * Fake out.
2033 */
2034 if (RT_UNLIKELY(g_uSupFakeMode))
2035 return VINF_SUCCESS;
2036
2037 /*
2038 * Create a string table for the function names in the location array.
2039 * It's somewhat easier to do that here than from ring-0.
2040 */
2041 uint32_t const cProbeLocs = pVtgHdr->cbProbeLocs
2042 / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
2043 PVTGPROBELOC paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
2044 PSUPDRVTRACERSTRTAB pStrTab = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs,
2045 (PVTGPROBELOC64)paProbeLocs,
2046 cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr,
2047 pVtgHdr->cBits == 32);
2048 if (!pStrTab)
2049 return VERR_NO_MEMORY;
2050
2051
2052 /*
2053 * Issue IOCtl to the SUPDRV kernel module.
2054 */
2055 SUPTRACERUMODREG Req;
2056 Req.Hdr.u32Cookie = g_u32Cookie;
2057 Req.Hdr.u32SessionCookie= g_u32SessionCookie;
2058 Req.Hdr.cbIn = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;
2059 Req.Hdr.cbOut = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;
2060 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2061 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2062 Req.u.In.uVtgHdrAddr = uVtgHdrAddr;
2063 Req.u.In.R3PtrVtgHdr = pVtgHdr;
2064 Req.u.In.R3PtrStrTab = pStrTab->pchStrTab;
2065 Req.u.In.cbStrTab = pStrTab->cbStrTab;
2066 Req.u.In.fFlags = fFlags;
2067
2068 memcpy(Req.u.In.szName, pszModule, cchModule + 1);
2069 if (!RTPathHasSuffix(Req.u.In.szName))
2070 {
2071 /* Add the default suffix if none is given. */
2072 switch (fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK)
2073 {
2074#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
2075 case SUP_TRACER_UMOD_FLAGS_EXE:
2076 if (cchModule + sizeof(".exe") <= sizeof(Req.u.In.szName))
2077 strcpy(&Req.u.In.szName[cchModule], ".exe");
2078 break;
2079#endif
2080
2081 case SUP_TRACER_UMOD_FLAGS_SHARED:
2082 {
2083 const char *pszSuff = RTLdrGetSuff();
2084 size_t cchSuff = strlen(pszSuff);
2085 if (cchModule + cchSuff < sizeof(Req.u.In.szName))
2086 memcpy(&Req.u.In.szName[cchModule], pszSuff, cchSuff + 1);
2087 break;
2088 }
2089 }
2090 }
2091
2092 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_REG, &Req, SUP_IOCTL_TRACER_UMOD_REG_SIZE);
2093 if (RT_SUCCESS(rc))
2094 rc = Req.Hdr.rc;
2095
2096 supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs,
2097 cProbeLocs, pVtgHdr->cBits == 32);
2098 return rc;
2099}
2100
2101
2102SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr)
2103{
2104 /* Validate input. */
2105 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
2106 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
2107
2108 /*
2109 * Don't bother if the object is empty.
2110 */
2111 if ( !pVtgHdr->cbProbeLocs
2112 || !pVtgHdr->cbProbes)
2113 return VINF_SUCCESS;
2114
2115 /*
2116 * Fake out.
2117 */
2118 if (RT_UNLIKELY(g_uSupFakeMode))
2119 return VINF_SUCCESS;
2120
2121 /*
2122 * Issue IOCtl to the SUPDRV kernel module.
2123 */
2124 SUPTRACERUMODDEREG Req;
2125 Req.Hdr.u32Cookie = g_u32Cookie;
2126 Req.Hdr.u32SessionCookie= g_u32SessionCookie;
2127 Req.Hdr.cbIn = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;
2128 Req.Hdr.cbOut = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;
2129 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2130 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2131 Req.u.In.pVtgHdr = pVtgHdr;
2132
2133 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_DEREG, &Req, SUP_IOCTL_TRACER_UMOD_DEREG_SIZE);
2134 if (RT_SUCCESS(rc))
2135 rc = Req.Hdr.rc;
2136 return rc;
2137}
2138
2139
2140DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq)
2141{
2142 RT_NOREF1(pProbeLoc);
2143
2144 pReq->Hdr.u32Cookie = g_u32Cookie;
2145 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
2146 Assert(pReq->Hdr.cbIn == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN);
2147 Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT);
2148 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2149 pReq->Hdr.rc = VINF_SUCCESS;
2150
2151 suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE);
2152}
2153
2154
2155SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp)
2156{
2157 SUPMSRPROBER Req;
2158 Req.Hdr.u32Cookie = g_u32Cookie;
2159 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2160 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN;
2161 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
2162 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2163 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2164
2165 Req.u.In.enmOp = SUPMSRPROBEROP_READ;
2166 Req.u.In.uMsr = uMsr;
2167 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
2168
2169 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
2170 if (RT_SUCCESS(rc))
2171 rc = Req.Hdr.rc;
2172 if (RT_SUCCESS(rc))
2173 {
2174 if (puValue)
2175 *puValue = Req.u.Out.uResults.Read.uValue;
2176 if (pfGp)
2177 *pfGp = Req.u.Out.uResults.Read.fGp;
2178 }
2179
2180 return rc;
2181}
2182
2183
2184SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp)
2185{
2186 SUPMSRPROBER Req;
2187 Req.Hdr.u32Cookie = g_u32Cookie;
2188 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2189 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN;
2190 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
2191 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2192 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2193
2194 Req.u.In.enmOp = SUPMSRPROBEROP_WRITE;
2195 Req.u.In.uMsr = uMsr;
2196 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
2197 Req.u.In.uArgs.Write.uToWrite = uValue;
2198
2199 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
2200 if (RT_SUCCESS(rc))
2201 rc = Req.Hdr.rc;
2202 if (RT_SUCCESS(rc) && pfGp)
2203 *pfGp = Req.u.Out.uResults.Write.fGp;
2204
2205 return rc;
2206}
2207
2208
2209SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
2210 PSUPMSRPROBERMODIFYRESULT pResult)
2211{
2212 return SUPR3MsrProberModifyEx(uMsr, idCpu, fAndMask, fOrMask, false /*fFaster*/, pResult);
2213}
2214
2215
2216SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
2217 PSUPMSRPROBERMODIFYRESULT pResult)
2218{
2219 SUPMSRPROBER Req;
2220 Req.Hdr.u32Cookie = g_u32Cookie;
2221 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2222 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN;
2223 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
2224 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2225 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2226
2227 Req.u.In.enmOp = fFaster ? SUPMSRPROBEROP_MODIFY_FASTER : SUPMSRPROBEROP_MODIFY;
2228 Req.u.In.uMsr = uMsr;
2229 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
2230 Req.u.In.uArgs.Modify.fAndMask = fAndMask;
2231 Req.u.In.uArgs.Modify.fOrMask = fOrMask;
2232
2233 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
2234 if (RT_SUCCESS(rc))
2235 rc = Req.Hdr.rc;
2236 if (RT_SUCCESS(rc))
2237 *pResult = Req.u.Out.uResults.Modify;
2238
2239 return rc;
2240}
2241
2242
2243SUPR3DECL(int) SUPR3ResumeSuspendedKeyboards(void)
2244{
2245#ifdef RT_OS_DARWIN
2246 /*
2247 * Issue IOCtl to the SUPDRV kernel module.
2248 */
2249 SUPREQHDR Req;
2250 Req.u32Cookie = g_u32Cookie;
2251 Req.u32SessionCookie= g_u32SessionCookie;
2252 Req.cbIn = SUP_IOCTL_RESUME_SUSPENDED_KBDS_SIZE_IN;
2253 Req.cbOut = SUP_IOCTL_RESUME_SUSPENDED_KBDS_SIZE_OUT;
2254 Req.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2255 Req.rc = VERR_INTERNAL_ERROR;
2256 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_RESUME_SUSPENDED_KBDS, &Req, SUP_IOCTL_RESUME_SUSPENDED_KBDS_SIZE);
2257 if (RT_SUCCESS(rc))
2258 rc = Req.rc;
2259 return rc;
2260#else /* !RT_OS_DARWIN */
2261 return VERR_NOT_SUPPORTED;
2262#endif
2263}
2264
2265
2266SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry)
2267{
2268 SUPTSCDELTAMEASURE Req;
2269 Req.Hdr.u32Cookie = g_u32Cookie;
2270 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2271 Req.Hdr.cbIn = SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_IN;
2272 Req.Hdr.cbOut = SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_OUT;
2273 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2274 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2275
2276 Req.u.In.cRetries = cRetries;
2277 Req.u.In.fAsync = fAsync;
2278 Req.u.In.fForce = fForce;
2279 Req.u.In.idCpu = idCpu;
2280 Req.u.In.cMsWaitRetry = cMsWaitRetry;
2281
2282 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TSC_DELTA_MEASURE, &Req, SUP_IOCTL_TSC_DELTA_MEASURE_SIZE);
2283 if (RT_SUCCESS(rc))
2284 rc = Req.Hdr.rc;
2285 return rc;
2286}
2287
2288
2289SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic)
2290{
2291 AssertReturn(puTsc, VERR_INVALID_PARAMETER);
2292
2293 SUPTSCREAD Req;
2294 Req.Hdr.u32Cookie = g_u32Cookie;
2295 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2296 Req.Hdr.cbIn = SUP_IOCTL_TSC_READ_SIZE_IN;
2297 Req.Hdr.cbOut = SUP_IOCTL_TSC_READ_SIZE_OUT;
2298 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2299 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2300
2301 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TSC_READ, &Req, SUP_IOCTL_TSC_READ_SIZE);
2302 if (RT_SUCCESS(rc))
2303 {
2304 rc = Req.Hdr.rc;
2305 *puTsc = Req.u.Out.u64AdjustedTsc;
2306 if (pidApic)
2307 *pidApic = Req.u.Out.idApic;
2308 }
2309 return rc;
2310}
2311
2312
2313SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask)
2314{
2315 AssertMsgReturn(!(fOrMask & ~SUPGIP_FLAGS_VALID_MASK),
2316 ("fOrMask=%#x ValidMask=%#x\n", fOrMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
2317 AssertMsgReturn((fAndMask & ~SUPGIP_FLAGS_VALID_MASK) == ~SUPGIP_FLAGS_VALID_MASK,
2318 ("fAndMask=%#x ValidMask=%#x\n", fAndMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
2319
2320 SUPGIPSETFLAGS Req;
2321 Req.Hdr.u32Cookie = g_u32Cookie;
2322 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2323 Req.Hdr.cbIn = SUP_IOCTL_GIP_SET_FLAGS_SIZE_IN;
2324 Req.Hdr.cbOut = SUP_IOCTL_GIP_SET_FLAGS_SIZE_OUT;
2325 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2326 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2327
2328 Req.u.In.fAndMask = fAndMask;
2329 Req.u.In.fOrMask = fOrMask;
2330
2331 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_SET_FLAGS, &Req, SUP_IOCTL_GIP_SET_FLAGS_SIZE);
2332 if (RT_SUCCESS(rc))
2333 rc = Req.Hdr.rc;
2334 return rc;
2335}
2336
2337
2338SUPR3DECL(int) SUPR3GetHwvirtMsrs(PSUPHWVIRTMSRS pHwvirtMsrs, bool fForceRequery)
2339{
2340 AssertReturn(pHwvirtMsrs, VERR_INVALID_PARAMETER);
2341
2342 SUPGETHWVIRTMSRS Req;
2343 Req.Hdr.u32Cookie = g_u32Cookie;
2344 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
2345 Req.Hdr.cbIn = SUP_IOCTL_GET_HWVIRT_MSRS_SIZE_IN;
2346 Req.Hdr.cbOut = SUP_IOCTL_GET_HWVIRT_MSRS_SIZE_OUT;
2347 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
2348 Req.Hdr.rc = VERR_INTERNAL_ERROR;
2349
2350 Req.u.In.fForce = fForceRequery;
2351 Req.u.In.fReserved0 = false;
2352 Req.u.In.fReserved1 = false;
2353 Req.u.In.fReserved2 = false;
2354
2355 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_HWVIRT_MSRS, &Req, SUP_IOCTL_GET_HWVIRT_MSRS_SIZE);
2356 if (RT_SUCCESS(rc))
2357 {
2358 rc = Req.Hdr.rc;
2359 *pHwvirtMsrs = Req.u.Out.HwvirtMsrs;
2360 }
2361 else
2362 RT_ZERO(*pHwvirtMsrs);
2363 return rc;
2364}
2365
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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