VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp@ 28517

Last change on this file since 28517 was 24034, checked in by vboxsync, 15 years ago

Backed out r53864; will cause too many problems unfortunately.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.6 KB
Line 
1/* $Id: initterm-r0drv-nt.cpp 24034 2009-10-23 13:04:13Z vboxsync $ */
2/** @file
3 * IPRT - Initialization & Termination, R0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include "the-nt-kernel.h"
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/mp.h>
38#include <iprt/string.h>
39#include "internal/initterm.h"
40#include "internal-r0drv-nt.h"
41
42
43/*******************************************************************************
44* Global Variables *
45*******************************************************************************/
46/** The Nt CPU set.
47 * KeQueryActiveProcssors() cannot be called at all IRQLs and therefore we'll
48 * have to cache it. Fortunately, Nt doesn't really support taking CPUs offline
49 * or online. It's first with W2K8 that support for CPU hotplugging was added.
50 * Once we start caring about this, we'll simply let the native MP event callback
51 * and update this variable as CPUs comes online. (The code is done already.)
52 */
53RTCPUSET g_rtMpNtCpuSet;
54
55/** ExSetTimerResolution, introduced in W2K. */
56PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution;
57/** KeFlushQueuedDpcs, introduced in XP. */
58PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs;
59/** HalRequestIpi, introduced in ??. */
60PFNHALREQUESTIPI g_pfnrtNtHalRequestIpi;
61/** HalSendSoftwareInterrupt */
62PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt;
63/** SendIpi handler based on Windows version */
64PFNRTSENDIPI g_pfnrtSendIpi;
65/** KeIpiGenericCall - Windows Server 2003+ only */
66PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall;
67
68/** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */
69uint32_t g_offrtNtPbQuantumEnd;
70/** Size of the _KPRCB::QuantumEnd field. 0 if not found. */
71uint32_t g_cbrtNtPbQuantumEnd;
72/** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */
73uint32_t g_offrtNtPbDpcQueueDepth;
74
75
76
77int rtR0InitNative(void)
78{
79 /*
80 * Init the Nt cpu set.
81 */
82#ifdef IPRT_TARGET_NT4
83 KAFFINITY ActiveProcessors = (UINT64_C(1) << KeNumberProcessors) - UINT64_C(1);
84#else
85 KAFFINITY ActiveProcessors = KeQueryActiveProcessors();
86#endif
87 RTCpuSetEmpty(&g_rtMpNtCpuSet);
88 RTCpuSetFromU64(&g_rtMpNtCpuSet, ActiveProcessors);
89
90#ifdef IPRT_TARGET_NT4
91 g_pfnrtNtExSetTimerResolution = NULL;
92 g_pfnrtNtKeFlushQueuedDpcs = NULL;
93 g_pfnrtNtHalRequestIpi = NULL;
94 g_pfnrtNtHalSendSoftwareInterrupt = NULL;
95 g_pfnrtKeIpiGenericCall = NULL;
96#else
97 /*
98 * Initialize the function pointers.
99 */
100 UNICODE_STRING RoutineName;
101 RtlInitUnicodeString(&RoutineName, L"ExSetTimerResolution");
102 g_pfnrtNtExSetTimerResolution = (PFNMYEXSETTIMERRESOLUTION)MmGetSystemRoutineAddress(&RoutineName);
103
104 RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
105 g_pfnrtNtKeFlushQueuedDpcs = (PFNMYKEFLUSHQUEUEDDPCS)MmGetSystemRoutineAddress(&RoutineName);
106
107 RtlInitUnicodeString(&RoutineName, L"HalRequestIpi");
108 g_pfnrtNtHalRequestIpi = (PFNHALREQUESTIPI)MmGetSystemRoutineAddress(&RoutineName);
109
110 RtlInitUnicodeString(&RoutineName, L"HalSendSoftwareInterrupt");
111 g_pfnrtNtHalSendSoftwareInterrupt = (PFNHALSENDSOFTWAREINTERRUPT)MmGetSystemRoutineAddress(&RoutineName);
112
113 RtlInitUnicodeString(&RoutineName, L"KeIpiGenericCall");
114 g_pfnrtKeIpiGenericCall = (PFNRTKEIPIGENERICCALL)MmGetSystemRoutineAddress(&RoutineName);
115#endif
116
117 /*
118 * Get some info that might come in handy below.
119 */
120 ULONG MajorVersion = 0;
121 ULONG MinorVersion = 0;
122 ULONG BuildNumber = 0;
123 BOOLEAN fChecked = PsGetVersion(&MajorVersion, &MinorVersion, &BuildNumber, NULL);
124
125 g_pfnrtSendIpi = rtMpSendIpiDummy;
126#ifndef IPRT_TARGET_NT4
127 if ( g_pfnrtNtHalRequestIpi
128 && MajorVersion == 6
129 && MinorVersion == 0)
130 {
131 /* Vista or Windows Server 2008 */
132 g_pfnrtSendIpi = rtMpSendIpiVista;
133 }
134 else
135 if ( g_pfnrtNtHalSendSoftwareInterrupt
136 && MajorVersion == 6
137 && MinorVersion == 1)
138 {
139 /* Windows 7 or Windows Server 2008 R2 */
140 g_pfnrtSendIpi = rtMpSendIpiWin7;
141 }
142 /* Windows XP should send always send an IPI -> VERIFY */
143#endif
144 KIRQL OldIrql;
145 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); /* make sure we stay on the same cpu */
146
147 union
148 {
149 uint32_t auRegs[4];
150 char szVendor[4*3+1];
151 } u;
152 ASMCpuId(0, &u.auRegs[3], &u.auRegs[0], &u.auRegs[2], &u.auRegs[1]);
153 u.szVendor[4*3] = '\0';
154
155 /*
156 * HACK ALERT (and déjà vu warning)!
157 *
158 * Try find _KPRCB::QuantumEnd and _KPRCB::[DpcData.]DpcQueueDepth.
159 * For purpose of verification we use the VendorString member (12+1 chars).
160 *
161 * The offsets was initially derived by poking around with windbg
162 * (dt _KPRCB, !prcb ++, and such like). Systematic harvesting is now done
163 * by means of dia2dump, grep and the symbol packs. Typically:
164 * dia2dump -type _KDPC_DATA -type _KPRCB EXE\ntkrnlmp.pdb | grep -wE "QuantumEnd|DpcData|DpcQueueDepth|VendorString"
165 */
166 /** @todo array w/ data + script for extracting a row. (save space + readability; table will be short.) */
167 __try
168 {
169#if defined(RT_ARCH_X86)
170 PKPCR pPcr = (PKPCR)__readfsdword(RT_OFFSETOF(KPCR,SelfPcr));
171 uint8_t *pbPrcb = (uint8_t *)pPcr->Prcb;
172
173 if ( BuildNumber == 2600 /* XP SP2 */
174 && !memcmp(&pbPrcb[0x900], &u.szVendor[0], 4*3))
175 {
176 g_offrtNtPbQuantumEnd = 0x88c;
177 g_cbrtNtPbQuantumEnd = 4;
178 g_offrtNtPbDpcQueueDepth = 0x870;
179 }
180 /* WindowsVista.6002.090410-1830.x86fre.Symbols.exe
181 WindowsVista.6002.090410-1830.x86chk.Symbols.exe
182 WindowsVista.6002.090130-1715.x86fre.Symbols.exe
183 WindowsVista.6002.090130-1715.x86chk.Symbols.exe */
184 else if ( BuildNumber == 6002
185 && !memcmp(&pbPrcb[0x1c2c], &u.szVendor[0], 4*3))
186 {
187 g_offrtNtPbQuantumEnd = 0x1a41;
188 g_cbrtNtPbQuantumEnd = 1;
189 g_offrtNtPbDpcQueueDepth = 0x19e0 + 0xc;
190 }
191
192 /** @todo more */
193 //pbQuantumEnd = (uint8_t volatile *)pPcr->Prcb + 0x1a41;
194
195#elif defined(RT_ARCH_AMD64)
196 PKPCR pPcr = (PKPCR)__readgsqword(RT_OFFSETOF(KPCR,Self));
197 uint8_t *pbPrcb = (uint8_t *)pPcr->CurrentPrcb;
198
199 if ( BuildNumber == 3790 /* XP64 / W2K3-AMD64 SP1 */
200 && !memcmp(&pbPrcb[0x22b4], &u.szVendor[0], 4*3))
201 {
202 g_offrtNtPbQuantumEnd = 0x1f75;
203 g_cbrtNtPbQuantumEnd = 1;
204 g_offrtNtPbDpcQueueDepth = 0x1f00 + 0x18;
205 }
206 else if ( BuildNumber == 6000 /* Vista/AMD64 */
207 && !memcmp(&pbPrcb[0x38bc], &u.szVendor[0], 4*3))
208 {
209 g_offrtNtPbQuantumEnd = 0x3375;
210 g_cbrtNtPbQuantumEnd = 1;
211 g_offrtNtPbDpcQueueDepth = 0x3300 + 0x18;
212 }
213 /* WindowsVista.6002.090410-1830.amd64fre.Symbols
214 WindowsVista.6002.090130-1715.amd64fre.Symbols
215 WindowsVista.6002.090410-1830.amd64chk.Symbols */
216 else if ( BuildNumber == 6002
217 && !memcmp(&pbPrcb[0x399c], &u.szVendor[0], 4*3))
218 {
219 g_offrtNtPbQuantumEnd = 0x3475;
220 g_cbrtNtPbQuantumEnd = 1;
221 g_offrtNtPbDpcQueueDepth = 0x3400 + 0x18;
222 }
223
224#else
225# error "port me"
226#endif
227 }
228 __except(EXCEPTION_EXECUTE_HANDLER) /** @todo this handler doesn't seem to work... Because of Irql? */
229 {
230 g_offrtNtPbQuantumEnd = 0;
231 g_cbrtNtPbQuantumEnd = 0;
232 g_offrtNtPbDpcQueueDepth = 0;
233 }
234
235 KeLowerIrql(OldIrql);
236
237#ifndef IN_GUEST /** @todo fix above for all Nt versions. */
238 if (!g_offrtNtPbQuantumEnd && !g_offrtNtPbDpcQueueDepth)
239 DbgPrint("IPRT: Neither _KPRCB::QuantumEnd nor _KPRCB::DpcQueueDepth was not found! Kernel %u.%u %u %s\n",
240 MajorVersion, MinorVersion, BuildNumber, fChecked ? "checked" : "free");
241# ifdef DEBUG
242 else
243 DbgPrint("IPRT: _KPRCB:{.QuantumEnd=%x/%d, .DpcQueueDepth=%x/%d} Kernel %ul.%ul %ul %s\n",
244 g_offrtNtPbQuantumEnd, g_cbrtNtPbQuantumEnd, g_offrtNtPbDpcQueueDepth,
245 MajorVersion, MinorVersion, BuildNumber, fChecked ? "checked" : "free");
246# endif
247#endif
248
249 return VINF_SUCCESS;
250}
251
252
253void rtR0TermNative(void)
254{
255}
256
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette