]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/scudo/scudo_utils.cpp
Update to zstd 1.3.2
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / scudo / scudo_utils.cpp
1 //===-- scudo_utils.cpp -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// Platform specific utility functions.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "scudo_utils.h"
15
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdarg.h>
19 #include <unistd.h>
20 #if defined(__x86_64__) || defined(__i386__)
21 # include <cpuid.h>
22 #endif
23 #if defined(__arm__) || defined(__aarch64__)
24 # include <sys/auxv.h>
25 #endif
26
27 // TODO(kostyak): remove __sanitizer *Printf uses in favor for our own less
28 //                complicated string formatting code. The following is a
29 //                temporary workaround to be able to use __sanitizer::VSNPrintf.
30 namespace __sanitizer {
31
32 extern int VSNPrintf(char *buff, int buff_length, const char *format,
33                      va_list args);
34
35 }  // namespace __sanitizer
36
37 namespace __scudo {
38
39 FORMAT(1, 2)
40 void NORETURN dieWithMessage(const char *Format, ...) {
41   // Our messages are tiny, 256 characters is more than enough.
42   char Message[256];
43   va_list Args;
44   va_start(Args, Format);
45   __sanitizer::VSNPrintf(Message, sizeof(Message), Format, Args);
46   va_end(Args);
47   RawWrite(Message);
48   Die();
49 }
50
51 #if defined(__x86_64__) || defined(__i386__)
52 // i386 and x86_64 specific code to detect CRC32 hardware support via CPUID.
53 // CRC32 requires the SSE 4.2 instruction set.
54 typedef struct {
55   u32 Eax;
56   u32 Ebx;
57   u32 Ecx;
58   u32 Edx;
59 } CPUIDRegs;
60
61 static void getCPUID(CPUIDRegs *Regs, u32 Level)
62 {
63   __get_cpuid(Level, &Regs->Eax, &Regs->Ebx, &Regs->Ecx, &Regs->Edx);
64 }
65
66 CPUIDRegs getCPUFeatures() {
67   CPUIDRegs VendorRegs = {};
68   getCPUID(&VendorRegs, 0);
69   bool IsIntel =
70       (VendorRegs.Ebx == signature_INTEL_ebx) &&
71       (VendorRegs.Edx == signature_INTEL_edx) &&
72       (VendorRegs.Ecx == signature_INTEL_ecx);
73   bool IsAMD =
74       (VendorRegs.Ebx == signature_AMD_ebx) &&
75       (VendorRegs.Edx == signature_AMD_edx) &&
76       (VendorRegs.Ecx == signature_AMD_ecx);
77   // Default to an empty feature set if not on a supported CPU.
78   CPUIDRegs FeaturesRegs = {};
79   if (IsIntel || IsAMD) {
80     getCPUID(&FeaturesRegs, 1);
81   }
82   return FeaturesRegs;
83 }
84
85 #ifndef bit_SSE4_2
86 # define bit_SSE4_2 bit_SSE42  // clang and gcc have different defines.
87 #endif
88
89 bool testCPUFeature(CPUFeature Feature)
90 {
91   CPUIDRegs FeaturesRegs = getCPUFeatures();
92
93   switch (Feature) {
94     case CRC32CPUFeature:  // CRC32 is provided by SSE 4.2.
95       return !!(FeaturesRegs.Ecx & bit_SSE4_2);
96     default:
97       break;
98   }
99   return false;
100 }
101 #elif defined(__arm__) || defined(__aarch64__)
102 // For ARM and AArch64, hardware CRC32 support is indicated in the
103 // AT_HWVAL auxiliary vector.
104
105 #ifndef HWCAP_CRC32
106 # define HWCAP_CRC32 (1<<7)  // HWCAP_CRC32 is missing on older platforms.
107 #endif
108
109 bool testCPUFeature(CPUFeature Feature) {
110   uptr HWCap = getauxval(AT_HWCAP);
111
112   switch (Feature) {
113     case CRC32CPUFeature:
114       return !!(HWCap & HWCAP_CRC32);
115     default:
116       break;
117   }
118   return false;
119 }
120 #else
121 bool testCPUFeature(CPUFeature Feature) {
122   return false;
123 }
124 #endif  // defined(__x86_64__) || defined(__i386__)
125
126 }  // namespace __scudo