From 293e8fa13d3f05e993771577a4c022deee5cbf6e Mon Sep 17 00:00:00 2001 From: Vy Nguyen Date: Thu, 25 Feb 2021 17:40:38 -0500 Subject: [PATCH] [llvm-exegesis] Disable the LBR check on AMD https://bugs.llvm.org/show_bug.cgi?id=48918 The bug reported a hang (or very very slow runtime) on a Zen2. Unfortunately, we don't have the hardware right now to debug it and I was not able to reproduce the bug on a HSW. Theory we've got is that the lbr-checking code could be confused on AMD. Differential Revision: https://reviews.llvm.org/D97504 --- llvm/include/llvm/Support/Host.h | 15 +++++++++ llvm/lib/Support/Host.cpp | 51 +++++++++++++++++++++-------- llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 16 ++++++--- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/llvm/include/llvm/Support/Host.h b/llvm/include/llvm/Support/Host.h index d4ef389..3a7397e 100644 --- a/llvm/include/llvm/Support/Host.h +++ b/llvm/include/llvm/Support/Host.h @@ -65,6 +65,21 @@ namespace sys { StringRef getHostCPUNameForARM(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForS390x(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForBPF(); + + /// Helper functions to extract CPU details from CPUID on x86. +#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) + namespace x86 { + enum class VendorSignatures { + UNKNOWN, + GENUINE_INTEL, + AUTHENTIC_AMD, + }; + + /// Returns the host CPU's vendor. + VendorSignatures getVendorSignature(); + } // namespace x86 +#endif } } } diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index d89518b..2b0451e 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -420,11 +420,6 @@ StringRef sys::detail::getHostCPUNameForBPF() { #if defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64__) || defined(_M_X64) -enum VendorSignatures { - SIG_INTEL = 0x756e6547 /* Genu */, - SIG_AMD = 0x68747541 /* Auth */ -}; - // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID // support. Consequently, for i386, the presence of CPUID is checked first @@ -498,6 +493,38 @@ static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, #endif } +namespace llvm { +namespace sys { +namespace detail { +namespace x86 { + +VendorSignatures getVendorSignature() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + + if (!isCpuIdSupported()) + return VendorSignatures::UNKNOWN; + + if (getX86CpuIDAndInfo(0, &EAX, &EBX, &ECX, &EDX) || EAX < 1) + return VendorSignatures::UNKNOWN; + + // "Genu ineI ntel" + if (EBX == 0x756e6547 && ECX == 0x6c65746e && EDX == 0x49656e69) + return VendorSignatures::GENUINE_INTEL; + + // "Auth enti cAMD" + if (EBX == 0x68747541 && ECX == 0x69746e65 && EDX == 0x444d4163) + return VendorSignatures::AUTHENTIC_AMD; + + return VendorSignatures::UNKNOWN; +} + +} // namespace x86 +} // namespace detail +} // namespace sys +} // namespace llvm + +using namespace llvm::sys::detail::x86; + /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return /// the 4 values in the specified arguments. If we can't run cpuid on the host, /// return true. @@ -1095,18 +1122,16 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, } StringRef sys::getHostCPUName() { - unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; - unsigned MaxLeaf, Vendor; - - if (!isCpuIdSupported()) + const VendorSignatures Vendor = getVendorSignature(); + if (Vendor == VendorSignatures::UNKNOWN) return "generic"; - if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1) - return "generic"; + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); unsigned Family = 0, Model = 0; unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0}; + unsigned MaxLeaf = 0; detectX86FamilyModel(EAX, &Family, &Model); getAvailableFeatures(ECX, EDX, MaxLeaf, Features); @@ -1117,10 +1142,10 @@ StringRef sys::getHostCPUName() { StringRef CPU; - if (Vendor == SIG_INTEL) { + if (Vendor == VendorSignatures::GENUINE_INTEL) { CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); - } else if (Vendor == SIG_AMD) { + } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) { CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); } diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 96781dd..67fb5d1 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Host.h" #include #include @@ -735,6 +736,8 @@ private: } Error checkFeatureSupport() const override { + using namespace sys::detail::x86; + // LBR is the only feature we conditionally support now. // So if LBR is not requested, then we should be able to run the benchmarks. if (LbrSamplingPeriod == 0) @@ -742,13 +745,18 @@ private: #if defined(__linux__) && defined(HAVE_LIBPFM) && \ defined(LIBPFM_HAS_FIELD_CYCLES) - // If the kernel supports it, the hardware still may not have it. - return X86LbrCounter::checkLbrSupport(); -#else + // FIXME: Fix this. + // https://bugs.llvm.org/show_bug.cgi?id=48918 + // For now, only do the check if we see an Intel machine because + // the counter uses some intel-specific magic and it could + // be confuse and think an AMD machine actually has LBR support. + if (getVendorSignature() == VendorSignatures::GENUINE_INTEL) + // If the kernel supports it, the hardware still may not have it. + return X86LbrCounter::checkLbrSupport(); +#endif return llvm::make_error( "LBR not supported on this kernel and/or platform", llvm::errc::not_supported); -#endif } std::unique_ptr withSavedState() const override { -- 2.7.4