/src/botan/src/lib/utils/cpuid/cpuid.cpp
Line | Count | Source |
1 | | /* |
2 | | * Runtime CPU detection |
3 | | * (C) 2009,2010,2013,2017,2023 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/internal/cpuid.h> |
9 | | |
10 | | #include <botan/exceptn.h> |
11 | | #include <botan/internal/parsing.h> |
12 | | |
13 | | #if defined(BOTAN_HAS_OS_UTILS) |
14 | | #include <botan/internal/os_utils.h> |
15 | | #endif |
16 | | |
17 | | namespace Botan { |
18 | | |
19 | | #if !defined(BOTAN_HAS_CPUID_DETECTION) |
20 | | uint32_t CPUFeature::as_u32() const { |
21 | | throw Invalid_State("CPUFeature invalid bit"); |
22 | | } |
23 | | |
24 | | std::optional<CPUFeature> CPUFeature::from_string(std::string_view) { |
25 | | return {}; |
26 | | } |
27 | | |
28 | | std::string CPUFeature::to_string() const { |
29 | | throw Invalid_State("CPUFeature invalid bit"); |
30 | | } |
31 | | #endif |
32 | | |
33 | | //static |
34 | 0 | std::string CPUID::to_string() { |
35 | 0 | std::vector<std::string> flags; |
36 | |
|
37 | 0 | const uint32_t bitset = state().bitset(); |
38 | |
|
39 | 0 | for(size_t i = 0; i != 32; ++i) { |
40 | 0 | const uint32_t b = static_cast<uint32_t>(1) << i; |
41 | 0 | if((bitset & b) == b) { |
42 | | // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) |
43 | 0 | flags.push_back(CPUFeature(static_cast<CPUFeature::Bit>(b)).to_string()); |
44 | 0 | } |
45 | 0 | } |
46 | |
|
47 | 0 | return string_join(flags, ' '); |
48 | 0 | } |
49 | | |
50 | | //static |
51 | 0 | void CPUID::initialize() { |
52 | 0 | state() = CPUID_Data(); |
53 | 0 | } |
54 | | |
55 | | #if defined(BOTAN_HAS_CPUID_DETECTION) |
56 | | |
57 | | namespace { |
58 | | |
59 | 0 | uint32_t cleared_cpuid_bits() { |
60 | 0 | uint32_t cleared = 0; |
61 | |
|
62 | 0 | #if defined(BOTAN_HAS_OS_UTILS) |
63 | 0 | std::string clear_cpuid_env; |
64 | 0 | if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID")) { |
65 | 0 | for(const auto& cpuid : split_on(clear_cpuid_env, ',')) { |
66 | 0 | if(auto bit = CPUID::bit_from_string(cpuid)) { |
67 | 0 | cleared |= bit->as_u32(); |
68 | 0 | } |
69 | 0 | } |
70 | 0 | } |
71 | 0 | #endif |
72 | |
|
73 | 0 | return cleared; |
74 | 0 | } |
75 | | |
76 | | } // namespace |
77 | | |
78 | | #endif |
79 | | |
80 | 0 | CPUID::CPUID_Data::CPUID_Data() { |
81 | | // NOLINTBEGIN(*-prefer-member-initializer) |
82 | 0 | #if defined(BOTAN_HAS_CPUID_DETECTION) |
83 | 0 | m_processor_features = detect_cpu_features(~cleared_cpuid_bits()); |
84 | | #else |
85 | | m_processor_features = 0; |
86 | | #endif |
87 | | // NOLINTEND(*-prefer-member-initializer) |
88 | 0 | } |
89 | | |
90 | 0 | std::optional<CPUFeature> CPUID::bit_from_string(std::string_view tok) { |
91 | 0 | return CPUFeature::from_string(tok); |
92 | 0 | } |
93 | | |
94 | | } // namespace Botan |