b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/* $Id$ */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** @file
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, NT.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/*
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * Copyright (C) 2008-2011 Oracle Corporation
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * available from http://www.virtualbox.org. This file is free software;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * General Public License (GPL) as published by the Free Software
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * The contents of this file may alternatively be used under the terms
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * of the Common Development and Distribution License Version 1.0
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * CDDL are applicable instead of those of the GPL.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * You may elect to license modified versions of this file under the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * terms and conditions of either the GPL or the CDDL or both.
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/*******************************************************************************
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync* Header Files *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync*******************************************************************************/
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#include "the-nt-kernel.h"
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#include <iprt/mp.h>
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync#include <iprt/err.h>
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#include <iprt/cpuset.h>
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#include "r0drv/mp-r0drv.h"
28626a5957b49791b505bf66131448a847043763vboxsync#include "internal-r0drv-nt.h"
2f827df539da232220444c27f2b207a707a045b0vboxsync
ae6cc8f82ba26e3940022ea7d26078bec3d2a05fvboxsync
2f827df539da232220444c27f2b207a707a045b0vboxsync#if 0 /* The following is 100% untested code . */
2f827df539da232220444c27f2b207a707a045b0vboxsync
2f827df539da232220444c27f2b207a707a045b0vboxsync#ifndef KE_PROCESSOR_CHANGE_ADD_EXISTING
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/* Some bits that are missing from our DDK headers. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsynctypedef enum
9b0ba1d4360299b4e6ee23c946feb5a4f16c6d00vboxsync{
9b0ba1d4360299b4e6ee23c946feb5a4f16c6d00vboxsync KeProcessorAddStartNotify = 0,
9b0ba1d4360299b4e6ee23c946feb5a4f16c6d00vboxsync KeProcessorAddCompleteNotify,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync KeProcessorAddFailureNotify
7cca5a9aeb06913531b982bf772508d09b4c2f0bvboxsync} KE_PROCESSOR_CHANGE_NOTIFY_STATE;
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync
7cca5a9aeb06913531b982bf772508d09b4c2f0bvboxsynctypedef struct _KE_PROCESSOR_CHANGE_NOTIFY_CONTEXT
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync{
7cca5a9aeb06913531b982bf772508d09b4c2f0bvboxsync KE_PROCESSOR_CHANGE_NOTIFY_STATE State;
7cca5a9aeb06913531b982bf772508d09b4c2f0bvboxsync ULONG NtNumber;
2f827df539da232220444c27f2b207a707a045b0vboxsync NTSTATUS Status;
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync} KE_PROCESSOR_CHANGE_NOTIFY_CONTEXT;
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsynctypedef KE_PROCESSOR_CHANGE_NOTIFY_CONTEXT *PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT;
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsynctypedef VOID (__stdcall *PPROCESSOR_CALLBACK_FUNCTION)(PVOID, PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT, PNTSTATUS);
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync
2f827df539da232220444c27f2b207a707a045b0vboxsync# define KE_PROCESSOR_CHANGE_ADD_EXISTING 1
2f827df539da232220444c27f2b207a707a045b0vboxsync#endif /* !KE_PROCESSOR_CHANGE_ADD_EXISTING */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/*******************************************************************************
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync* Structures and Typedefs *
69485a2b3107976ff92a4f3db3ea862e25544059vboxsync*******************************************************************************/
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync/** Typedef of KeRegisterProcessorChangeCallback. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsynctypedef PVOID (__stdcall *PFNMYKEREGISTERPROCESSORCHANGECALLBACK)(PPROCESSOR_CALLBACK_FUNCTION, PVOID, ULONG);
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** Typedef of KeDeregisterProcessorChangeCallback. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsynctypedef VOID (__stdcall *PFNMYKEDEREGISTERPROCESSORCHANGECALLBACK)(PVOID);
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/*******************************************************************************
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync* Global Variables *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync*******************************************************************************/
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** The pointer to KeRegisterProcessorChangeCallback if found. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsyncstatic PFNMYKEREGISTERPROCESSORCHANGECALLBACK g_pfnKeRegisterProcessorChangeCallback = NULL;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** The pointer to KeDeregisterProcessorChangeCallback if found. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsyncstatic PFNMYKEDEREGISTERPROCESSORCHANGECALLBACK g_pfnKeDeregisterProcessorChangeCallback = NULL;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** The callback handle. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsyncstatic PVOID g_hCallback = NULL;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/**
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * The native callback.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync *
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * @param pNotifierBlock Pointer to g_NotifierBlock.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * @param ulNativeEvent The native event.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * @param pvCpu The cpu id cast into a pointer value.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsyncstatic VOID __stdcall rtMpNotificationNtCallback(PVOID pvUser,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT pChangeContext,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync PNTSTATUS pOperationStatus)
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync{
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync NOREF(pvUser);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync AssertPtr(pChangeContext);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync AssertPtrNull(pOperationStatus);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync RTCPUID idCpu = pChangeContext->NtNumber;
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync switch (pChangeContext->State)
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync {
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync case KeProcessorAddStartNotify:
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync case KeProcessorAddFailureNotify:
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync break;
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync case KeProcessorAddCompleteNotify:
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync /* Update the active CPU set before doing callback round. */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync RTCpuSetAdd(&g_rtMpNtCpuSet, idCpu);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync break;
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync //case KeProcessorDelCompleteNotify:
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync // rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync // break;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync default:
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync AssertMsgFailed(("Unexpected state=%d idCpu=%d\n", pChangeContext->State, (int)idCpu));
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync break;
7f9e93577d96c7f2a6977229c1baab57d5ec94e4vboxsync }
2f827df539da232220444c27f2b207a707a045b0vboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync *pOperationStatus = STATUS_SUCCESS;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync}
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsyncDECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync{
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync /*
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync * Try resolve the symbols.
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync */
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync UNICODE_STRING RoutineName;
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync RtlInitUnicodeString(&RoutineName, L"KeRegisterProcessorChangeCallback");
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync g_pfnKeRegisterProcessorChangeCallback = (PFNMYKEREGISTERPROCESSORCHANGECALLBACK)MmGetSystemRoutineAddress(&RoutineName);
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync if (g_pfnKeRegisterProcessorChangeCallback)
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync {
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync RtlInitUnicodeString(&RoutineName, L"KeDeregisterProcessorChangeCallback");
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync g_pfnKeDeregisterProcessorChangeCallback = (PFNMYKEDEREGISTERPROCESSORCHANGECALLBACK)MmGetSystemRoutineAddress(&RoutineName);
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync if (g_pfnKeDeregisterProcessorChangeCallback)
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync {
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync /*
5b0adfbdd9550a026f5d6209743504562f791f97vboxsync * Try call it.
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync */
f2e1f71feb5d4ec79d46defcd71de0763234b1e2vboxsync NTSTATUS ntRc = 0;
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync g_hCallback = g_pfnKeRegisterProcessorChangeCallback(rtMpNotificationNtCallback, &ntRc, KE_PROCESSOR_CHANGE_ADD_EXISTING);
f2e1f71feb5d4ec79d46defcd71de0763234b1e2vboxsync if (g_hCallback != NULL)
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync return VINF_SUCCESS;
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync /* Genuine failure. */
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync int rc = RTErrConvertFromNtStatus(ntRc);
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync AssertMsgFailed(("ntRc=%#x rc=%d\n", ntRc, rc));
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync return rc;
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync }
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync /* this shouldn't happen. */
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync AssertFailed();
581bb0c43dececce2fbba05cfb77d9a59c88a078vboxsync }
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync /* Not supported - success. */
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync g_pfnKeRegisterProcessorChangeCallback = NULL;
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync g_pfnKeDeregisterProcessorChangeCallback = NULL;
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync return VINF_SUCCESS;
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync}
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
2f827df539da232220444c27f2b207a707a045b0vboxsync
2f827df539da232220444c27f2b207a707a045b0vboxsyncDECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync{
2f827df539da232220444c27f2b207a707a045b0vboxsync if ( g_pfnKeDeregisterProcessorChangeCallback
2f827df539da232220444c27f2b207a707a045b0vboxsync && g_hCallback)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync {
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync g_pfnKeDeregisterProcessorChangeCallback(g_hCallback);
2cb52dd865592ea8e27b588beb22898d189646b1vboxsync g_hCallback = NULL;
a2410ed6c0ce63f29ac7132882e4e46d921f239dvboxsync }
a2410ed6c0ce63f29ac7132882e4e46d921f239dvboxsync}
a2410ed6c0ce63f29ac7132882e4e46d921f239dvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync#else /* Not supported */
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsyncDECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync{
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync return VINF_SUCCESS;
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync}
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsyncDECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync{
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync}
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync#endif /* Not supported */
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync