SUPDrv-win.cpp revision 95e8e91bf4a392b957a78ffc430bda448b95de4e
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/* $Id$ */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** @file
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox Support Driver - Windows NT specific parts.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync/*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2006-2007 innotek GmbH
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License as published by the Free Software Foundation,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Header Files *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include "SUPDRV.h"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <excpt.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/assert.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/process.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Defined Constants And Macros *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The support service name. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define SERVICE_NAME "VBoxDrv"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** Win32 Device name. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define DEVICE_NAME "\\\\.\\VBoxDrv"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** NT Device name. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define DEVICE_NAME_NT L"\\Device\\VBoxDrv"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** Win Symlink name. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define DEVICE_NAME_DOS L"\\DosDevices\\VBoxDrv"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The Pool tag (VBox). */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define SUPDRV_NT_POOL_TAG 'xoBV'
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Structures and Typedefs *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#if 0 //def RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsynctypedef struct SUPDRVEXECMEM
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PMDL pMdl;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pvMapping;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pvAllocation;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync} SUPDRVEXECMEM, *PSUPDRVEXECMEM;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Internal Functions *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void _stdcall VBoxSupDrvUnload(PDRIVER_OBJECT pDrvObj);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS _stdcall VBoxSupDrvCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS _stdcall VBoxSupDrvClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS _stdcall VBoxSupDrvDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic int VBoxSupDrvDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS _stdcall VBoxSupDrvNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS VBoxSupDrvErr2NtStatus(int rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS VBoxSupDrvGipInit(PSUPDRVDEVEXT pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Exported Functions *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync__BEGIN_DECLS
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync__END_DECLS
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Driver entry point.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns appropriate status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDrvObj Pointer to driver object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pRegPath Registry base path.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxDrv::DriverEntry\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Create device.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (That means creating a device object and a symbolic link so the DOS
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * subsystems (OS/2, win32, ++) can access the device.)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync UNICODE_STRING DevName;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RtlInitUnicodeString(&DevName, DEVICE_NAME_NT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PDEVICE_OBJECT pDevObj;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync rc = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync if (NT_SUCCESS(rc))
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync {
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync UNICODE_STRING DosName;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = IoCreateSymbolicLink(&DosName, &DevName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (NT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Initialize the device extension.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync memset(pDevExt, 0, sizeof(*pDevExt));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int vrc = supdrvInitDevExt(pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!vrc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Inititalize the GIP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = VBoxSupDrvGipInit(pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (NT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Setup the driver entry points in pDrvObj.
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync pDrvObj->DriverUnload = VBoxSupDrvUnload;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxSupDrvCreate;
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxSupDrvClose;
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxSupDrvDeviceControl;
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxSupDrvNotSupportedStub;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxSupDrvNotSupportedStub;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* more? */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvGipInit failed with rc=%#x!\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvDeleteDevExt(pDevExt);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync }
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = VBoxSupDrvErr2NtStatus(vrc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoDeleteSymbolicLink(&DosName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("IoCreateSymbolicLink failed with rc=%#x!\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync IoDeleteDevice(pDevObj);
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("IoCreateDevice failed with rc=%#x!\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (NT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = STATUS_INVALID_PARAMETER;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxDrv::DriverEntry returning %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * Unload the driver.
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDrvObj Driver object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid _stdcall VBoxSupDrvUnload(PDRIVER_OBJECT pDrvObj)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvUnload\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDrvObj->DeviceObject->DeviceExtension;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * We ASSUME that it's not possible to unload a driver with open handles.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Start by deleting the symbolic link
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync UNICODE_STRING DosName;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Terminate the GIP page and delete the device extension.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync VBoxSupDrvGipTerm(pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvDeleteDevExt(pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoDeleteDevice(pDrvObj->DeviceObject);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Create (i.e. Open) file entry point.
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync *
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync * @param pDevObj Device object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pIrp Request packet.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncNTSTATUS _stdcall VBoxSupDrvCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvCreate\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * We are not remotely similar to a directory...
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (But this is possible.)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Information = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync return STATUS_NOT_A_DIRECTORY;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Call common code for the rest.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pFileObj->FsContext = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVSESSION pSession;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = supdrvCreateSession(pDevExt, &pSession);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!rc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pSession->Uid = NIL_RTUID;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pSession->Gid = NIL_RTGID;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pSession->Process = RTProcSelf();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pSession->R0Process = RTR0ProcHandleSelf();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pFileObj->FsContext = pSession;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rcNt = pIrp->IoStatus.Status = VBoxSupDrvErr2NtStatus(rc);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync pIrp->IoStatus.Information = 0;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rcNt;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Close file entry point.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevObj Device object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pIrp Request packet.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncNTSTATUS _stdcall VBoxSupDrvClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync{
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvClose: pDevExt=%p pFileObj=%p pSession=%p\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevExt, pFileObj, pFileObj->FsContext));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvCloseSession(pDevExt, (PSUPDRVSESSION)pFileObj->FsContext);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pFileObj->FsContext = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Information = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Device I/O Control entry point.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevObj Device object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pIrp Request packet.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncNTSTATUS _stdcall VBoxSupDrvDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVSESSION pSession = (PSUPDRVSESSION)pStack->FileObject->FsContext;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifdef VBOX_WITHOUT_IDT_PATCHING
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Deal with the two high-speed IOCtl that takes it's arguments from
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * the session and iCmd, and only returns a VBox status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if ( ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync || ulCmd == SUP_IOCTL_FAST_DO_HWACC_RUN
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync || ulCmd == SUP_IOCTL_FAST_DO_NOP)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = supdrvIOCtlFast(ulCmd, pDevExt, pSession);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* Complete the I/O request. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rcNt = pIrp->IoStatus.Status = STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Information = sizeof(rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *(int *)pIrp->UserBuffer = rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcNt = pIrp->IoStatus.Status = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvDeviceContorl: Exception Code %#x\n", rcNt));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rcNt;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif /* VBOX_WITHOUT_IDT_PATCHING */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync return VBoxSupDrvDeviceControlSlow(pDevExt, pSession, pIrp, pStack);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync * Worker for VBoxSupDrvDeviceControl that takes the slow IOCtl functions.
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns NT status code.
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync *
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * @param pDevObj Device object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pSession The session.
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * @param pIrp Request packet.
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * @param pStack The stack location containing the DeviceControl parameters.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsyncstatic int VBoxSupDrvDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack)
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rcNt = STATUS_NOT_SUPPORTED;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync unsigned cbOut = 0;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync int rc = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("VBoxSupDrvDeviceControlSlow(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n",
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync pDevObj, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode,
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync pBuf, pStack->Parameters.DeviceIoControl.InputBufferLength,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession));
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync#ifdef RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* Don't allow 32-bit processes to do any I/O controls. */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync if (!IoIs32bitProcess(pIrp))
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync#endif
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /* Verify that it's a buffered CTL. */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Do the job.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = supdrvIOCtl(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pBuf, pStack->Parameters.DeviceIoControl.InputBufferLength,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pBuf, pStack->Parameters.DeviceIoControl.OutputBufferLength,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync &cbOut);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcNt = VBoxSupDrvErr2NtStatus(rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* sanity check. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsg(cbOut <= pStack->Parameters.DeviceIoControl.OutputBufferLength,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ("cbOut is too large! cbOut=%d max=%d! ioctl=%#x\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cbOut, pStack->Parameters.DeviceIoControl.OutputBufferLength,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pStack->Parameters.DeviceIoControl.IoControlCode));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (cbOut > pStack->Parameters.DeviceIoControl.OutputBufferLength)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("VBoxSupDrvDeviceControlSlow: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvDeviceControlSlow: not buffered request (%#x) - not supported\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pStack->Parameters.DeviceIoControl.IoControlCode));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifdef RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvDeviceControlSlow: WOW64 req - not supported\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* complete the request. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Status = rcNt;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Information = NT_SUCCESS(rcNt) ? cbOut : rc; /* does this rc passing actually work?!? */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rcNt;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Stub function for functions we don't implemented.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns STATUS_NOT_SUPPORTED
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevObj Device object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pIrp IRP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncNTSTATUS _stdcall VBoxSupDrvNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvNotSupportedStub\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevObj = pDevObj;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Information = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return STATUS_NOT_SUPPORTED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Initializes any OS specific object creator fields.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(pObj);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(pSession);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Checks if the session can access the object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns true if a decision has been made.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns false if the default access policy should be applied.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pObj The object in question.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pSession The session wanting to access the object.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pszObjName The object name, can be NULL.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param prc Where to store the result when returning true.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncbool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(pObj);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(pSession);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(pszObjName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NOREF(prc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return false;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifndef USE_NEW_OS_INTERFACE_FOR_MM
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * OS Specific code for locking down memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns 0 on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns SUPDRV_ERR_* on failure.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Pointer to memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This is not linked in anywhere.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param paPages Array which should be filled with the address of the physical pages.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL supdrvOSLockMemOne(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* paranoia */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!pMem->cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailed(("Fool! No memory to lock!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_INVALID_PARAM;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(RT_ALIGN(pMem->cb, PAGE_SIZE) == pMem->cb);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Calc the number of MDLs we need to allocate.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cMdls = pMem->cb / MAX_LOCK_MEM_SIZE;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if ((pMem->cb % MAX_LOCK_MEM_SIZE) > 0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cMdls++;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Allocate memory for the MDL pointer array.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.locked.papMdl = (PMDL *)ExAllocatePoolWithTag(NonPagedPool, sizeof(*pMem->u.locked.papMdl) * cMdls, SUPDRV_NT_POOL_TAG);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!pMem->u.locked.papMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailed(("shit, couldn't allocated %d bytes for the mdl pointer array!\n", sizeof(*pMem->u.locked.papMdl) * cMdls));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Loop locking down the sub parts of the memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPPAGE pPage = paPages;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cbTotal = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t *pu8 = (uint8_t *)pMem->pvR3;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0; i < cMdls; i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Calc the number of bytes to lock this time.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cbCur = pMem->cb - cbTotal;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (cbCur > MAX_LOCK_MEM_SIZE)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cbCur = MAX_LOCK_MEM_SIZE;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (cbCur == 0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailed(("cbCur: 0!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Allocate pMdl.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PMDL pMdl = IoAllocateMdl(pu8, cbCur, FALSE, FALSE, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!pMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailed(("Ops! IoAllocateMdl failed for pu8=%p and cb=%d\n", pu8, cbCur));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Lock the pages.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmProbeAndLockPages(pMdl, UserMode, IoModifyAccess);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSLockMemOne: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!NT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Cleanup and fail.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync while (i-- > 0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnlockPages(pMem->u.locked.papMdl[i]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.locked.papMdl[i]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ExFreePool(pMem->u.locked.papMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.locked.papMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_LOCK_FAILED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Add MDL to array and update the pages.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.locked.papMdl[i] = pMdl;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uintptr_t *pauPFNs = (uintptr_t *)(pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned iPage = 0, cPages = cbCur >> PAGE_SHIFT; iPage < cPages; iPage++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pPage->Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pPage->uReserved = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pPage++;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* next */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cbTotal += cbCur;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pu8 += cbCur;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Finish structure and return succesfully.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.locked.cMdls = cMdls;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSLockMemOne: pvR3=%p cb=%d cMdls=%d\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3, pMem->cb, cMdls));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Unlocks the memory pointed to by pv.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pv Memory to unlock.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param cb Size of the memory (debug).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSUnlockMemOne(PSUPDRVMEMREF pMem)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSUnlockMemOne: pvR3=%p cb=%d cMdl=%p papMdl=%p\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3, pMem->cb, pMem->u.locked.cMdls, pMem->u.locked.papMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0; i < pMem->u.locked.cMdls; i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnlockPages(pMem->u.locked.papMdl[i]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.locked.papMdl[i]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ExFreePool(pMem->u.locked.papMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.locked.papMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * OS Specific code for allocating page aligned memory with continuous fixed
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * physical paged backing.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns 0 on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns SUPDRV_ERR_* on failure.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Memory reference record of the memory to be allocated.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (This is not linked in anywhere.)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param ppvR0 Where to store the virtual address of the ring-0 mapping. (optional)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param ppvR3 Where to store the virtual address of the ring-3 mapping.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pHCPhys Where to store the physical address.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL supdrvOSContAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(ppvR3);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(pHCPhys);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Try allocate the memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PHYSICAL_ADDRESS Phys;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Phys.HighPart = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Phys.LowPart = ~0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cbAligned = RT_ALIGN(pMem->cb, PAGE_SIZE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = MmAllocateContiguousMemory(cbAligned, Phys);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!pMem->pvR0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Map into user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.cont.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->u.cont.pMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmBuildMdlForNonPagedPool(pMem->u.cont.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3 = (RTR3PTR)MmMapLockedPagesSpecifyCache(pMem->u.cont.pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->pvR3)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Done, setup pMem and return values.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifdef RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmProtectMdlSystemAddress(pMem->u.cont.pMdl, PAGE_EXECUTE_READWRITE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *ppvR3 = pMem->pvR3;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (ppvR0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *ppvR0 = pMem->pvR0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.cont.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pHCPhys = (RTHCPHYS)pauPFNs[0] << PAGE_SHIFT;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p *pHCPhys=%VHp\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl, *pHCPhys));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.cont.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = SUPDRV_ERR_LOCK_FAILED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmFreeContiguousMemory(pMem->pvR0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Frees contiguous memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Memory reference record of the memory to be freed.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSContFreeOne(PSUPDRVMEMREF pMem)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.cont.pMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->pvR3)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.cont.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("MmUnmapLockedPages ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.cont.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("IoFreeMdl ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.cont.pMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmFreeContiguousMemory(pMem->pvR0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("MmFreeContiguousMemory ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Allocates memory which mapped into both kernel and user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The returned memory is page aligned and so is the allocation.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns 0 on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns SUPDRV_ERR_* on failure.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Memory reference record of the memory to be allocated.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (This is not linked in anywhere.)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param ppvR0 Where to store the address of the Ring-0 mapping.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param ppvR3 Where to store the address of the Ring-3 mapping.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL supdrvOSMemAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(ppvR0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(ppvR3);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Try allocate the memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cbAligned = RT_ALIGN(RT_MAX(pMem->cb, PAGE_SIZE * 2), PAGE_SIZE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = ExAllocatePoolWithTag(NonPagedPool, cbAligned, SUPDRV_NT_POOL_TAG);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!pMem->pvR0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Map into user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.mem.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->u.mem.pMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmBuildMdlForNonPagedPool(pMem->u.mem.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3 = (RTR3PTR)MmMapLockedPagesSpecifyCache(pMem->u.mem.pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->pvR3)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Done, setup pMem and return values.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *ppvR3 = pMem->pvR3;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *ppvR0 = pMem->pvR0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = SUPDRV_ERR_LOCK_FAILED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.mem.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.mem.pMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmFreeContiguousMemory(pMem->pvR0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Get the physical addresses of the pages in the allocation.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This is called while inside bundle the spinlock.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Memory reference record of the memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param paPages Where to store the page addresses.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSMemGetPages(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const unsigned cPages = RT_ALIGN(pMem->cb, PAGE_SIZE) >> PAGE_SHIFT;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.mem.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK doesn't have ULONG_PTR. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned iPage = 0; iPage < cPages; iPage++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync paPages[iPage].Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync paPages[iPage].uReserved = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Frees memory allocated by supdrvOSMemAllocOne().
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pMem Memory reference record of the memory to be free.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSMemFreeOne(PSUPDRVMEMREF pMem)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMem->pvR3)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.mem.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR3 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("MmUnmapLockedPages ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.mem.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->u.mem.pMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("IoFreeMdl ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ExFreePool(pMem->pvR0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pMem->pvR0 = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("MmFreeContiguousMemory ok!\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif /* !USE_NEW_OS_INTERFACE_FOR_MM */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Gets the monotone timestamp (nano seconds).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns NanoTS.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic inline uint64_t supdrvOSMonotime(void)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (uint64_t)KeQueryInterruptTime() * 100;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Initializes the GIP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns NT status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data. GIP stuff may be updated.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS VBoxSupDrvGipInit(PSUPDRVDEVEXT pDevExt)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("VBoxSupDrvTermGip:\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Try allocate the memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Make sure it's below 4GB for 32-bit GC support
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PHYSICAL_ADDRESS Phys;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Phys.HighPart = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Phys.LowPart = ~0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)MmAllocateContiguousMemory(PAGE_SIZE, Phys);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pGip)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!((uintptr_t)pGip & (PAGE_SIZE - 1)))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevExt->pGipMdl = IoAllocateMdl(pGip, PAGE_SIZE, FALSE, FALSE, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pDevExt->pGipMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmBuildMdlForNonPagedPool(pDevExt->pGipMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Figure the timer interval and frequency.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * It turns out trying 1023Hz doesn't work. So, we'll set the max Hz at 128 for now.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ExSetTimerResolution(156250, TRUE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ULONG ulClockIntervalActual = ExSetTimerResolution(0, FALSE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ULONG ulClockInterval = RT_MAX(ulClockIntervalActual, 78125); /* 1/128 */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ULONG ulClockFreq = 10000000 / ulClockInterval;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevExt->ulGipTimerInterval = ulClockInterval / 10000; /* ms */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Call common initialization routine.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Phys = MmGetPhysicalAddress(pGip); /* could perhaps use the Mdl, not that it looks much better */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvGipInit(pDevExt, pGip, (RTHCPHYS)Phys.QuadPart, supdrvOSMonotime(), ulClockFreq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Initialize the timer.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeInitializeTimerEx(&pDevExt->GipTimer, SynchronizationTimer);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pDevExt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Initialize the DPCs we're using to update the per-cpu GIP data.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (Not sure if we need to be this careful with KeSetTargetProcessorDpc...)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync UNICODE_STRING RoutineName;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RtlInitUnicodeString(&RoutineName, L"KeSetTargetProcessorDpc");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync VOID (*pfnKeSetTargetProcessorDpc)(IN PRKDPC, IN CCHAR) = (VOID (*)(IN PRKDPC, IN CCHAR))MmGetSystemRoutineAddress(&RoutineName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeInitializeDpc(&pDevExt->aGipCpuDpcs[i], VBoxSupDrvGipPerCpuDpc, pGip);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeSetImportanceDpc(&pDevExt->aGipCpuDpcs[i], HighImportance);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pfnKeSetTargetProcessorDpc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pfnKeSetTargetProcessorDpc(&pDevExt->aGipCpuDpcs[i], i);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvGipInit: ulClockFreq=%ld ulClockInterval=%ld ulClockIntervalActual=%ld Phys=%x%08x\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ulClockFreq, ulClockInterval, ulClockIntervalActual, Phys.HighPart, Phys.LowPart));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = STATUS_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvInitGip: GIP memory is not page aligned! pGip=%p\n", pGip));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = STATUS_INVALID_ADDRESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmFreeContiguousMemory(pGip);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvInitGip: no cont memory.\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = STATUS_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Terminates the GIP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns negative errno.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data. GIP stuff may be updated.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("VBoxSupDrvTermGip:\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPGLOBALINFOPAGE pGip;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Cancel the timer and wait on DPCs if it was still pending.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (KeCancelTimer(&pDevExt->GipTimer))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync UNICODE_STRING RoutineName;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync VOID (*pfnKeFlushQueuedDpcs)(VOID) = (VOID (*)(VOID))MmGetSystemRoutineAddress(&RoutineName);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pfnKeFlushQueuedDpcs)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pfnKeFlushQueuedDpcs();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Uninitialize the content.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pGip = pDevExt->pGip;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevExt->pGip = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pGip)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvGipTerm(pGip);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Free the page.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pDevExt->pGipMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pDevExt->pGipMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pDevExt->pGipMdl = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmFreeContiguousMemory(pGip);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Timer callback function.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The pvUser parameter is the pDevExt pointer.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pGip)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvGipUpdate(pGip, supdrvOSMonotime());
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTCCUINTREG xFL = ASMGetFlags();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ASMIntDisable();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * We cannot do other than assume a 1:1 relation ship between the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * affinity mask and the process despite the warnings in the docs.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * If someone knows a better way to get this done, please let bird know.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned iSelf = KeGetCurrentProcessorNumber();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KAFFINITY Mask = KeQueryActiveProcessors();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if ( i != iSelf
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync && (Mask & RT_BIT_64(i)))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeInsertQueueDpc(&pDevExt->aGipCpuDpcs[i], 0, 0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* Run the normal update. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvGipUpdate(pGip, supdrvOSMonotime());
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ASMSetFlags(xFL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Per cpu callback callback function.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The pvUser parameter is the pGip pointer.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync supdrvGipUpdatePerCpu(pGip, supdrvOSMonotime(), ASMGetApicId());
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Maps the GIP into user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns negative errno.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL supdrvOSGipMap(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE *ppGip)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipMap: ppGip=%p (pDevExt->pGipMdl=%p)\n", ppGip, pDevExt->pGipMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Map into user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pv = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *ppGip = (PSUPGLOBALINFOPAGE)MmMapLockedPagesSpecifyCache(pDevExt->pGipMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rcNt = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOsGipMap: Exception Code %#x\n", rcNt));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = SUPDRV_ERR_LOCK_FAILED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipMap: returns %d, *ppGip=%p\n", rc, *ppGip));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Maps the GIP into user space.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns negative errno.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL supdrvOSGipUnmap(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipUnmap: pGip=%p (pGipMdl=%p)\n", pGip, pDevExt->pGipMdl));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnmapLockedPages((void *)pGip, pDevExt->pGipMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rcNt = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSGipUnmap: Exception Code %#x\n", rcNt));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = SUPDRV_ERR_GENERAL_FAILURE;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipUnmap: returns %d\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Resumes the GIP updating.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSGipResume(PSUPDRVDEVEXT pDevExt)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipResume:\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync LARGE_INTEGER DueTime;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync DueTime.QuadPart = -10000; /* 1ms, relative */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeSetTimerEx(&pDevExt->GipTimer, DueTime, pDevExt->ulGipTimerInterval, &pDevExt->GipDpc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Suspends the GIP updating.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pDevExt Instance data.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid VBOXCALL supdrvOSGipSuspend(PSUPDRVDEVEXT pDevExt)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSGipSuspend:\n"));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync KeCancelTimer(&pDevExt->GipTimer);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifdef RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ExSetTimerResolution(0, FALSE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#ifndef USE_NEW_OS_INTERFACE_FOR_MM
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Allocate small amounts of memory which is does not have the NX bit set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns Pointer to the allocated memory
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns NULL if out of memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param cb Size of the memory block.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid *VBOXCALL supdrvOSExecAlloc(size_t cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#if 0 //def RT_ARCH_AMD64
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pv)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Create a kernel mapping which we make PAGE_EXECUTE_READWRITE using
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * the MmProtectMdlSystemAddress API.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = SUPDRV_ERR_NO_MEMORY;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PMDL pMdl = IoAllocateMdl(pv, cb, FALSE, FALSE, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pMdl)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmBuildMdlForNonPagedPool(pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __try
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pvMapping = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pvMapping)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync NTSTATUS rc = MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (NT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Create tracking structure and insert it into the list.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return pvMapping;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync MmUnmapLockedPages(pvMapping, pMdl);
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync }
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync }
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync {
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync NTSTATUS rc = GetExceptionCode();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf(("supdrvOSExecAlloc: Exception Code %#x\n", rc));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync IoFreeMdl(pMem->u.mem.pMdl);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync ExFreePool(pv);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync dprintf2(("supdrvOSExecAlloc(%d): returns NULL\n", cb));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync dprintf2(("supdrvOSExecAlloc(%d): returns %p\n", cb, pv));
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync return pv;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync#endif
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#endif /* !USE_NEW_OS_INTERFACE_FOR_MM */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Get the current CPU count.
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync * @returns Number of cpus.
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync */
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsyncunsigned VBOXCALL supdrvOSGetCPUCount(void)
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync{
1167f682bad8a5c086022e181da3bb4028a20ff8vboxsync KAFFINITY Mask = KeQueryActiveProcessors();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned cCpus = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync unsigned iBit;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (iBit = 0; iBit < sizeof(Mask) * 8; iBit++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (Mask & RT_BIT_64(iBit))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cCpus++;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (cCpus == 0) /* paranoia */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cCpus = 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return cCpus;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Force async tsc mode (stub).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncbool VBOXCALL supdrvOSGetForcedAsyncTscMode(void)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return false;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Converts a supdrv error code to an nt status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns corresponding nt status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param rc supdrv error code (SUPDRV_ERR_* defines).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic NTSTATUS VBoxSupDrvErr2NtStatus(int rc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync switch (rc)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0: return STATUS_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_GENERAL_FAILURE: return STATUS_NOT_SUPPORTED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_INVALID_PARAM: return STATUS_INVALID_PARAMETER;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_INVALID_MAGIC: return STATUS_UNKNOWN_REVISION;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_INVALID_POINTER: return STATUS_INVALID_ADDRESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_LOCK_FAILED: return STATUS_NOT_LOCKED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_ALREADY_LOADED: return STATUS_IMAGE_ALREADY_LOADED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_PERMISSION_DENIED: return STATUS_ACCESS_DENIED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SUPDRV_ERR_VERSION_MISMATCH: return STATUS_REVISION_MISMATCH;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return STATUS_UNSUCCESSFUL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** Runtime assert implementation for Native Win32 Ring-0. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(void) AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync DbgPrint("\n!!Assertion Failed!!\n"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync "Expression: %s\n"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync "Location : %s(%d) %s\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pszExpr, pszFile, uLine, pszFunction);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncint VBOXCALL mymemcmp(const void *pv1, const void *pv2, size_t cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uint8_t *pb1 = (const uint8_t *)pv1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uint8_t *pb2 = (const uint8_t *)pv2;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (; cb > 0; cb--, pb1++, pb2++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (*pb1 != *pb2)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return *pb1 - *pb2;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync