1 //===-- checksum.cpp --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "checksum.h" 10 #include "atomic_helpers.h" 11 12 #if defined(__x86_64__) || defined(__i386__) 13 #include <cpuid.h> 14 #elif defined(__arm__) || defined(__aarch64__) 15 #if SCUDO_FUCHSIA 16 #include <zircon/features.h> 17 #include <zircon/syscalls.h> 18 #else 19 #include <sys/auxv.h> 20 #endif 21 #endif 22 23 namespace scudo { 24 25 Checksum HashAlgorithm = {Checksum::BSD}; 26 27 #if defined(__x86_64__) || defined(__i386__) 28 // i386 and x86_64 specific code to detect CRC32 hardware support via CPUID. 29 // CRC32 requires the SSE 4.2 instruction set. 30 #ifndef bit_SSE4_2 31 #define bit_SSE4_2 bit_SSE42 // clang and gcc have different defines. 32 #endif 33 34 #ifndef signature_HYGON_ebx // They are not defined in gcc. 35 // HYGON: "HygonGenuine". 36 #define signature_HYGON_ebx 0x6f677948 37 #define signature_HYGON_edx 0x6e65476e 38 #define signature_HYGON_ecx 0x656e6975 39 #endif 40 41 bool hasHardwareCRC32() { 42 u32 Eax, Ebx = 0, Ecx = 0, Edx = 0; 43 __get_cpuid(0, &Eax, &Ebx, &Ecx, &Edx); 44 const bool IsIntel = (Ebx == signature_INTEL_ebx) && 45 (Edx == signature_INTEL_edx) && 46 (Ecx == signature_INTEL_ecx); 47 const bool IsAMD = (Ebx == signature_AMD_ebx) && (Edx == signature_AMD_edx) && 48 (Ecx == signature_AMD_ecx); 49 const bool IsHygon = (Ebx == signature_HYGON_ebx) && 50 (Edx == signature_HYGON_edx) && 51 (Ecx == signature_HYGON_ecx); 52 if (!IsIntel && !IsAMD && !IsHygon) 53 return false; 54 __get_cpuid(1, &Eax, &Ebx, &Ecx, &Edx); 55 return !!(Ecx & bit_SSE4_2); 56 } 57 #elif defined(__arm__) || defined(__aarch64__) 58 #ifndef AT_HWCAP 59 #define AT_HWCAP 16 60 #endif 61 #ifndef HWCAP_CRC32 62 #define HWCAP_CRC32 (1U << 7) // HWCAP_CRC32 is missing on older platforms. 63 #endif 64 65 bool hasHardwareCRC32() { 66 #if SCUDO_FUCHSIA 67 u32 HWCap; 68 const zx_status_t Status = 69 zx_system_get_features(ZX_FEATURE_KIND_CPU, &HWCap); 70 if (Status != ZX_OK) 71 return false; 72 return !!(HWCap & ZX_ARM64_FEATURE_ISA_CRC32); 73 #else 74 return !!(getauxval(AT_HWCAP) & HWCAP_CRC32); 75 #endif // SCUDO_FUCHSIA 76 } 77 #else 78 // No hardware CRC32 implemented in Scudo for other architectures. 79 bool hasHardwareCRC32() { return false; } 80 #endif // defined(__x86_64__) || defined(__i386__) 81 82 } // namespace scudo 83