- Timestamp:
- Apr 9, 2013 6:30:45 PM (12 years ago)
- Location:
- trunk/src/VBox/Runtime/r0drv/nt
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
r44528 r45443 5 5 6 6 /* 7 * Copyright (C) 2006-201 1Oracle Corporation7 * Copyright (C) 2006-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 36 36 #include "internal/initterm.h" 37 37 #include "internal-r0drv-nt.h" 38 #include "symdb.h" 39 #include "symdbdata.h" 38 40 39 41 … … 41 43 * Global Variables * 42 44 *******************************************************************************/ 43 /** The N tCPU set.45 /** The NT CPU set. 44 46 * KeQueryActiveProcssors() cannot be called at all IRQLs and therefore we'll 45 47 * have to cache it. Fortunately, Nt doesn't really support taking CPUs offline … … 62 64 /** KeIpiGenericCall - Windows Server 2003+ only */ 63 65 PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 66 /** RtlGetVersion, introduced in ??. */ 67 PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; 64 68 65 69 /** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */ … … 71 75 72 76 77 /** 78 * Determines the NT kernel verison information. 79 * 80 * @param pOsVerInfo Where to return the version information. 81 * 82 * @remarks pOsVerInfo->fSmp is only definitive if @c true. 83 * @remarks pOsVerInfo->uCsdNo is set to MY_NIL_CSD if it cannot be determined. 84 */ 85 static void rtR0NtGetOsVersionInfo(PRTNTSDBOSVER pOsVerInfo) 86 { 87 ULONG ulMajorVersion = 0; 88 ULONG ulMinorVersion = 0; 89 ULONG ulBuildNumber = 0; 90 91 pOsVerInfo->fChecked = PsGetVersion(&ulMajorVersion, &ulMinorVersion, &ulBuildNumber, NULL) == TRUE; 92 pOsVerInfo->uMajorVer = (uint8_t)ulMajorVersion; 93 pOsVerInfo->uMinorVer = (uint8_t)ulMinorVersion; 94 pOsVerInfo->uBuildNo = ulBuildNumber; 95 #define MY_NIL_CSD 0x3f 96 pOsVerInfo->uCsdNo = MY_NIL_CSD; 97 98 if (g_pfnrtRtlGetVersion) 99 { 100 RTL_OSVERSIONINFOEXW VerInfo; 101 RT_ZERO(VerInfo); 102 VerInfo.dwOSVersionInfoSize = sizeof(VerInfo); 103 104 NTSTATUS rcNt = g_pfnrtRtlGetVersion(&VerInfo); 105 if (NT_SUCCESS(rcNt)) 106 pOsVerInfo->uCsdNo = VerInfo.wServicePackMajor; 107 } 108 109 /* Note! We cannot quite say if something is MP or UNI. So, fSmp is 110 redefined to indicate that it must be MP. */ 111 pOsVerInfo->fSmp = RTMpGetCount() > 1 112 || ulMajorVersion >= 6; /* Vista and later has no UNI kernel AFAIK. */ 113 } 114 115 116 /** 117 * Tries a set against the current kernel. 118 * 119 * @retval @c true if it matched up, global variables are updated. 120 * @retval @c false otherwise (no globals updated). 121 * @param pSet The data set. 122 * @param pbPrcb Pointer to the processor control block. 123 * @param pszVendor Pointer to the processor vendor string. 124 * @param pOsVerInfo The OS version info. 125 */ 126 static bool rtR0NtTryMatchSymSet(PCRTNTSDBSET pSet, uint8_t *pbPrcb, const char *pszVendor, PCRTNTSDBOSVER pOsVerInfo) 127 { 128 /* 129 * Don't bother trying stuff where the NT kernel version number differs, or 130 * if the build type or SMPness doesn't match up. 131 */ 132 if ( pSet->OsVerInfo.uMajorVer != pOsVerInfo->uMajorVer 133 || pSet->OsVerInfo.uMinorVer != pOsVerInfo->uMinorVer 134 || pSet->OsVerInfo.fChecked != pOsVerInfo->fChecked 135 || (!pSet->OsVerInfo.fSmp && pOsVerInfo->fSmp /*must-be-smp*/) ) 136 { 137 //DbgPrint("IPRT: #%d Version/type mismatch.\n", pSet - &g_artNtSdbSets[0]); 138 return false; 139 } 140 141 /* 142 * Do the CPU vendor test. 143 */ 144 __try 145 { 146 if (memcmp(&pbPrcb[pSet->KPRCB.offVendorString], pszVendor, 147 RT_MIN(4 * 3, pSet->KPRCB.cbVendorString)) != 0) 148 { 149 //DbgPrint("IPRT: #%d Vendor string mismatch.\n"); 150 return false; 151 } 152 } 153 __except(EXCEPTION_EXECUTE_HANDLER) /** @todo this handler doesn't seem to work... Because of Irql? */ 154 { 155 //DbgPrint("IPRT: Exception\n"); 156 return false; 157 } 158 159 /* 160 * Got a match, update the global variables and report succcess. 161 */ 162 g_offrtNtPbQuantumEnd = pSet->KPRCB.offQuantumEnd; 163 g_cbrtNtPbQuantumEnd = pSet->KPRCB.cbQuantumEnd; 164 g_offrtNtPbDpcQueueDepth = pSet->KPRCB.offDpcQueueDepth; 165 166 #if 0 167 DbgPrint("IPRT: Using data set #%u for %u.%usp%u build %u %s %s.\n", 168 pSet - &g_artNtSdbSets[0], 169 pSet->OsVerInfo.uMajorVer, 170 pSet->OsVerInfo.uMinorVer, 171 pSet->OsVerInfo.uCsdNo, 172 pSet->OsVerInfo.uBuildNo, 173 pSet->OsVerInfo.fSmp ? "smp" : "uni", 174 pSet->OsVerInfo.fChecked ? "checked" : "free"); 175 #endif 176 return true; 177 } 178 73 179 74 180 DECLHIDDEN(int) rtR0InitNative(void) … … 92 198 g_pfnrtNtHalSendSoftwareInterrupt = NULL; 93 199 g_pfnrtKeIpiGenericCall = NULL; 200 g_pfnrtRtlGetVersion = NULL; 94 201 #else 95 202 /* … … 111 218 RtlInitUnicodeString(&RoutineName, L"KeIpiGenericCall"); 112 219 g_pfnrtKeIpiGenericCall = (PFNRTKEIPIGENERICCALL)MmGetSystemRoutineAddress(&RoutineName); 113 #endif 114 115 /* 116 * Get some info that might come in handy below. 117 */ 118 ULONG MajorVersion = 0; 119 ULONG MinorVersion = 0; 120 ULONG BuildNumber = 0; 121 BOOLEAN fChecked = PsGetVersion(&MajorVersion, &MinorVersion, &BuildNumber, NULL); 122 123 g_pfnrtSendIpi = rtMpSendIpiDummy; 124 #ifndef IPRT_TARGET_NT4 125 if ( g_pfnrtNtHalRequestIpi 126 && MajorVersion == 6 127 && MinorVersion == 0) 128 { 129 /* Vista or Windows Server 2008 */ 130 g_pfnrtSendIpi = rtMpSendIpiVista; 131 } 132 else 133 if ( g_pfnrtNtHalSendSoftwareInterrupt 134 && MajorVersion == 6 135 && MinorVersion == 1) 136 { 137 /* Windows 7 or Windows Server 2008 R2 */ 138 g_pfnrtSendIpi = rtMpSendIpiWin7; 139 } 140 /* Windows XP should send always send an IPI -> VERIFY */ 141 #endif 142 KIRQL OldIrql; 143 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); /* make sure we stay on the same cpu */ 144 145 union 146 { 147 uint32_t auRegs[4]; 148 char szVendor[4*3+1]; 149 } u; 150 ASMCpuId(0, &u.auRegs[3], &u.auRegs[0], &u.auRegs[2], &u.auRegs[1]); 151 u.szVendor[4*3] = '\0'; 220 221 RtlInitUnicodeString(&RoutineName, L"RtlGetVersion"); 222 g_pfnrtRtlGetVersion = (PFNRTRTLGETVERSION)MmGetSystemRoutineAddress(&RoutineName); 223 #endif 152 224 153 225 /* … … 162 234 * dia2dump -type _KDPC_DATA -type _KPRCB EXE\ntkrnlmp.pdb | grep -wE "QuantumEnd|DpcData|DpcQueueDepth|VendorString" 163 235 */ 164 /** @todo array w/ data + script for extracting a row. (save space + readability; table will be short.) */ 236 237 RTNTSDBOSVER OsVerInfo; 238 rtR0NtGetOsVersionInfo(&OsVerInfo); 239 240 /* 241 * Gather consistent CPU vendor string and PRCB pointers. 242 */ 243 KIRQL OldIrql; 244 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); /* make sure we stay on the same cpu */ 245 246 union 247 { 248 uint32_t auRegs[4]; 249 char szVendor[4*3+1]; 250 } u; 251 ASMCpuId(0, &u.auRegs[3], &u.auRegs[0], &u.auRegs[2], &u.auRegs[1]); 252 u.szVendor[4*3] = '\0'; 253 254 uint8_t *pbPrcb; 165 255 __try 166 256 { 167 257 #if defined(RT_ARCH_X86) 168 258 PKPCR pPcr = (PKPCR)__readfsdword(RT_OFFSETOF(KPCR,SelfPcr)); 169 uint8_t *pbPrcb = (uint8_t *)pPcr->Prcb; 170 171 if ( BuildNumber == 2600 /* XP SP2 */ 172 && !memcmp(&pbPrcb[0x900], &u.szVendor[0], 4*3)) 173 { 174 g_offrtNtPbQuantumEnd = 0x88c; 175 g_cbrtNtPbQuantumEnd = 4; 176 g_offrtNtPbDpcQueueDepth = 0x870; 177 } 178 /* WindowsVista.6002.090410-1830.x86fre.Symbols.exe 179 WindowsVista.6002.090410-1830.x86chk.Symbols.exe 180 WindowsVista.6002.090130-1715.x86fre.Symbols.exe 181 WindowsVista.6002.090130-1715.x86chk.Symbols.exe */ 182 else if ( BuildNumber == 6002 183 && !memcmp(&pbPrcb[0x1c2c], &u.szVendor[0], 4*3)) 184 { 185 g_offrtNtPbQuantumEnd = 0x1a41; 186 g_cbrtNtPbQuantumEnd = 1; 187 g_offrtNtPbDpcQueueDepth = 0x19e0 + 0xc; 188 } 189 else if ( BuildNumber == 3790 /* Server 2003 SP2 */ 190 && !memcmp(&pbPrcb[0xb60], &u.szVendor[0], 4*3)) 191 { 192 g_offrtNtPbQuantumEnd = 0x981; 193 g_cbrtNtPbQuantumEnd = 1; 194 g_offrtNtPbDpcQueueDepth = 0x920 + 0xc; 195 } 196 197 /** @todo more */ 198 //pbQuantumEnd = (uint8_t volatile *)pPcr->Prcb + 0x1a41; 199 259 pbPrcb = (uint8_t *)pPcr->Prcb; 200 260 #elif defined(RT_ARCH_AMD64) 201 261 PKPCR pPcr = (PKPCR)__readgsqword(RT_OFFSETOF(KPCR,Self)); 202 uint8_t *pbPrcb = (uint8_t *)pPcr->CurrentPrcb; 203 204 if ( BuildNumber == 3790 /* XP64 / W2K3-AMD64 SP1 */ 205 && !memcmp(&pbPrcb[0x22b4], &u.szVendor[0], 4*3)) 206 { 207 g_offrtNtPbQuantumEnd = 0x1f75; 208 g_cbrtNtPbQuantumEnd = 1; 209 g_offrtNtPbDpcQueueDepth = 0x1f00 + 0x18; 210 } 211 else if ( BuildNumber == 6000 /* Vista/AMD64 */ 212 && !memcmp(&pbPrcb[0x38bc], &u.szVendor[0], 4*3)) 213 { 214 g_offrtNtPbQuantumEnd = 0x3375; 215 g_cbrtNtPbQuantumEnd = 1; 216 g_offrtNtPbDpcQueueDepth = 0x3300 + 0x18; 217 } 218 /* WindowsVista.6002.090410-1830.amd64fre.Symbols 219 WindowsVista.6002.090130-1715.amd64fre.Symbols 220 WindowsVista.6002.090410-1830.amd64chk.Symbols */ 221 else if ( BuildNumber == 6002 222 && !memcmp(&pbPrcb[0x399c], &u.szVendor[0], 4*3)) 223 { 224 g_offrtNtPbQuantumEnd = 0x3475; 225 g_cbrtNtPbQuantumEnd = 1; 226 g_offrtNtPbDpcQueueDepth = 0x3400 + 0x18; 227 } 228 /* Windows7.7600.16539.amd64fre.win7_gdr.100226-1909 */ 229 else if ( BuildNumber == 7600 230 && !memcmp(&pbPrcb[0x4bb8], &u.szVendor[0], 4*3)) 231 { 232 g_offrtNtPbQuantumEnd = 0x21d9; 233 g_cbrtNtPbQuantumEnd = 1; 234 g_offrtNtPbDpcQueueDepth = 0x2180 + 0x18; 235 } 236 262 pbPrcb = (uint8_t *)pPcr->CurrentPrcb; 237 263 #else 238 264 # error "port me" 265 pbPrcb = NULL; 239 266 #endif 240 267 } 241 268 __except(EXCEPTION_EXECUTE_HANDLER) /** @todo this handler doesn't seem to work... Because of Irql? */ 242 269 { 243 g_offrtNtPbQuantumEnd = 0; 244 g_cbrtNtPbQuantumEnd = 0; 245 g_offrtNtPbDpcQueueDepth = 0; 246 } 247 248 KeLowerIrql(OldIrql); 249 250 #ifndef IN_GUEST /** @todo fix above for all Nt versions. */ 270 pbPrcb = NULL; 271 } 272 273 KeLowerIrql(OldIrql); /* Lowering the IRQL early in the hope that we may catch exceptions below. */ 274 275 /* 276 * Search the database 277 */ 278 if (pbPrcb) 279 { 280 /* Find the best matching kernel version based on build number. */ 281 uint32_t iBest = UINT32_MAX; 282 int32_t iBestDelta = INT32_MAX; 283 for (uint32_t i = 0; i < RT_ELEMENTS(g_artNtSdbSets); i++) 284 { 285 if (g_artNtSdbSets[i].OsVerInfo.fChecked != OsVerInfo.fChecked) 286 continue; 287 if (OsVerInfo.fSmp /*must-be-smp*/ && !g_artNtSdbSets[i].OsVerInfo.fSmp) 288 continue; 289 290 int32_t iDelta = RT_ABS((int32_t)OsVerInfo.uBuildNo - (int32_t)g_artNtSdbSets[i].OsVerInfo.uBuildNo); 291 if ( iDelta == 0 292 && (g_artNtSdbSets[i].OsVerInfo.uCsdNo == OsVerInfo.uCsdNo || OsVerInfo.uCsdNo == MY_NIL_CSD)) 293 { 294 /* prefect */ 295 iBestDelta = iDelta; 296 iBest = i; 297 break; 298 } 299 if ( iDelta < iBestDelta 300 || iBest == UINT32_MAX 301 || ( iDelta == iBestDelta 302 && OsVerInfo.uCsdNo != MY_NIL_CSD 303 && RT_ABS(g_artNtSdbSets[i ].OsVerInfo.uCsdNo - (int32_t)OsVerInfo.uCsdNo) 304 < RT_ABS(g_artNtSdbSets[iBest].OsVerInfo.uCsdNo - (int32_t)OsVerInfo.uCsdNo) 305 ) 306 ) 307 { 308 iBestDelta = iDelta; 309 iBest = i; 310 } 311 } 312 iBest = RT_ELEMENTS(g_artNtSdbSets)-1; 313 if (iBest < RT_ELEMENTS(g_artNtSdbSets)) 314 { 315 /* Try all sets: iBest -> End; iBest -> Start. */ 316 bool fDone = false; 317 int32_t i = iBest; 318 while ( i < RT_ELEMENTS(g_artNtSdbSets) 319 && !(fDone = rtR0NtTryMatchSymSet(&g_artNtSdbSets[i], pbPrcb, u.szVendor, &OsVerInfo))) 320 i++; 321 if (!fDone) 322 { 323 i = (int32_t)iBest - 1; 324 while ( i >= 0 325 && !(fDone = rtR0NtTryMatchSymSet(&g_artNtSdbSets[i], pbPrcb, u.szVendor, &OsVerInfo))) 326 i--; 327 } 328 } 329 else 330 DbgPrint("IPRT: Failed to locate data set.\n"); 331 } 332 else 333 DbgPrint("IPRT: Failed to get PCBR pointer.\n"); 334 335 #ifndef IN_GUEST 251 336 if (!g_offrtNtPbQuantumEnd && !g_offrtNtPbDpcQueueDepth) 252 337 DbgPrint("IPRT: Neither _KPRCB::QuantumEnd nor _KPRCB::DpcQueueDepth was not found! Kernel %u.%u %u %s\n", 253 MajorVersion, MinorVersion, BuildNumber,fChecked ? "checked" : "free");338 OsVerInfo.uMajorVer, OsVerInfo.uMinorVer, OsVerInfo.uBuildNo, OsVerInfo.fChecked ? "checked" : "free"); 254 339 # ifdef DEBUG 255 340 else 256 DbgPrint("IPRT: _KPRCB:{.QuantumEnd=%x/%d, .DpcQueueDepth=%x/%d} Kernel %u l.%ul %ul%s\n",341 DbgPrint("IPRT: _KPRCB:{.QuantumEnd=%x/%d, .DpcQueueDepth=%x/%d} Kernel %u.%u %u %s\n", 257 342 g_offrtNtPbQuantumEnd, g_cbrtNtPbQuantumEnd, g_offrtNtPbDpcQueueDepth, 258 MajorVersion, MinorVersion, BuildNumber,fChecked ? "checked" : "free");343 OsVerInfo.uMajorVer, OsVerInfo.uMinorVer, OsVerInfo.uBuildNo, OsVerInfo.fChecked ? "checked" : "free"); 259 344 # endif 345 #endif 346 347 /* 348 * Special IPI fun. 349 */ 350 g_pfnrtSendIpi = rtMpSendIpiDummy; 351 #ifndef IPRT_TARGET_NT4 352 if ( g_pfnrtNtHalRequestIpi 353 && OsVerInfo.uMajorVer == 6 354 && OsVerInfo.uMinorVer == 0) 355 { 356 /* Vista or Windows Server 2008 */ 357 g_pfnrtSendIpi = rtMpSendIpiVista; 358 } 359 else if ( g_pfnrtNtHalSendSoftwareInterrupt 360 && OsVerInfo.uMajorVer == 6 361 && OsVerInfo.uMinorVer == 1) 362 { 363 /* Windows 7 or Windows Server 2008 R2 */ 364 g_pfnrtSendIpi = rtMpSendIpiWin7; 365 } 366 /* Windows XP should send always send an IPI -> VERIFY */ 260 367 #endif 261 368 -
trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
r44529 r45443 41 41 typedef int (__stdcall *PFNRTSENDIPI)(RTCPUID idCpu); 42 42 typedef ULONG_PTR (__stdcall *PFNRTKEIPIGENERICCALL)(PKIPI_BROADCAST_WORKER BroadcastFunction, ULONG_PTR Context); 43 typedef ULONG (__stdcall *PFNRTRTLGETVERSION)(PRTL_OSVERSIONINFOEXW pVerInfo); 43 44 44 45 /******************************************************************************* … … 52 53 extern PFNRTSENDIPI g_pfnrtSendIpi; 53 54 extern PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 55 extern PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; 54 56 extern uint32_t g_offrtNtPbQuantumEnd; 55 57 extern uint32_t g_cbrtNtPbQuantumEnd; -
trunk/src/VBox/Runtime/r0drv/nt/ntBldSymDb.cpp
r45440 r45443 260 260 { 261 261 const char *pszStructName = figureCStructName(&g_aStructs[i]); 262 RTStrmPrintf(pOut, " RTNTSDBTYPE_%-20s %s \n", pszStructName, pszStructName);262 RTStrmPrintf(pOut, " RTNTSDBTYPE_%-20s %s;\n", pszStructName, pszStructName); 263 263 } 264 264 RTStrmPrintf(pOut, … … 273 273 "\n" 274 274 "#ifndef RTNTSDB_NO_DATA\n" 275 "const RTNTSDBSET g_ rtNtSdbSets[] = \n"275 "const RTNTSDBSET g_artNtSdbSets[] = \n" 276 276 "{\n"); 277 277 PMYSET pSet; … … 299 299 pSet->OsVerInfo.uCsdNo, 300 300 pSet->OsVerInfo.uBuildNo); 301 for (uint32_t i = 0; i < RT_ELEMENTS( g_aStructs); i++)302 { 303 const char *pszStructName = figureCStructName(& g_aStructs[i]);301 for (uint32_t i = 0; i < RT_ELEMENTS(pSet->aStructs); i++) 302 { 303 const char *pszStructName = figureCStructName(&pSet->aStructs[i]); 304 304 RTStrmPrintf(pOut, 305 305 " /* .%s = */\n" 306 306 " {\n", pszStructName); 307 PMYMEMBER paMembers = g_aStructs[i].paMembers;308 for (uint32_t j = 0; j < g_aStructs->cMembers; j++)307 PMYMEMBER paMembers = pSet->aStructs[i].paMembers; 308 for (uint32_t j = 0; j < pSet->aStructs[i].cMembers; j++) 309 309 { 310 310 const char *pszMemName = figureCMemberName(&paMembers[j]); … … 329 329 "\n"); 330 330 331 RTStrmPrintf(pOut, "\n#endif\n ");331 RTStrmPrintf(pOut, "\n#endif\n\n"); 332 332 } 333 333 … … 387 387 if (iDiff > 0 || pInsertBefore->enmArch > pSet->enmArch) 388 388 { 389 RTList Prepend(&pInsertBefore->ListEntry, &pSet->ListEntry);389 RTListNodeInsertBefore(&pInsertBefore->ListEntry, &pSet->ListEntry); 390 390 return RTEXITCODE_SUCCESS; 391 391 }
Note:
See TracChangeset
for help on using the changeset viewer.