1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_ 18 #define ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_ 19 20 #include <iosfwd> 21 #include <memory> 22 #include <vector> 23 24 #include "arch/instruction_set.h" 25 #include "base/macros.h" 26 27 namespace art HIDDEN { 28 29 class ArmInstructionSetFeatures; 30 class Arm64InstructionSetFeatures; 31 class Riscv64InstructionSetFeatures; 32 class X86InstructionSetFeatures; 33 class X86_64InstructionSetFeatures; 34 35 // Abstraction used to describe features of a different instruction sets. 36 class InstructionSetFeatures { 37 public: 38 // Process a CPU variant string for the given ISA and create an InstructionSetFeatures. 39 EXPORT static std::unique_ptr<const InstructionSetFeatures> FromVariant( 40 InstructionSet isa, const std::string& variant, std::string* error_msg); 41 42 // Process a CPU variant string for the given ISA and make sure the features advertised 43 // are supported by the hardware. This is needed for Pixel3a which wrongly 44 // reports itself as cortex-a75. 45 EXPORT static std::unique_ptr<const InstructionSetFeatures> FromVariantAndHwcap( 46 InstructionSet isa, const std::string& variant, std::string* error_msg); 47 48 // Parse a bitmap for the given isa and create an InstructionSetFeatures. 49 EXPORT static std::unique_ptr<const InstructionSetFeatures> FromBitmap(InstructionSet isa, 50 uint32_t bitmap); 51 52 // Turn C pre-processor #defines into the equivalent instruction set features for kRuntimeISA. 53 EXPORT static std::unique_ptr<const InstructionSetFeatures> FromCppDefines(); 54 55 // Check if run-time detection of instruction set features is supported. 56 // 57 // Return: true - if run-time detection is supported on a target device. 58 // false - otherwise IsRuntimeDetectionSupported()59 static bool IsRuntimeDetectionSupported() { 60 return FromRuntimeDetection() != nullptr; 61 } 62 63 // Use run-time detection to get instruction set features. 64 // 65 // Return: a set of detected features or nullptr if runtime detection is not 66 // supported on a target. 67 static std::unique_ptr<const InstructionSetFeatures> FromRuntimeDetection(); 68 69 // Process /proc/cpuinfo and use kRuntimeISA to produce InstructionSetFeatures. 70 static std::unique_ptr<const InstructionSetFeatures> FromCpuInfo(); 71 72 // Process the auxiliary vector AT_HWCAP entry and use kRuntimeISA to produce 73 // InstructionSetFeatures. 74 static std::unique_ptr<const InstructionSetFeatures> FromHwcap(); 75 76 // Use assembly tests of the current runtime (ie kRuntimeISA) to determine the 77 // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo. 78 static std::unique_ptr<const InstructionSetFeatures> FromAssembly(); 79 80 // Use external cpu_features library. 81 static std::unique_ptr<const InstructionSetFeatures> FromCpuFeatures(); 82 83 // Parse a string of the form "div,-atomic_ldrd_strd" adding and removing these features to 84 // create a new InstructionSetFeatures. 85 EXPORT std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromString( 86 const std::string& feature_list, std::string* error_msg) const WARN_UNUSED; 87 88 // Are these features the same as the other given features? 89 virtual bool Equals(const InstructionSetFeatures* other) const = 0; 90 91 // For testing purposes we want to make sure that the system we run on has at 92 // least the options we claim it has. In this cases Equals() does not 93 // suffice and will cause the test to fail, since the runtime cpu feature 94 // detection claims more capabilities then statically specified from the 95 // build system. 96 // 97 // A good example of this is the armv8 ART test target that declares 98 // "CPU_VARIANT=generic". If the generic target is specified and the code 99 // is run on a platform with enhanced capabilities, the 100 // instruction_set_features test will fail if we resort to using Equals() 101 // between statically defined cpu features and runtime cpu features. 102 // 103 // For now we default this to Equals() in case the architecture does not 104 // provide it. HasAtLeast(const InstructionSetFeatures * other)105 virtual bool HasAtLeast(const InstructionSetFeatures* other) const { 106 return Equals(other); 107 } 108 109 // Return the ISA these features relate to. 110 virtual InstructionSet GetInstructionSet() const = 0; 111 112 // Return a bitmap that represents the features. ISA specific. 113 virtual uint32_t AsBitmap() const = 0; 114 115 // Return a string of the form "div,lpae" or "none". 116 virtual std::string GetFeatureString() const = 0; 117 118 // Down cast this ArmInstructionFeatures. 119 const ArmInstructionSetFeatures* AsArmInstructionSetFeatures() const; 120 121 // Down cast this Arm64InstructionFeatures. 122 EXPORT const Arm64InstructionSetFeatures* AsArm64InstructionSetFeatures() const; 123 124 // Down cast this Riscv64InstructionFeatures. 125 EXPORT const Riscv64InstructionSetFeatures* AsRiscv64InstructionSetFeatures() const; 126 127 // Down cast this X86InstructionFeatures. 128 const X86InstructionSetFeatures* AsX86InstructionSetFeatures() const; 129 130 // Down cast this X86_64InstructionFeatures. 131 const X86_64InstructionSetFeatures* AsX86_64InstructionSetFeatures() const; 132 ~InstructionSetFeatures()133 virtual ~InstructionSetFeatures() {} 134 135 protected: InstructionSetFeatures()136 InstructionSetFeatures() {} 137 138 // Returns true if variant appears in the array variants. 139 static bool FindVariantInArray(const char* const variants[], size_t num_variants, 140 const std::string& variant); 141 142 // Add architecture specific features in sub-classes. 143 virtual std::unique_ptr<const InstructionSetFeatures> 144 AddFeaturesFromSplitString(const std::vector<std::string>& features, 145 std::string* error_msg) const = 0; 146 147 // Add run-time detected architecture specific features in sub-classes. 148 virtual std::unique_ptr<const InstructionSetFeatures> AddRuntimeDetectedFeatures( 149 [[maybe_unused]] const InstructionSetFeatures* features) const; 150 151 private: 152 DISALLOW_COPY_AND_ASSIGN(InstructionSetFeatures); 153 }; 154 EXPORT std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs); 155 156 } // namespace art 157 158 #endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_ 159