initterm-r0drv-nt.cpp revision ae8302e80cb2f8a5ad2812dd644029761de06c57
0N/A * IPRT - Initialization & Termination, R0 Driver, NT. 0N/A * Copyright (C) 2006-2013 Oracle Corporation 0N/A * This file is part of VirtualBox Open Source Edition (OSE), as 0N/A * you can redistribute it and/or modify it under the terms of the GNU 0N/A * General Public License (GPL) as published by the Free Software 0N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 0N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 0N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 0N/A * The contents of this file may alternatively be used under the terms 0N/A * of the Common Development and Distribution License Version 1.0 1472N/A * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 1472N/A * VirtualBox OSE distribution, in which case the provisions of the 1472N/A * CDDL are applicable instead of those of the GPL. 0N/A * You may elect to license modified versions of this file under the 0N/A * terms and conditions of either the GPL or the CDDL or both. 1879N/A/******************************************************************************* 1879N/A*******************************************************************************/ 2073N/A/******************************************************************************* 2073N/A*******************************************************************************/ 2073N/A * KeQueryActiveProcssors() cannot be called at all IRQLs and therefore we'll 2073N/A * have to cache it. Fortunately, Nt doesn't really support taking CPUs offline 1879N/A * or online. It's first with W2K8 that support for CPU hotplugging was added. 1879N/A * Once we start caring about this, we'll simply let the native MP event callback 1879N/A * and update this variable as CPUs comes online. (The code is done already.) 1879N/A/** ExSetTimerResolution, introduced in W2K. */ 1879N/A/** KeFlushQueuedDpcs, introduced in XP. */ 2796N/A/** HalRequestIpi, introduced in ??. */ 1879N/A/** HalSendSoftwareInterrupt */ 0N/A/** SendIpi handler based on Windows version */ 0N/A/** KeIpiGenericCall - Windows Server 2003+ only */ 0N/A/** RtlGetVersion, introduced in ??. */ 0N/A/** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */ 0N/A/** Size of the _KPRCB::QuantumEnd field. 0 if not found. */ 0N/A/** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */ 0N/A * Determines the NT kernel verison information. 0N/A * @param pOsVerInfo Where to return the version information. 0N/A * @remarks pOsVerInfo->fSmp is only definitive if @c true. 0N/A * @remarks pOsVerInfo->uCsdNo is set to MY_NIL_CSD if it cannot be determined. 0N/A /* Note! We cannot quite say if something is MP or UNI. So, fSmp is 0N/A redefined to indicate that it must be MP. */ 0N/A * Tries a set against the current kernel. 0N/A * @retval @c true if it matched up, global variables are updated. 0N/A * @retval @c false otherwise (no globals updated). 0N/A * @param pSet The data set. 0N/A * @param pbPrcb Pointer to the processor control block. 0N/A * @param pszVendor Pointer to the processor vendor string. 0N/A * @param pOsVerInfo The OS version info. 0N/A * Don't bother trying stuff where the NT kernel version number differs, or 0N/A * if the build type or SMPness doesn't match up. 0N/A //DbgPrint("IPRT: #%d Version/type mismatch.\n", pSet - &g_artNtSdbSets[0]); 0N/A * Do the CPU vendor test. 0N/A * Note! The MmIsAddressValid call is the real #PF security here as the 0N/A * __try/__except has limited/no ability to catch everything we need. 0N/A //DbgPrint("IPRT: #%d invalid vendor string address.\n", pSet - &g_artNtSdbSets[0]); 0N/A //DbgPrint("IPRT: #%d Vendor string mismatch.\n", pSet - &g_artNtSdbSets[0]); 0N/A * Got a match, update the global variables and report succcess. 0N/A DbgPrint(
"IPRT: Using data set #%u for %u.%usp%u build %u %s %s.\n",
0N/A * Init the Nt cpu set. 2062N/A * Initialize the function pointers. * HACK ALERT! (and d�j� vu warning - remember win32k.sys?) * Try find _KPRCB::QuantumEnd and _KPRCB::[DpcData.]DpcQueueDepth. * For purpose of verification we use the VendorString member (12+1 chars). * The offsets was initially derived by poking around with windbg * (dt _KPRCB, !prcb ++, and such like). Systematic harvesting was then * planned using dia2dump, grep and the symbol pack in a manner like this: * dia2dump -type _KDPC_DATA -type _KPRCB EXE\ntkrnlmp.pdb | grep -wE "QuantumEnd|DpcData|DpcQueueDepth|VendorString" * The final solution ended up using a custom harvester program called * ntBldSymDb that recursively searches thru unpacked symbol packages for * the desired structure offsets. The program assumes that the packages * are unpacked into directories with the same name as the package, with * exception of some of the w2k packages which requires a 'w2k' prefix to * be distinguishable from another. * Gather consistent CPU vendor string and PRCB pointers. __try /* Warning. This try/except statement may provide some false safety. */ /* Find the best matching kernel version based on build number. */ /* Try all sets: iBest -> End; iBest -> Start. */ DbgPrint(
"IPRT: Failed to locate data set.\n");
DbgPrint(
"IPRT: Failed to get PCBR pointer.\n");
KeLowerIrql(
OldIrql);
/* Lowering the IRQL early in the hope that we may catch exceptions below. */ DbgPrint(
"IPRT: Neither _KPRCB::QuantumEnd nor _KPRCB::DpcQueueDepth was not found! Kernel %u.%u %u %s\n",
DbgPrint(
"IPRT: _KPRCB:{.QuantumEnd=%x/%d, .DpcQueueDepth=%x/%d} Kernel %u.%u %u %s\n",
/* Vista or Windows Server 2008 */ /* Windows 7 or Windows Server 2008 R2 */ /* Windows XP should send always send an IPI -> VERIFY */