mp-r0drv-nt.cpp revision e6e2974634808306e2557acf7b9faae14ff5b93b
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync/* $Id$ */
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync/** @file
9ae4ea547111829e80548cfee4c972e62c0da811vboxsync * IPRT - Multiprocessor, Ring-0 Driver, NT.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync */
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync/*
c0e374304cebe77219b2abc0b6796e72e452c4ddvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync *
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.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync *
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 *
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.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync *
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
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/*******************************************************************************
1e40f57c72c881067b0314f898e1004211bb7650vboxsync* Header Files *
1e40f57c72c881067b0314f898e1004211bb7650vboxsync*******************************************************************************/
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include "the-nt-kernel.h"
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include <iprt/mp.h>
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include <iprt/cpuset.h>
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include <iprt/err.h>
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include <iprt/asm.h>
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include "r0drv/mp-r0drv.h"
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#include "internal-r0drv-nt.h"
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/*******************************************************************************
1e40f57c72c881067b0314f898e1004211bb7650vboxsync* Structures and Typedefs *
1e40f57c72c881067b0314f898e1004211bb7650vboxsync*******************************************************************************/
1e40f57c72c881067b0314f898e1004211bb7650vboxsynctypedef enum
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync RT_NT_CPUID_SPECIFIC,
1e40f57c72c881067b0314f898e1004211bb7650vboxsync RT_NT_CPUID_OTHERS,
1e40f57c72c881067b0314f898e1004211bb7650vboxsync RT_NT_CPUID_ALL
1e40f57c72c881067b0314f898e1004211bb7650vboxsync} RT_NT_CPUID;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/* test a couple of assumption. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncAssertCompile(MAXIMUM_PROCESSORS <= RTCPUSET_MAX_CPUS);
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncAssertCompile(NIL_RTCPUID >= MAXIMUM_PROCESSORS);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/** @todo
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 */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(RTCPUID) RTMpCpuId(void)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* WDK upgrade warning: PCR->Number changed from BYTE to WORD. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return KeGetCurrentProcessorNumber();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
a4a232fa546df3af50f9389873b521028eed4cdevboxsync{
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync return idCpu < MAXIMUM_PROCESSORS ? idCpu : -1;
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync}
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync
a4a232fa546df3af50f9389873b521028eed4cdevboxsync
a4a232fa546df3af50f9389873b521028eed4cdevboxsyncRTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync{
a4a232fa546df3af50f9389873b521028eed4cdevboxsync return (unsigned)iCpu < MAXIMUM_PROCESSORS ? iCpu : NIL_RTCPUID;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
a4a232fa546df3af50f9389873b521028eed4cdevboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(RTCPUID) RTMpGetMaxCpuId(void)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return MAXIMUM_PROCESSORS - 1;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncRTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (idCpu >= MAXIMUM_PROCESSORS)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return false;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#if 0 /* this isn't safe at all IRQLs (great work guys) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KAFFINITY Mask = KeQueryActiveProcessors();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return !!(Mask & RT_BIT_64(idCpu));
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync#else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return RTCpuSetIsMember(&g_rtMpNtCpuSet, idCpu);
cd7a8c034836a94a0c4f0adf9764f9ed661cdd01vboxsync#endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* Cannot easily distinguish between online and offline cpus. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return RTMpIsCpuOnline(idCpu);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncRTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return RTMpGetOnlineSet(pSet);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(RTCPUID) RTMpGetCount(void)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /** @todo online/present cpu stuff must be corrected for proper W2K8 support. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return RTMpGetOnlineCount();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync#if 0 /* this isn't safe at all IRQLs (great work guys) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KAFFINITY Mask = KeQueryActiveProcessors();
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync return RTCpuSetFromU64(pSet, Mask);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync#else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync *pSet = g_rtMpNtCpuSet;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return pSet;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync#endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncRTDECL(RTCPUID) RTMpGetOnlineCount(void)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync RTCPUSET Set;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync RTMpGetOnlineSet(&Set);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync return RTCpuSetCount(&Set);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync/**
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Wrapper between the native nt per-cpu callbacks and PFNRTWORKER
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync *
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
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync */
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncstatic VOID rtmpNtDPCWrapper(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync PRTMPARGS pArgs = (PRTMPARGS)DeferredContext;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ASMAtomicIncU32(&pArgs->cHits);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync pArgs->pfnWorker(KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync}
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync/**
1e40f57c72c881067b0314f898e1004211bb7650vboxsync * Internal worker for the RTMpOn* APIs.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync *
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.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync */
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsyncstatic int rtMpCall(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu)
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync PRTMPARGS pArgs;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KDPC *paExecCpuDpcs;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
b92634cd549ff80a3b9136227345237116ccd4favboxsync#if 0
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync /* KeFlushQueuedDpcs must be run at IRQL PASSIVE_LEVEL according to MSDN, but the
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync * driver verifier doesn't complain...
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync AssertMsg(KeGetCurrentIrql() == PASSIVE_LEVEL, ("%d != %d (PASSIVE_LEVEL)\n", KeGetCurrentIrql(), PASSIVE_LEVEL));
1e40f57c72c881067b0314f898e1004211bb7650vboxsync#endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KAFFINITY Mask = KeQueryActiveProcessors();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* KeFlushQueuedDpcs is not present in Windows 2000; import it dynamically so we can just fail this call. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync UNICODE_STRING RoutineName;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
1e40f57c72c881067b0314f898e1004211bb7650vboxsync VOID (*pfnKeFlushQueuedDpcs)(VOID) = (VOID (*)(VOID))MmGetSystemRoutineAddress(&RoutineName);
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync if (!pfnKeFlushQueuedDpcs)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return VERR_NOT_SUPPORTED;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pArgs = (PRTMPARGS)ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_PROCESSORS*sizeof(KDPC) + sizeof(RTMPARGS), (ULONG)'RTMp');
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (!pArgs)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return VERR_NO_MEMORY;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pArgs->pfnWorker = pfnWorker;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pArgs->pvUser1 = pvUser1;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync pArgs->pvUser2 = pvUser2;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pArgs->idCpu = NIL_RTCPUID;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync pArgs->cHits = 0;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync paExecCpuDpcs = (KDPC *)(pArgs + 1);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (enmCpuid == RT_NT_CPUID_SPECIFIC)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetTargetProcessorDpc(&paExecCpuDpcs[0], idCpu);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeInitializeDpc(&paExecCpuDpcs[i], rtmpNtDPCWrapper, pArgs);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetImportanceDpc(&paExecCpuDpcs[i], HighImportance);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeSetTargetProcessorDpc(&paExecCpuDpcs[i], i);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
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 */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KIRQL oldIrql;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /*
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 */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (enmCpuid == RT_NT_CPUID_SPECIFIC)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[0], 0, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync Assert(ret);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync unsigned iSelf = KeGetCurrentProcessorNumber();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if ( (i != iSelf)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync && (Mask & RT_BIT_64(i)))
1e40f57c72c881067b0314f898e1004211bb7650vboxsync {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[i], 0, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync Assert(ret);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (enmCpuid != RT_NT_CPUID_OTHERS)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pfnWorker(iSelf, pvUser1, pvUser2);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync KeLowerIrql(oldIrql);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync /* Flush all DPCs and wait for completion. (can take long!) */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync pfnKeFlushQueuedDpcs();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ExFreePool(pArgs);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return VINF_SUCCESS;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
b92634cd549ff80a3b9136227345237116ccd4favboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
b92634cd549ff80a3b9136227345237116ccd4favboxsync return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, 0);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncRTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync{
1e40f57c72c881067b0314f898e1004211bb7650vboxsync if (RTMpIsCpuOnline(idCpu))
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return !RTMpIsCpuPossible(idCpu)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ? VERR_CPU_NOT_FOUND
1e40f57c72c881067b0314f898e1004211bb7650vboxsync : VERR_CPU_OFFLINE;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_SPECIFIC, idCpu);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync}
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync