VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp@ 4811

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

Split VMMR0Entry into VMMR0EntryInt, VMMR0EntryFast and VMMr0EntryEx. This will prevent the SUPCallVMMR0Ex path from causing harm and messing up the paths that has to be optimized.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.1 KB
Line 
1/* $Id: SUPDrv-win.cpp 4811 2007-09-14 17:53:56Z vboxsync $ */
2/** @file
3 * VirtualBox Support Driver - Windows NT specific parts.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include "SUPDRV.h"
24#include <excpt.h>
25#include <iprt/assert.h>
26#include <iprt/process.h>
27
28
29/*******************************************************************************
30* Defined Constants And Macros *
31*******************************************************************************/
32/** The support service name. */
33#define SERVICE_NAME "VBoxDrv"
34/** Win32 Device name. */
35#define DEVICE_NAME "\\\\.\\VBoxDrv"
36/** NT Device name. */
37#define DEVICE_NAME_NT L"\\Device\\VBoxDrv"
38/** Win Symlink name. */
39#define DEVICE_NAME_DOS L"\\DosDevices\\VBoxDrv"
40/** The Pool tag (VBox). */
41#define SUPDRV_NT_POOL_TAG 'xoBV'
42
43
44/*******************************************************************************
45* Structures and Typedefs *
46*******************************************************************************/
47#if 0 //def RT_ARCH_AMD64
48typedef struct SUPDRVEXECMEM
49{
50 PMDL pMdl;
51 void *pvMapping;
52 void *pvAllocation;
53} SUPDRVEXECMEM, *PSUPDRVEXECMEM;
54#endif
55
56
57/*******************************************************************************
58* Internal Functions *
59*******************************************************************************/
60static void _stdcall VBoxDrvNtUnload(PDRIVER_OBJECT pDrvObj);
61static NTSTATUS _stdcall VBoxDrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
62static NTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
63static NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
64static int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
65static NTSTATUS _stdcall VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
66static NTSTATUS VBoxDrvNtErr2NtStatus(int rc);
67static NTSTATUS VBoxDrvNtGipInit(PSUPDRVDEVEXT pDevExt);
68static void VBoxDrvNtGipTerm(PSUPDRVDEVEXT pDevExt);
69static void _stdcall VBoxDrvNtGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
70static void _stdcall VBoxDrvNtGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
71
72
73/*******************************************************************************
74* Exported Functions *
75*******************************************************************************/
76__BEGIN_DECLS
77ULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
78__END_DECLS
79
80
81/**
82 * Driver entry point.
83 *
84 * @returns appropriate status code.
85 * @param pDrvObj Pointer to driver object.
86 * @param pRegPath Registry base path.
87 */
88ULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
89{
90 NTSTATUS rc;
91 dprintf(("VBoxDrv::DriverEntry\n"));
92
93 /*
94 * Create device.
95 * (That means creating a device object and a symbolic link so the DOS
96 * subsystems (OS/2, win32, ++) can access the device.)
97 */
98 UNICODE_STRING DevName;
99 RtlInitUnicodeString(&DevName, DEVICE_NAME_NT);
100 PDEVICE_OBJECT pDevObj;
101 rc = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
102 if (NT_SUCCESS(rc))
103 {
104 UNICODE_STRING DosName;
105 RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
106 rc = IoCreateSymbolicLink(&DosName, &DevName);
107 if (NT_SUCCESS(rc))
108 {
109 /*
110 * Initialize the device extension.
111 */
112 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
113 memset(pDevExt, 0, sizeof(*pDevExt));
114 int vrc = supdrvInitDevExt(pDevExt);
115 if (!vrc)
116 {
117 /*
118 * Inititalize the GIP.
119 */
120 rc = VBoxDrvNtGipInit(pDevExt);
121 if (NT_SUCCESS(rc))
122 {
123 /*
124 * Setup the driver entry points in pDrvObj.
125 */
126 pDrvObj->DriverUnload = VBoxDrvNtUnload;
127 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxDrvNtCreate;
128 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxDrvNtClose;
129 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxDrvNtDeviceControl;
130 pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxDrvNtNotSupportedStub;
131 pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxDrvNtNotSupportedStub;
132 /* more? */
133 dprintf(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
134 return STATUS_SUCCESS;
135 }
136 dprintf(("VBoxDrvNtGipInit failed with rc=%#x!\n", rc));
137
138 supdrvDeleteDevExt(pDevExt);
139 }
140 else
141 {
142 dprintf(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
143 rc = VBoxDrvNtErr2NtStatus(vrc);
144 }
145
146 IoDeleteSymbolicLink(&DosName);
147 }
148 else
149 dprintf(("IoCreateSymbolicLink failed with rc=%#x!\n", rc));
150
151 IoDeleteDevice(pDevObj);
152 }
153 else
154 dprintf(("IoCreateDevice failed with rc=%#x!\n", rc));
155
156 if (NT_SUCCESS(rc))
157 rc = STATUS_INVALID_PARAMETER;
158 dprintf(("VBoxDrv::DriverEntry returning %#x\n", rc));
159 return rc;
160}
161
162
163/**
164 * Unload the driver.
165 *
166 * @param pDrvObj Driver object.
167 */
168void _stdcall VBoxDrvNtUnload(PDRIVER_OBJECT pDrvObj)
169{
170 dprintf(("VBoxDrvNtUnload\n"));
171 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDrvObj->DeviceObject->DeviceExtension;
172
173 /*
174 * We ASSUME that it's not possible to unload a driver with open handles.
175 * Start by deleting the symbolic link
176 */
177 UNICODE_STRING DosName;
178 RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
179 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
180
181 /*
182 * Terminate the GIP page and delete the device extension.
183 */
184 VBoxDrvNtGipTerm(pDevExt);
185 supdrvDeleteDevExt(pDevExt);
186 IoDeleteDevice(pDrvObj->DeviceObject);
187}
188
189
190/**
191 * Create (i.e. Open) file entry point.
192 *
193 * @param pDevObj Device object.
194 * @param pIrp Request packet.
195 */
196NTSTATUS _stdcall VBoxDrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
197{
198 dprintf(("VBoxDrvNtCreate\n"));
199 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
200 PFILE_OBJECT pFileObj = pStack->FileObject;
201 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
202
203 /*
204 * We are not remotely similar to a directory...
205 * (But this is possible.)
206 */
207 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
208 {
209 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
210 pIrp->IoStatus.Information = 0;
211 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
212 return STATUS_NOT_A_DIRECTORY;
213 }
214
215 /*
216 * Call common code for the rest.
217 */
218 pFileObj->FsContext = NULL;
219 PSUPDRVSESSION pSession;
220 int rc = supdrvCreateSession(pDevExt, &pSession);
221 if (!rc)
222 {
223 pSession->Uid = NIL_RTUID;
224 pSession->Gid = NIL_RTGID;
225 pSession->Process = RTProcSelf();
226 pSession->R0Process = RTR0ProcHandleSelf();
227 pFileObj->FsContext = pSession;
228 }
229
230 NTSTATUS rcNt = pIrp->IoStatus.Status = VBoxDrvNtErr2NtStatus(rc);
231 pIrp->IoStatus.Information = 0;
232 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
233
234 return rcNt;
235}
236
237
238/**
239 * Close file entry point.
240 *
241 * @param pDevObj Device object.
242 * @param pIrp Request packet.
243 */
244NTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
245{
246 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
247 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
248 PFILE_OBJECT pFileObj = pStack->FileObject;
249 dprintf(("VBoxDrvNtClose: pDevExt=%p pFileObj=%p pSession=%p\n",
250 pDevExt, pFileObj, pFileObj->FsContext));
251 supdrvCloseSession(pDevExt, (PSUPDRVSESSION)pFileObj->FsContext);
252 pFileObj->FsContext = NULL;
253 pIrp->IoStatus.Information = 0;
254 pIrp->IoStatus.Status = STATUS_SUCCESS;
255 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
256
257 return STATUS_SUCCESS;
258}
259
260
261/**
262 * Device I/O Control entry point.
263 *
264 * @param pDevObj Device object.
265 * @param pIrp Request packet.
266 */
267NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
268{
269 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
270 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
271 PSUPDRVSESSION pSession = (PSUPDRVSESSION)pStack->FileObject->FsContext;
272
273 /*
274 * Deal with the two high-speed IOCtl that takes it's arguments from
275 * the session and iCmd, and only returns a VBox status code.
276 */
277 ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
278 if ( ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
279 || ulCmd == SUP_IOCTL_FAST_DO_HWACC_RUN
280 || ulCmd == SUP_IOCTL_FAST_DO_NOP)
281 {
282 int rc = supdrvIOCtlFast(ulCmd, pDevExt, pSession);
283
284 /* Complete the I/O request. */
285 NTSTATUS rcNt = pIrp->IoStatus.Status = STATUS_SUCCESS;
286 pIrp->IoStatus.Information = sizeof(rc);
287 __try
288 {
289 *(int *)pIrp->UserBuffer = rc;
290 }
291 __except(EXCEPTION_EXECUTE_HANDLER)
292 {
293 rcNt = pIrp->IoStatus.Status = GetExceptionCode();
294 dprintf(("VBoxSupDrvDeviceContorl: Exception Code %#x\n", rcNt));
295 }
296 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
297 return rcNt;
298 }
299
300 return VBoxDrvNtDeviceControlSlow(pDevExt, pSession, pIrp, pStack);
301}
302
303
304/**
305 * Worker for VBoxDrvNtDeviceControl that takes the slow IOCtl functions.
306 *
307 * @returns NT status code.
308 *
309 * @param pDevObj Device object.
310 * @param pSession The session.
311 * @param pIrp Request packet.
312 * @param pStack The stack location containing the DeviceControl parameters.
313 */
314static int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack)
315{
316 NTSTATUS rcNt;
317 unsigned cbOut = 0;
318 int rc = 0;
319 dprintf2(("VBoxDrvNtDeviceControlSlow(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n",
320 pDevExt, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode,
321 pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength,
322 pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession));
323
324#ifdef RT_ARCH_AMD64
325 /* Don't allow 32-bit processes to do any I/O controls. */
326 if (!IoIs32bitProcess(pIrp))
327#endif
328 {
329 /* Verify that it's a buffered CTL. */
330 if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
331 {
332 /* Verify that the sizes in the request header are correct. */
333 PSUPREQHDR pHdr = (PSUPREQHDR)pIrp->AssociatedIrp.SystemBuffer;
334 if ( pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr)
335 && pStack->Parameters.DeviceIoControl.InputBufferLength == pHdr->cbIn
336 && pStack->Parameters.DeviceIoControl.OutputBufferLength == pHdr->cbOut)
337 {
338 /*
339 * Do the job.
340 */
341 rc = supdrvIOCtl(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession, pHdr);
342 if (!rc)
343 {
344 rcNt = STATUS_SUCCESS;
345 cbOut = pHdr->cbOut;
346 if (cbOut > pStack->Parameters.DeviceIoControl.OutputBufferLength)
347 {
348 cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
349 OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n",
350 pHdr->cbOut, cbOut, pStack->Parameters.DeviceIoControl.IoControlCode));
351 }
352 }
353 else
354 rcNt = STATUS_INVALID_PARAMETER;
355 dprintf2(("VBoxDrvNtDeviceControlSlow: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
356 }
357 else
358 {
359 dprintf(("VBoxDrvNtDeviceControlSlow: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n",
360 pStack->Parameters.DeviceIoControl.IoControlCode,
361 pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbIn : 0,
362 pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbOut : 0,
363 pStack->Parameters.DeviceIoControl.InputBufferLength,
364 pStack->Parameters.DeviceIoControl.OutputBufferLength));
365 rcNt = STATUS_INVALID_PARAMETER;
366 }
367 }
368 else
369 {
370 dprintf(("VBoxDrvNtDeviceControlSlow: not buffered request (%#x) - not supported\n",
371 pStack->Parameters.DeviceIoControl.IoControlCode));
372 rcNt = STATUS_NOT_SUPPORTED;
373 }
374 }
375#ifdef RT_ARCH_AMD64
376 else
377 {
378 dprintf(("VBoxDrvNtDeviceControlSlow: WOW64 req - not supported\n"));
379 rcNt = STATUS_NOT_SUPPORTED;
380 }
381#endif
382
383 /* complete the request. */
384 pIrp->IoStatus.Status = rcNt;
385 pIrp->IoStatus.Information = cbOut;
386 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
387 return rcNt;
388}
389
390
391/**
392 * Stub function for functions we don't implemented.
393 *
394 * @returns STATUS_NOT_SUPPORTED
395 * @param pDevObj Device object.
396 * @param pIrp IRP.
397 */
398NTSTATUS _stdcall VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
399{
400 dprintf(("VBoxDrvNtNotSupportedStub\n"));
401 pDevObj = pDevObj;
402
403 pIrp->IoStatus.Information = 0;
404 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
405 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
406
407 return STATUS_NOT_SUPPORTED;
408}
409
410
411/**
412 * Initializes any OS specific object creator fields.
413 */
414void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
415{
416 NOREF(pObj);
417 NOREF(pSession);
418}
419
420
421/**
422 * Checks if the session can access the object.
423 *
424 * @returns true if a decision has been made.
425 * @returns false if the default access policy should be applied.
426 *
427 * @param pObj The object in question.
428 * @param pSession The session wanting to access the object.
429 * @param pszObjName The object name, can be NULL.
430 * @param prc Where to store the result when returning true.
431 */
432bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
433{
434 NOREF(pObj);
435 NOREF(pSession);
436 NOREF(pszObjName);
437 NOREF(prc);
438 return false;
439}
440
441
442#ifndef USE_NEW_OS_INTERFACE_FOR_MM
443
444/**
445 * OS Specific code for locking down memory.
446 *
447 * @returns 0 on success.
448 * @returns SUPDRV_ERR_* on failure.
449 * @param pMem Pointer to memory.
450 * This is not linked in anywhere.
451 * @param paPages Array which should be filled with the address of the physical pages.
452 */
453int VBOXCALL supdrvOSLockMemOne(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
454{
455 /* paranoia */
456 if (!pMem->cb)
457 {
458 AssertMsgFailed(("Fool! No memory to lock!\n"));
459 return SUPDRV_ERR_INVALID_PARAM;
460 }
461 Assert(RT_ALIGN(pMem->cb, PAGE_SIZE) == pMem->cb);
462
463 /*
464 * Calc the number of MDLs we need to allocate.
465 */
466 unsigned cMdls = pMem->cb / MAX_LOCK_MEM_SIZE;
467 if ((pMem->cb % MAX_LOCK_MEM_SIZE) > 0)
468 cMdls++;
469
470 /*
471 * Allocate memory for the MDL pointer array.
472 */
473 pMem->u.locked.papMdl = (PMDL *)ExAllocatePoolWithTag(NonPagedPool, sizeof(*pMem->u.locked.papMdl) * cMdls, SUPDRV_NT_POOL_TAG);
474 if (!pMem->u.locked.papMdl)
475 {
476 AssertMsgFailed(("shit, couldn't allocated %d bytes for the mdl pointer array!\n", sizeof(*pMem->u.locked.papMdl) * cMdls));
477 return SUPDRV_ERR_NO_MEMORY;
478 }
479
480 /*
481 * Loop locking down the sub parts of the memory.
482 */
483 PSUPPAGE pPage = paPages;
484 unsigned cbTotal = 0;
485 uint8_t *pu8 = (uint8_t *)pMem->pvR3;
486 for (unsigned i = 0; i < cMdls; i++)
487 {
488 /*
489 * Calc the number of bytes to lock this time.
490 */
491 unsigned cbCur = pMem->cb - cbTotal;
492 if (cbCur > MAX_LOCK_MEM_SIZE)
493 cbCur = MAX_LOCK_MEM_SIZE;
494
495 if (cbCur == 0)
496 AssertMsgFailed(("cbCur: 0!\n"));
497
498 /*
499 * Allocate pMdl.
500 */
501 PMDL pMdl = IoAllocateMdl(pu8, cbCur, FALSE, FALSE, NULL);
502 if (!pMdl)
503 {
504 AssertMsgFailed(("Ops! IoAllocateMdl failed for pu8=%p and cb=%d\n", pu8, cbCur));
505 return SUPDRV_ERR_NO_MEMORY;
506 }
507
508 /*
509 * Lock the pages.
510 */
511 NTSTATUS rc = STATUS_SUCCESS;
512 __try
513 {
514 MmProbeAndLockPages(pMdl, UserMode, IoModifyAccess);
515 }
516 __except(EXCEPTION_EXECUTE_HANDLER)
517 {
518 rc = GetExceptionCode();
519 dprintf(("supdrvOSLockMemOne: Exception Code %#x\n", rc));
520 }
521
522 if (!NT_SUCCESS(rc))
523 {
524 /*
525 * Cleanup and fail.
526 */
527 IoFreeMdl(pMdl);
528 while (i-- > 0)
529 {
530 MmUnlockPages(pMem->u.locked.papMdl[i]);
531 IoFreeMdl(pMem->u.locked.papMdl[i]);
532 }
533 ExFreePool(pMem->u.locked.papMdl);
534 pMem->u.locked.papMdl = NULL;
535 return SUPDRV_ERR_LOCK_FAILED;
536 }
537
538 /*
539 * Add MDL to array and update the pages.
540 */
541 pMem->u.locked.papMdl[i] = pMdl;
542
543 const uintptr_t *pauPFNs = (uintptr_t *)(pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
544 for (unsigned iPage = 0, cPages = cbCur >> PAGE_SHIFT; iPage < cPages; iPage++)
545 {
546 pPage->Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
547 pPage->uReserved = 0;
548 pPage++;
549 }
550
551 /* next */
552 cbTotal += cbCur;
553 pu8 += cbCur;
554 }
555
556 /*
557 * Finish structure and return succesfully.
558 */
559 pMem->u.locked.cMdls = cMdls;
560
561 dprintf2(("supdrvOSLockMemOne: pvR3=%p cb=%d cMdls=%d\n",
562 pMem->pvR3, pMem->cb, cMdls));
563 return 0;
564}
565
566
567/**
568 * Unlocks the memory pointed to by pv.
569 *
570 * @param pv Memory to unlock.
571 * @param cb Size of the memory (debug).
572 */
573void VBOXCALL supdrvOSUnlockMemOne(PSUPDRVMEMREF pMem)
574{
575 dprintf2(("supdrvOSUnlockMemOne: pvR3=%p cb=%d cMdl=%p papMdl=%p\n",
576 pMem->pvR3, pMem->cb, pMem->u.locked.cMdls, pMem->u.locked.papMdl));
577
578 for (unsigned i = 0; i < pMem->u.locked.cMdls; i++)
579 {
580 MmUnlockPages(pMem->u.locked.papMdl[i]);
581 IoFreeMdl(pMem->u.locked.papMdl[i]);
582 }
583
584 ExFreePool(pMem->u.locked.papMdl);
585 pMem->u.locked.papMdl = NULL;
586}
587
588
589/**
590 * OS Specific code for allocating page aligned memory with continuous fixed
591 * physical paged backing.
592 *
593 * @returns 0 on success.
594 * @returns SUPDRV_ERR_* on failure.
595 * @param pMem Memory reference record of the memory to be allocated.
596 * (This is not linked in anywhere.)
597 * @param ppvR0 Where to store the virtual address of the ring-0 mapping. (optional)
598 * @param ppvR3 Where to store the virtual address of the ring-3 mapping.
599 * @param pHCPhys Where to store the physical address.
600 */
601int VBOXCALL supdrvOSContAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys)
602{
603 Assert(ppvR3);
604 Assert(pHCPhys);
605
606 /*
607 * Try allocate the memory.
608 */
609 PHYSICAL_ADDRESS Phys;
610 Phys.HighPart = 0;
611 Phys.LowPart = ~0;
612 unsigned cbAligned = RT_ALIGN(pMem->cb, PAGE_SIZE);
613 pMem->pvR0 = MmAllocateContiguousMemory(cbAligned, Phys);
614 if (!pMem->pvR0)
615 return SUPDRV_ERR_NO_MEMORY;
616
617 /*
618 * Map into user space.
619 */
620 int rc = SUPDRV_ERR_NO_MEMORY;
621 pMem->u.cont.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
622 if (pMem->u.cont.pMdl)
623 {
624 MmBuildMdlForNonPagedPool(pMem->u.cont.pMdl);
625 __try
626 {
627 pMem->pvR3 = (RTR3PTR)MmMapLockedPagesSpecifyCache(pMem->u.cont.pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
628 if (pMem->pvR3)
629 {
630 /*
631 * Done, setup pMem and return values.
632 */
633#ifdef RT_ARCH_AMD64
634 MmProtectMdlSystemAddress(pMem->u.cont.pMdl, PAGE_EXECUTE_READWRITE);
635#endif
636 *ppvR3 = pMem->pvR3;
637 if (ppvR0)
638 *ppvR0 = pMem->pvR0;
639 const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.cont.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
640 *pHCPhys = (RTHCPHYS)pauPFNs[0] << PAGE_SHIFT;
641 dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p *pHCPhys=%VHp\n",
642 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl, *pHCPhys));
643 return 0;
644 }
645 }
646 __except(EXCEPTION_EXECUTE_HANDLER)
647 {
648 NTSTATUS rc = GetExceptionCode();
649 dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
650 }
651 IoFreeMdl(pMem->u.cont.pMdl);
652 rc = SUPDRV_ERR_LOCK_FAILED;
653 }
654 MmFreeContiguousMemory(pMem->pvR0);
655 pMem->pvR0 = NULL;
656 return rc;
657}
658
659
660/**
661 * Frees contiguous memory.
662 *
663 * @param pMem Memory reference record of the memory to be freed.
664 */
665void VBOXCALL supdrvOSContFreeOne(PSUPDRVMEMREF pMem)
666{
667 __try
668 {
669 dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
670 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.cont.pMdl));
671 if (pMem->pvR3)
672 {
673 MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.cont.pMdl);
674 dprintf2(("MmUnmapLockedPages ok!\n"));
675 pMem->pvR3 = NULL;
676 }
677
678 IoFreeMdl(pMem->u.cont.pMdl);
679 dprintf2(("IoFreeMdl ok!\n"));
680 pMem->u.cont.pMdl = NULL;
681
682 MmFreeContiguousMemory(pMem->pvR0);
683 dprintf2(("MmFreeContiguousMemory ok!\n"));
684 pMem->pvR0 = NULL;
685 }
686 __except(EXCEPTION_EXECUTE_HANDLER)
687 {
688 NTSTATUS rc = GetExceptionCode();
689 dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
690 }
691}
692
693
694/**
695 * Allocates memory which mapped into both kernel and user space.
696 * The returned memory is page aligned and so is the allocation.
697 *
698 * @returns 0 on success.
699 * @returns SUPDRV_ERR_* on failure.
700 * @param pMem Memory reference record of the memory to be allocated.
701 * (This is not linked in anywhere.)
702 * @param ppvR0 Where to store the address of the Ring-0 mapping.
703 * @param ppvR3 Where to store the address of the Ring-3 mapping.
704 */
705int VBOXCALL supdrvOSMemAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3)
706{
707 Assert(ppvR0);
708 Assert(ppvR3);
709
710 /*
711 * Try allocate the memory.
712 */
713 unsigned cbAligned = RT_ALIGN(RT_MAX(pMem->cb, PAGE_SIZE * 2), PAGE_SIZE);
714 pMem->pvR0 = ExAllocatePoolWithTag(NonPagedPool, cbAligned, SUPDRV_NT_POOL_TAG);
715 if (!pMem->pvR0)
716 return SUPDRV_ERR_NO_MEMORY;
717
718 /*
719 * Map into user space.
720 */
721 int rc = SUPDRV_ERR_NO_MEMORY;
722 pMem->u.mem.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
723 if (pMem->u.mem.pMdl)
724 {
725 MmBuildMdlForNonPagedPool(pMem->u.mem.pMdl);
726 __try
727 {
728 pMem->pvR3 = (RTR3PTR)MmMapLockedPagesSpecifyCache(pMem->u.mem.pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
729 if (pMem->pvR3)
730 {
731 /*
732 * Done, setup pMem and return values.
733 */
734 *ppvR3 = pMem->pvR3;
735 *ppvR0 = pMem->pvR0;
736 dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
737 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
738 return 0;
739 }
740 }
741 __except(EXCEPTION_EXECUTE_HANDLER)
742 {
743 NTSTATUS rc = GetExceptionCode();
744 dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
745 }
746 rc = SUPDRV_ERR_LOCK_FAILED;
747
748 IoFreeMdl(pMem->u.mem.pMdl);
749 pMem->u.mem.pMdl = NULL;
750 pMem->pvR3 = NULL;
751 }
752
753 MmFreeContiguousMemory(pMem->pvR0);
754 pMem->pvR0 = NULL;
755 return rc;
756}
757
758
759/**
760 * Get the physical addresses of the pages in the allocation.
761 * This is called while inside bundle the spinlock.
762 *
763 * @param pMem Memory reference record of the memory.
764 * @param paPages Where to store the page addresses.
765 */
766void VBOXCALL supdrvOSMemGetPages(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
767{
768 const unsigned cPages = RT_ALIGN(pMem->cb, PAGE_SIZE) >> PAGE_SHIFT;
769 const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.mem.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK doesn't have ULONG_PTR. */
770 for (unsigned iPage = 0; iPage < cPages; iPage++)
771 {
772 paPages[iPage].Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
773 paPages[iPage].uReserved = 0;
774 }
775}
776
777
778/**
779 * Frees memory allocated by supdrvOSMemAllocOne().
780 *
781 * @param pMem Memory reference record of the memory to be free.
782 */
783void VBOXCALL supdrvOSMemFreeOne(PSUPDRVMEMREF pMem)
784{
785 __try
786 {
787 dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
788 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
789 if (pMem->pvR3)
790 {
791 MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.mem.pMdl);
792 pMem->pvR3 = NULL;
793 dprintf2(("MmUnmapLockedPages ok!\n"));
794 }
795
796 IoFreeMdl(pMem->u.mem.pMdl);
797 pMem->u.mem.pMdl = NULL;
798 dprintf2(("IoFreeMdl ok!\n"));
799
800 ExFreePool(pMem->pvR0);
801 pMem->pvR0 = NULL;
802 dprintf2(("MmFreeContiguousMemory ok!\n"));
803 }
804 __except(EXCEPTION_EXECUTE_HANDLER)
805 {
806 NTSTATUS rc = GetExceptionCode();
807 dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
808 }
809}
810
811#endif /* !USE_NEW_OS_INTERFACE_FOR_MM */
812
813
814/**
815 * Gets the monotone timestamp (nano seconds).
816 * @returns NanoTS.
817 */
818static inline uint64_t supdrvOSMonotime(void)
819{
820 return (uint64_t)KeQueryInterruptTime() * 100;
821}
822
823
824/**
825 * Initializes the GIP.
826 *
827 * @returns NT status code.
828 * @param pDevExt Instance data. GIP stuff may be updated.
829 */
830static NTSTATUS VBoxDrvNtGipInit(PSUPDRVDEVEXT pDevExt)
831{
832 dprintf2(("VBoxSupDrvTermGip:\n"));
833
834 /*
835 * Try allocate the memory.
836 * Make sure it's below 4GB for 32-bit GC support
837 */
838 NTSTATUS rc;
839 PHYSICAL_ADDRESS Phys;
840 Phys.HighPart = 0;
841 Phys.LowPart = ~0;
842 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)MmAllocateContiguousMemory(PAGE_SIZE, Phys);
843 if (pGip)
844 {
845 if (!((uintptr_t)pGip & (PAGE_SIZE - 1)))
846 {
847 pDevExt->pGipMdl = IoAllocateMdl(pGip, PAGE_SIZE, FALSE, FALSE, NULL);
848 if (pDevExt->pGipMdl)
849 {
850 MmBuildMdlForNonPagedPool(pDevExt->pGipMdl);
851
852 /*
853 * Figure the timer interval and frequency.
854 * It turns out trying 1023Hz doesn't work. So, we'll set the max Hz at 128 for now.
855 */
856 ExSetTimerResolution(156250, TRUE);
857 ULONG ulClockIntervalActual = ExSetTimerResolution(0, FALSE);
858 ULONG ulClockInterval = RT_MAX(ulClockIntervalActual, 78125); /* 1/128 */
859 ULONG ulClockFreq = 10000000 / ulClockInterval;
860 pDevExt->ulGipTimerInterval = ulClockInterval / 10000; /* ms */
861
862 /*
863 * Call common initialization routine.
864 */
865 Phys = MmGetPhysicalAddress(pGip); /* could perhaps use the Mdl, not that it looks much better */
866 supdrvGipInit(pDevExt, pGip, (RTHCPHYS)Phys.QuadPart, supdrvOSMonotime(), ulClockFreq);
867
868 /*
869 * Initialize the timer.
870 */
871 KeInitializeTimerEx(&pDevExt->GipTimer, SynchronizationTimer);
872 KeInitializeDpc(&pDevExt->GipDpc, VBoxDrvNtGipTimer, pDevExt);
873
874 /*
875 * Initialize the DPCs we're using to update the per-cpu GIP data.
876 * (Not sure if we need to be this careful with KeSetTargetProcessorDpc...)
877 */
878 UNICODE_STRING RoutineName;
879 RtlInitUnicodeString(&RoutineName, L"KeSetTargetProcessorDpc");
880 VOID (*pfnKeSetTargetProcessorDpc)(IN PRKDPC, IN CCHAR) = (VOID (*)(IN PRKDPC, IN CCHAR))MmGetSystemRoutineAddress(&RoutineName);
881
882 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
883 {
884 KeInitializeDpc(&pDevExt->aGipCpuDpcs[i], VBoxDrvNtGipPerCpuDpc, pGip);
885 KeSetImportanceDpc(&pDevExt->aGipCpuDpcs[i], HighImportance);
886 if (pfnKeSetTargetProcessorDpc)
887 pfnKeSetTargetProcessorDpc(&pDevExt->aGipCpuDpcs[i], i);
888 }
889
890 dprintf(("VBoxDrvNtGipInit: ulClockFreq=%ld ulClockInterval=%ld ulClockIntervalActual=%ld Phys=%x%08x\n",
891 ulClockFreq, ulClockInterval, ulClockIntervalActual, Phys.HighPart, Phys.LowPart));
892 return STATUS_SUCCESS;
893 }
894
895 dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip));
896 rc = STATUS_NO_MEMORY;
897 }
898 else
899 {
900 dprintf(("VBoxSupDrvInitGip: GIP memory is not page aligned! pGip=%p\n", pGip));
901 rc = STATUS_INVALID_ADDRESS;
902 }
903 MmFreeContiguousMemory(pGip);
904 }
905 else
906 {
907 dprintf(("VBoxSupDrvInitGip: no cont memory.\n"));
908 rc = STATUS_NO_MEMORY;
909 }
910 return rc;
911}
912
913
914/**
915 * Terminates the GIP.
916 *
917 * @returns negative errno.
918 * @param pDevExt Instance data. GIP stuff may be updated.
919 */
920static void VBoxDrvNtGipTerm(PSUPDRVDEVEXT pDevExt)
921{
922 dprintf(("VBoxSupDrvTermGip:\n"));
923 PSUPGLOBALINFOPAGE pGip;
924
925 /*
926 * Cancel the timer and wait on DPCs if it was still pending.
927 */
928 if (KeCancelTimer(&pDevExt->GipTimer))
929 {
930 UNICODE_STRING RoutineName;
931 RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
932 VOID (*pfnKeFlushQueuedDpcs)(VOID) = (VOID (*)(VOID))MmGetSystemRoutineAddress(&RoutineName);
933 if (pfnKeFlushQueuedDpcs)
934 pfnKeFlushQueuedDpcs();
935 }
936
937 /*
938 * Uninitialize the content.
939 */
940 pGip = pDevExt->pGip;
941 pDevExt->pGip = NULL;
942 if (pGip)
943 {
944 supdrvGipTerm(pGip);
945
946 /*
947 * Free the page.
948 */
949 if (pDevExt->pGipMdl)
950 {
951 IoFreeMdl(pDevExt->pGipMdl);
952 pDevExt->pGipMdl = NULL;
953 }
954 MmFreeContiguousMemory(pGip);
955 }
956}
957
958
959/**
960 * Timer callback function.
961 * The pvUser parameter is the pDevExt pointer.
962 */
963static void _stdcall VBoxDrvNtGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
964{
965 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser;
966 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
967 if (pGip)
968 {
969 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
970 supdrvGipUpdate(pGip, supdrvOSMonotime());
971 else
972 {
973 RTCCUINTREG xFL = ASMGetFlags();
974 ASMIntDisable();
975
976 /*
977 * We cannot do other than assume a 1:1 relation ship between the
978 * affinity mask and the process despite the warnings in the docs.
979 * If someone knows a better way to get this done, please let bird know.
980 */
981 unsigned iSelf = KeGetCurrentProcessorNumber();
982 KAFFINITY Mask = KeQueryActiveProcessors();
983
984 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
985 {
986 if ( i != iSelf
987 && (Mask & RT_BIT_64(i)))
988 KeInsertQueueDpc(&pDevExt->aGipCpuDpcs[i], 0, 0);
989 }
990
991 /* Run the normal update. */
992 supdrvGipUpdate(pGip, supdrvOSMonotime());
993
994 ASMSetFlags(xFL);
995 }
996 }
997}
998
999
1000/**
1001 * Per cpu callback callback function.
1002 * The pvUser parameter is the pGip pointer.
1003 */
1004static void _stdcall VBoxDrvNtGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
1005{
1006 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser;
1007 supdrvGipUpdatePerCpu(pGip, supdrvOSMonotime(), ASMGetApicId());
1008}
1009
1010
1011/**
1012 * Maps the GIP into user space.
1013 *
1014 * @returns negative errno.
1015 * @param pDevExt Instance data.
1016 */
1017int VBOXCALL supdrvOSGipMap(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE *ppGip)
1018{
1019 dprintf2(("supdrvOSGipMap: ppGip=%p (pDevExt->pGipMdl=%p)\n", ppGip, pDevExt->pGipMdl));
1020
1021 /*
1022 * Map into user space.
1023 */
1024 int rc = 0;
1025 void *pv = NULL;
1026 __try
1027 {
1028 *ppGip = (PSUPGLOBALINFOPAGE)MmMapLockedPagesSpecifyCache(pDevExt->pGipMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
1029 }
1030 __except(EXCEPTION_EXECUTE_HANDLER)
1031 {
1032 NTSTATUS rcNt = GetExceptionCode();
1033 dprintf(("supdrvOsGipMap: Exception Code %#x\n", rcNt));
1034 rc = SUPDRV_ERR_LOCK_FAILED;
1035 }
1036
1037 dprintf2(("supdrvOSGipMap: returns %d, *ppGip=%p\n", rc, *ppGip));
1038 return 0;
1039}
1040
1041
1042/**
1043 * Maps the GIP into user space.
1044 *
1045 * @returns negative errno.
1046 * @param pDevExt Instance data.
1047 */
1048int VBOXCALL supdrvOSGipUnmap(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip)
1049{
1050 dprintf2(("supdrvOSGipUnmap: pGip=%p (pGipMdl=%p)\n", pGip, pDevExt->pGipMdl));
1051
1052 int rc = 0;
1053 __try
1054 {
1055 MmUnmapLockedPages((void *)pGip, pDevExt->pGipMdl);
1056 }
1057 __except(EXCEPTION_EXECUTE_HANDLER)
1058 {
1059 NTSTATUS rcNt = GetExceptionCode();
1060 dprintf(("supdrvOSGipUnmap: Exception Code %#x\n", rcNt));
1061 rc = SUPDRV_ERR_GENERAL_FAILURE;
1062 }
1063 dprintf2(("supdrvOSGipUnmap: returns %d\n", rc));
1064 return rc;
1065}
1066
1067
1068/**
1069 * Resumes the GIP updating.
1070 *
1071 * @param pDevExt Instance data.
1072 */
1073void VBOXCALL supdrvOSGipResume(PSUPDRVDEVEXT pDevExt)
1074{
1075 dprintf2(("supdrvOSGipResume:\n"));
1076 LARGE_INTEGER DueTime;
1077 DueTime.QuadPart = -10000; /* 1ms, relative */
1078 KeSetTimerEx(&pDevExt->GipTimer, DueTime, pDevExt->ulGipTimerInterval, &pDevExt->GipDpc);
1079}
1080
1081
1082/**
1083 * Suspends the GIP updating.
1084 *
1085 * @param pDevExt Instance data.
1086 */
1087void VBOXCALL supdrvOSGipSuspend(PSUPDRVDEVEXT pDevExt)
1088{
1089 dprintf2(("supdrvOSGipSuspend:\n"));
1090 KeCancelTimer(&pDevExt->GipTimer);
1091#ifdef RT_ARCH_AMD64
1092 ExSetTimerResolution(0, FALSE);
1093#endif
1094}
1095
1096
1097#ifndef USE_NEW_OS_INTERFACE_FOR_MM
1098
1099/**
1100 * Allocate small amounts of memory which is does not have the NX bit set.
1101 *
1102 * @returns Pointer to the allocated memory
1103 * @returns NULL if out of memory.
1104 * @param cb Size of the memory block.
1105 */
1106void *VBOXCALL supdrvOSExecAlloc(size_t cb)
1107{
1108#if 0 //def RT_ARCH_AMD64
1109 cb = RT_ALIGN_Z(cb, PAGE_SIZE);
1110 void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
1111 if (pv)
1112 {
1113 /*
1114 * Create a kernel mapping which we make PAGE_EXECUTE_READWRITE using
1115 * the MmProtectMdlSystemAddress API.
1116 */
1117 int rc = SUPDRV_ERR_NO_MEMORY;
1118 PMDL pMdl = IoAllocateMdl(pv, cb, FALSE, FALSE, NULL);
1119 if (pMdl)
1120 {
1121 MmBuildMdlForNonPagedPool(pMdl);
1122 __try
1123 {
1124 void *pvMapping = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
1125 if (pvMapping)
1126 {
1127 NTSTATUS rc = MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
1128 if (NT_SUCCESS(rc))
1129 {
1130 /*
1131 * Create tracking structure and insert it into the list.
1132 */
1133
1134
1135 return pvMapping;
1136 }
1137
1138 MmUnmapLockedPages(pvMapping, pMdl);
1139 }
1140 }
1141 __except(EXCEPTION_EXECUTE_HANDLER)
1142 {
1143 NTSTATUS rc = GetExceptionCode();
1144 dprintf(("supdrvOSExecAlloc: Exception Code %#x\n", rc));
1145 }
1146 IoFreeMdl(pMem->u.mem.pMdl);
1147 }
1148 ExFreePool(pv);
1149 }
1150 dprintf2(("supdrvOSExecAlloc(%d): returns NULL\n", cb));
1151 return NULL;
1152#else
1153 void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
1154 dprintf2(("supdrvOSExecAlloc(%d): returns %p\n", cb, pv));
1155 return pv;
1156#endif
1157}
1158
1159#endif /* !USE_NEW_OS_INTERFACE_FOR_MM */
1160
1161
1162/**
1163 * Get the current CPU count.
1164 * @returns Number of cpus.
1165 */
1166unsigned VBOXCALL supdrvOSGetCPUCount(void)
1167{
1168 KAFFINITY Mask = KeQueryActiveProcessors();
1169 unsigned cCpus = 0;
1170 unsigned iBit;
1171 for (iBit = 0; iBit < sizeof(Mask) * 8; iBit++)
1172 if (Mask & RT_BIT_64(iBit))
1173 cCpus++;
1174 if (cCpus == 0) /* paranoia */
1175 cCpus = 1;
1176 return cCpus;
1177}
1178
1179
1180/**
1181 * Force async tsc mode (stub).
1182 */
1183bool VBOXCALL supdrvOSGetForcedAsyncTscMode(void)
1184{
1185 return false;
1186}
1187
1188
1189/**
1190 * Converts a supdrv error code to an nt status code.
1191 *
1192 * @returns corresponding nt status code.
1193 * @param rc supdrv error code (SUPDRV_ERR_* defines).
1194 */
1195static NTSTATUS VBoxDrvNtErr2NtStatus(int rc)
1196{
1197 switch (rc)
1198 {
1199 case 0: return STATUS_SUCCESS;
1200 case SUPDRV_ERR_GENERAL_FAILURE: return STATUS_NOT_SUPPORTED;
1201 case SUPDRV_ERR_INVALID_PARAM: return STATUS_INVALID_PARAMETER;
1202 case SUPDRV_ERR_INVALID_MAGIC: return STATUS_UNKNOWN_REVISION;
1203 case SUPDRV_ERR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
1204 case SUPDRV_ERR_INVALID_POINTER: return STATUS_INVALID_ADDRESS;
1205 case SUPDRV_ERR_LOCK_FAILED: return STATUS_NOT_LOCKED;
1206 case SUPDRV_ERR_ALREADY_LOADED: return STATUS_IMAGE_ALREADY_LOADED;
1207 case SUPDRV_ERR_PERMISSION_DENIED: return STATUS_ACCESS_DENIED;
1208 case SUPDRV_ERR_VERSION_MISMATCH: return STATUS_REVISION_MISMATCH;
1209 }
1210
1211 return STATUS_UNSUCCESSFUL;
1212}
1213
1214
1215/** Runtime assert implementation for Native Win32 Ring-0. */
1216RTDECL(void) AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
1217{
1218 DbgPrint("\n!!Assertion Failed!!\n"
1219 "Expression: %s\n"
1220 "Location : %s(%d) %s\n",
1221 pszExpr, pszFile, uLine, pszFunction);
1222}
1223
1224int VBOXCALL mymemcmp(const void *pv1, const void *pv2, size_t cb)
1225{
1226 const uint8_t *pb1 = (const uint8_t *)pv1;
1227 const uint8_t *pb2 = (const uint8_t *)pv2;
1228 for (; cb > 0; cb--, pb1++, pb2++)
1229 if (*pb1 != *pb2)
1230 return *pb1 - *pb2;
1231 return 0;
1232}
1233
Note: See TracBrowser for help on using the repository browser.

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