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