mp-r0drv-nt.cpp revision e6e2974634808306e2557acf7b9faae14ff5b93b
9ae4ea547111829e80548cfee4c972e62c0da811vboxsync * IPRT - Multiprocessor, Ring-0 Driver, NT.
c0e374304cebe77219b2abc0b6796e72e452c4ddvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync * available from http://www.virtualbox.org. This file is free software;
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * additional information or have any questions.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/*******************************************************************************
1e40f57c72c881067b0314f898e1004211bb7650vboxsync* Header Files *
1e40f57c72c881067b0314f898e1004211bb7650vboxsync*******************************************************************************/
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/*******************************************************************************
1e40f57c72c881067b0314f898e1004211bb7650vboxsync* Structures and Typedefs *
1e40f57c72c881067b0314f898e1004211bb7650vboxsync*******************************************************************************/
1e40f57c72c881067b0314f898e1004211bb7650vboxsynctypedef enum
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/* test a couple of assumption. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncAssertCompile(MAXIMUM_PROCESSORS <= RTCPUSET_MAX_CPUS);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * We cannot do other than assume a 1:1 relationship between the
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * affinity mask and the process despite the vagueness/warnings in
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * the docs. If someone knows a better way to get this done, please
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * let bird know.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* WDK upgrade warning: PCR->Number changed from BYTE to WORD. */
a4a232fa546df3af50f9389873b521028eed4cdevboxsync return (unsigned)iCpu < MAXIMUM_PROCESSORS ? iCpu : NIL_RTCPUID;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return false;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#if 0 /* this isn't safe at all IRQLs (great work guys) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* Cannot easily distinguish between online and offline cpus. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync#if 0 /* this isn't safe at all IRQLs (great work guys) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Wrapper between the native nt per-cpu callbacks and PFNRTWORKER
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param Dpc DPC object
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param DeferredContext Context argument specified by KeInitializeDpc
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param SystemArgument1 Argument specified by KeInsertQueueDpc
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param SystemArgument2 Argument specified by KeInsertQueueDpc
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncstatic VOID rtmpNtDPCWrapper(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync pArgs->pfnWorker(KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Internal worker for the RTMpOn* APIs.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * @returns IPRT status code.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * @param pfnWorker The callback.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param pvUser1 User argument 1.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * @param pvUser2 User argument 2.
b92634cd549ff80a3b9136227345237116ccd4favboxsync * @param enmCpuid What to do / is idCpu valid.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * @param idCpu Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncstatic int rtMpCall(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync /* KeFlushQueuedDpcs must be run at IRQL PASSIVE_LEVEL according to MSDN, but the
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * driver verifier doesn't complain...
1e40f57c72c881067b0314f898e1004211bb7650vboxsync AssertMsg(KeGetCurrentIrql() == PASSIVE_LEVEL, ("%d != %d (PASSIVE_LEVEL)\n", KeGetCurrentIrql(), PASSIVE_LEVEL));
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* KeFlushQueuedDpcs is not present in Windows 2000; import it dynamically so we can just fail this call. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
1e40f57c72c881067b0314f898e1004211bb7650vboxsync VOID (*pfnKeFlushQueuedDpcs)(VOID) = (VOID (*)(VOID))MmGetSystemRoutineAddress(&RoutineName);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pArgs = (PRTMPARGS)ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_PROCESSORS*sizeof(KDPC) + sizeof(RTMPARGS), (ULONG)'RTMp');
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeInitializeDpc(&paExecCpuDpcs[i], rtmpNtDPCWrapper, pArgs);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetImportanceDpc(&paExecCpuDpcs[i], HighImportance);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* Raise the IRQL to DISPATCH_LEVEL so we can't be rescheduled to another cpu.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * KeInsertQueueDpc must also be executed at IRQL >= DISPATCH_LEVEL.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * We cannot do other than assume a 1:1 relationship between the
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * affinity mask and the process despite the warnings in the docs.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * If someone knows a better way to get this done, please let bird know.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[0], 0, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[i], 0, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* Flush all DPCs and wait for completion. (can take long!) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
b92634cd549ff80a3b9136227345237116ccd4favboxsync return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)