From c4a87925e2355f5e49e22bd8a3f73aef8599421a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 25 Mar 2016 15:34:53 -0700 Subject: [PATCH] Add system information to log file --- interface/src/main.cpp | 133 ++++++++++++++++++++ libraries/shared/src/CPUID.cpp | 13 ++ libraries/shared/src/CPUID.h | 214 +++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) create mode 100644 libraries/shared/src/CPUID.cpp create mode 100644 libraries/shared/src/CPUID.h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6db53de0d8..cb0dd42538 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -24,12 +25,19 @@ #include "Application.h" #include "InterfaceLogging.h" #include "MainWindow.h" +#include #ifdef HAS_BUGSPLAT #include #include #endif + +#ifdef Q_OS_WIN +#include +#endif + + int main(int argc, const char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes @@ -154,6 +162,131 @@ int main(int argc, const char* argv[]) { auto logPath = QDir::toNativeSeparators(app.getLogger()->getFilename()); mpSender.sendAdditionalFile(qPrintable(logPath)); #endif + { + // Write system information to log + qDebug() << "Build Information"; + qDebug().noquote() << "\tBuild ABI: " << QSysInfo::buildAbi(); + qDebug().noquote() << "\tBuild CPU Architecture: " << QSysInfo::buildCpuArchitecture(); + + qDebug().noquote() << "System Information"; + qDebug().noquote() << "\tProduct Name: " << QSysInfo::prettyProductName(); + qDebug().noquote() << "\tCPU Architecture: " << QSysInfo::currentCpuArchitecture(); + qDebug().noquote() << "\tKernel Type: " << QSysInfo::kernelType(); + qDebug().noquote() << "\tKernel Version: " << QSysInfo::kernelVersion(); + + auto macVersion = QSysInfo::macVersion(); + if (macVersion != QSysInfo::MV_None) { + qDebug() << "\tMac Version: " << macVersion; + } + + auto windowsVersion = QSysInfo::windowsVersion(); + if (windowsVersion != QSysInfo::WV_None) { + qDebug() << "\tWindows Version: " << windowsVersion; + } + +#ifdef Q_OS_WIN + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + + qDebug() << "SYSTEM_INFO"; + qDebug().noquote() << "\tOEM ID: " << si.dwOemId; + qDebug().noquote() << "\tProcessor Architecture: " << si.wProcessorArchitecture; + qDebug().noquote() << "\tProcessor Type: " << si.dwProcessorType; + qDebug().noquote() << "\tProcessor Level: " << si.wProcessorLevel; + qDebug().noquote() << "\tProcessor Revision: " + << QString("0x%1").arg(si.wProcessorRevision, 4, 16, QChar('0')); + qDebug().noquote() << "\tNumber of Processors: " << si.dwNumberOfProcessors; + qDebug().noquote() << "\tPage size: " << si.dwPageSize << " Bytes"; + qDebug().noquote() << "\tMin Application Address: " + << QString("0x%1").arg(qulonglong(si.lpMinimumApplicationAddress), 16, 16, QChar('0')); + qDebug().noquote() << "\tMax Application Address: " + << QString("0x%1").arg(qulonglong(si.lpMaximumApplicationAddress), 16, 16, QChar('0')); + + const double BYTES_TO_MEGABYTE = 1.0 / (1024 * 1024); + + qDebug() << "MEMORYSTATUSEX"; + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + if (GlobalMemoryStatusEx(&ms)) { + qDebug().noquote() << QString("\tCurrent System Memory Usage: %1%").arg(ms.dwMemoryLoad); + qDebug().noquote() << QString("\tAvail Physical Memory: %1 MB").arg(ms.ullAvailPhys * BYTES_TO_MEGABYTE, 20, 'f', 2); + qDebug().noquote() << QString("\tTotal Physical Memory: %1 MB").arg(ms.ullTotalPhys * BYTES_TO_MEGABYTE, 20, 'f', 2); + qDebug().noquote() << QString("\tAvail in Page File: %1 MB").arg(ms.ullAvailPageFile * BYTES_TO_MEGABYTE, 20, 'f', 2); + qDebug().noquote() << QString("\tTotal in Page File: %1 MB").arg(ms.ullTotalPageFile * BYTES_TO_MEGABYTE, 20, 'f', 2); + qDebug().noquote() << QString("\tAvail Virtual Memory: %1 MB").arg(ms.ullAvailVirtual * BYTES_TO_MEGABYTE, 20, 'f', 2); + qDebug().noquote() << QString("\tTotal Virtual Memory: %1 MB").arg(ms.ullTotalVirtual * BYTES_TO_MEGABYTE, 20, 'f', 2); + } else { + qDebug() << "\tFailed to retrieve memory status: " << GetLastError(); + } + + qDebug() << "CPUID"; + + auto printSupported = [](QString isaFeatureName, bool isSupported) { + qDebug().nospace().noquote() << "\t[" << (isSupported ? "x" : " ") << "] " << isaFeatureName; + }; + + qDebug() << "\tCPU Vendor: " << CPUID::Vendor().c_str(); + qDebug() << "\tCPU Brand: " << CPUID::Brand().c_str(); + + printSupported("3DNOW", CPUID::_3DNOW()); + printSupported("3DNOWEXT", CPUID::_3DNOWEXT()); + printSupported("ABM", CPUID::ABM()); + printSupported("ADX", CPUID::ADX()); + printSupported("AES", CPUID::AES()); + printSupported("AVX", CPUID::AVX()); + printSupported("AVX2", CPUID::AVX2()); + printSupported("AVX512CD", CPUID::AVX512CD()); + printSupported("AVX512ER", CPUID::AVX512ER()); + printSupported("AVX512F", CPUID::AVX512F()); + printSupported("AVX512PF", CPUID::AVX512PF()); + printSupported("BMI1", CPUID::BMI1()); + printSupported("BMI2", CPUID::BMI2()); + printSupported("CLFSH", CPUID::CLFSH()); + printSupported("CMPXCHG16B", CPUID::CMPXCHG16B()); + printSupported("CX8", CPUID::CX8()); + printSupported("ERMS", CPUID::ERMS()); + printSupported("F16C", CPUID::F16C()); + printSupported("FMA", CPUID::FMA()); + printSupported("FSGSBASE", CPUID::FSGSBASE()); + printSupported("FXSR", CPUID::FXSR()); + printSupported("HLE", CPUID::HLE()); + printSupported("INVPCID", CPUID::INVPCID()); + printSupported("LAHF", CPUID::LAHF()); + printSupported("LZCNT", CPUID::LZCNT()); + printSupported("MMX", CPUID::MMX()); + printSupported("MMXEXT", CPUID::MMXEXT()); + printSupported("MONITOR", CPUID::MONITOR()); + printSupported("MOVBE", CPUID::MOVBE()); + printSupported("MSR", CPUID::MSR()); + printSupported("OSXSAVE", CPUID::OSXSAVE()); + printSupported("PCLMULQDQ", CPUID::PCLMULQDQ()); + printSupported("POPCNT", CPUID::POPCNT()); + printSupported("PREFETCHWT1", CPUID::PREFETCHWT1()); + printSupported("RDRAND", CPUID::RDRAND()); + printSupported("RDSEED", CPUID::RDSEED()); + printSupported("RDTSCP", CPUID::RDTSCP()); + printSupported("RTM", CPUID::RTM()); + printSupported("SEP", CPUID::SEP()); + printSupported("SHA", CPUID::SHA()); + printSupported("SSE", CPUID::SSE()); + printSupported("SSE2", CPUID::SSE2()); + printSupported("SSE3", CPUID::SSE3()); + printSupported("SSE4.1", CPUID::SSE41()); + printSupported("SSE4.2", CPUID::SSE42()); + printSupported("SSE4a", CPUID::SSE4a()); + printSupported("SSSE3", CPUID::SSSE3()); + printSupported("SYSCALL", CPUID::SYSCALL()); + printSupported("TBM", CPUID::TBM()); + printSupported("XOP", CPUID::XOP()); + printSupported("XSAVE", CPUID::XSAVE()); +#endif + + qDebug() << "Environment Variables"; + auto envVariables = QProcessEnvironment::systemEnvironment().toStringList(); + for (auto& env : envVariables) { + qDebug().noquote().nospace() << "\t" << env; + } + } QTranslator translator; translator.load("i18n/interface_en"); diff --git a/libraries/shared/src/CPUID.cpp b/libraries/shared/src/CPUID.cpp new file mode 100644 index 0000000000..474e5537b3 --- /dev/null +++ b/libraries/shared/src/CPUID.cpp @@ -0,0 +1,13 @@ +// +// CPUID.cpp +// +// Created by Ryan Huffman on 3/25/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "CPUID.h" + +const CPUID::CPUID_Internal CPUID::CPU_Rep; \ No newline at end of file diff --git a/libraries/shared/src/CPUID.h b/libraries/shared/src/CPUID.h new file mode 100644 index 0000000000..4040bbad05 --- /dev/null +++ b/libraries/shared/src/CPUID.h @@ -0,0 +1,214 @@ +// +// CPUID.h +// +// Adapted from Microsoft's example for using the cpuid intrinsic, +// found at https://msdn.microsoft.com/en-us/library/hskdteyh.aspx +// +// Provides acccess to information provided by the CPUID opcode +// +// TODO: Generalize to work outside of Windows. +// +// Created by Ryan Huffman on 3/25/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_CPUID_h +#define hifi_CPUID_h + +#include + +#include +#include +#include +#include + +#ifdef Q_OS_WIN + +#include + +class CPUID +{ + // forward declarations + class CPUID_Internal; + +public: + // getters + static std::string Vendor(void) { return CPU_Rep.vendor_; } + static std::string Brand(void) { return CPU_Rep.brand_; } + + static bool SSE3(void) { return CPU_Rep.f_1_ECX_[0]; } + static bool PCLMULQDQ(void) { return CPU_Rep.f_1_ECX_[1]; } + static bool MONITOR(void) { return CPU_Rep.f_1_ECX_[3]; } + static bool SSSE3(void) { return CPU_Rep.f_1_ECX_[9]; } + static bool FMA(void) { return CPU_Rep.f_1_ECX_[12]; } + static bool CMPXCHG16B(void) { return CPU_Rep.f_1_ECX_[13]; } + static bool SSE41(void) { return CPU_Rep.f_1_ECX_[19]; } + static bool SSE42(void) { return CPU_Rep.f_1_ECX_[20]; } + static bool MOVBE(void) { return CPU_Rep.f_1_ECX_[22]; } + static bool POPCNT(void) { return CPU_Rep.f_1_ECX_[23]; } + static bool AES(void) { return CPU_Rep.f_1_ECX_[25]; } + static bool XSAVE(void) { return CPU_Rep.f_1_ECX_[26]; } + static bool OSXSAVE(void) { return CPU_Rep.f_1_ECX_[27]; } + static bool AVX(void) { return CPU_Rep.f_1_ECX_[28]; } + static bool F16C(void) { return CPU_Rep.f_1_ECX_[29]; } + static bool RDRAND(void) { return CPU_Rep.f_1_ECX_[30]; } + + static bool MSR(void) { return CPU_Rep.f_1_EDX_[5]; } + static bool CX8(void) { return CPU_Rep.f_1_EDX_[8]; } + static bool SEP(void) { return CPU_Rep.f_1_EDX_[11]; } + static bool CMOV(void) { return CPU_Rep.f_1_EDX_[15]; } + static bool CLFSH(void) { return CPU_Rep.f_1_EDX_[19]; } + static bool MMX(void) { return CPU_Rep.f_1_EDX_[23]; } + static bool FXSR(void) { return CPU_Rep.f_1_EDX_[24]; } + static bool SSE(void) { return CPU_Rep.f_1_EDX_[25]; } + static bool SSE2(void) { return CPU_Rep.f_1_EDX_[26]; } + + static bool FSGSBASE(void) { return CPU_Rep.f_7_EBX_[0]; } + static bool BMI1(void) { return CPU_Rep.f_7_EBX_[3]; } + static bool HLE(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[4]; } + static bool AVX2(void) { return CPU_Rep.f_7_EBX_[5]; } + static bool BMI2(void) { return CPU_Rep.f_7_EBX_[8]; } + static bool ERMS(void) { return CPU_Rep.f_7_EBX_[9]; } + static bool INVPCID(void) { return CPU_Rep.f_7_EBX_[10]; } + static bool RTM(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[11]; } + static bool AVX512F(void) { return CPU_Rep.f_7_EBX_[16]; } + static bool RDSEED(void) { return CPU_Rep.f_7_EBX_[18]; } + static bool ADX(void) { return CPU_Rep.f_7_EBX_[19]; } + static bool AVX512PF(void) { return CPU_Rep.f_7_EBX_[26]; } + static bool AVX512ER(void) { return CPU_Rep.f_7_EBX_[27]; } + static bool AVX512CD(void) { return CPU_Rep.f_7_EBX_[28]; } + static bool SHA(void) { return CPU_Rep.f_7_EBX_[29]; } + + static bool PREFETCHWT1(void) { return CPU_Rep.f_7_ECX_[0]; } + + static bool LAHF(void) { return CPU_Rep.f_81_ECX_[0]; } + static bool LZCNT(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_ECX_[5]; } + static bool ABM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[5]; } + static bool SSE4a(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[6]; } + static bool XOP(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[11]; } + static bool TBM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[21]; } + + static bool SYSCALL(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[11]; } + static bool MMXEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[22]; } + static bool RDTSCP(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[27]; } + static bool _3DNOWEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[30]; } + static bool _3DNOW(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[31]; } + +private: + static const CPUID_Internal CPU_Rep; + + class CPUID_Internal + { + public: + CPUID_Internal() + : nIds_ { 0 }, + nExIds_ { 0 }, + isIntel_ { false }, + isAMD_ { false }, + f_1_ECX_ { 0 }, + f_1_EDX_ { 0 }, + f_7_EBX_ { 0 }, + f_7_ECX_ { 0 }, + f_81_ECX_ { 0 }, + f_81_EDX_ { 0 }, + data_ {}, + extdata_ {} + { + //int cpuInfo[4] = {-1}; + std::array cpui; + + // Calling __cpuid with 0x0 as the function_id argument + // gets the number of the highest valid function ID. + __cpuid(cpui.data(), 0); + nIds_ = cpui[0]; + + for (int i = 0; i <= nIds_; ++i) + { + __cpuidex(cpui.data(), i, 0); + data_.push_back(cpui); + } + + // Capture vendor string + char vendor[0x20]; + memset(vendor, 0, sizeof(vendor)); + *reinterpret_cast(vendor) = data_[0][1]; + *reinterpret_cast(vendor + 4) = data_[0][3]; + *reinterpret_cast(vendor + 8) = data_[0][2]; + vendor_ = vendor; + if (vendor_ == "GenuineIntel") + { + isIntel_ = true; + } + else if (vendor_ == "AuthenticAMD") + { + isAMD_ = true; + } + + // load bitset with flags for function 0x00000001 + if (nIds_ >= 1) + { + f_1_ECX_ = data_[1][2]; + f_1_EDX_ = data_[1][3]; + } + + // load bitset with flags for function 0x00000007 + if (nIds_ >= 7) + { + f_7_EBX_ = data_[7][1]; + f_7_ECX_ = data_[7][2]; + } + + // Calling __cpuid with 0x80000000 as the function_id argument + // gets the number of the highest valid extended ID. + __cpuid(cpui.data(), 0x80000000); + nExIds_ = cpui[0]; + + char brand[0x40]; + memset(brand, 0, sizeof(brand)); + + for (int i = 0x80000000; i <= nExIds_; ++i) + { + __cpuidex(cpui.data(), i, 0); + extdata_.push_back(cpui); + } + + // load bitset with flags for function 0x80000001 + if (nExIds_ >= 0x80000001) + { + f_81_ECX_ = extdata_[1][2]; + f_81_EDX_ = extdata_[1][3]; + } + + // Interpret CPU brand string if reported + if (nExIds_ >= 0x80000004) + { + memcpy(brand, extdata_[2].data(), sizeof(cpui)); + memcpy(brand + 16, extdata_[3].data(), sizeof(cpui)); + memcpy(brand + 32, extdata_[4].data(), sizeof(cpui)); + brand_ = brand; + } + }; + + int nIds_; + int nExIds_; + std::string vendor_; + std::string brand_; + bool isIntel_; + bool isAMD_; + std::bitset<32> f_1_ECX_; + std::bitset<32> f_1_EDX_; + std::bitset<32> f_7_EBX_; + std::bitset<32> f_7_ECX_; + std::bitset<32> f_81_ECX_; + std::bitset<32> f_81_EDX_; + std::vector> data_; + std::vector> extdata_; + }; +}; + +#endif + +#endif // hifi_CPUID_h