1 /* 2 * Copyright (C) 2014 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 #include "instruction_set_features_arm64.h" 18 19 #include <fstream> 20 #include <sstream> 21 22 #include <android-base/logging.h> 23 #include <android-base/stringprintf.h> 24 #include <android-base/strings.h> 25 26 #include "base/stl_util.h" 27 28 namespace art { 29 30 using android::base::StringPrintf; 31 32 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromVariant( 33 const std::string& variant, std::string* error_msg) { 34 // Look for variants that need a fix for a53 erratum 835769. 35 static const char* arm64_variants_with_a53_835769_bug[] = { 36 // Pessimistically assume all generic CPUs are cortex-a53. 37 "default", 38 "generic", 39 "cortex-a53", 40 "cortex-a53.a57", 41 "cortex-a53.a72", 42 // Pessimistically assume all "big" cortex CPUs are paired with a cortex-a53. 43 "cortex-a57", 44 "cortex-a72", 45 "cortex-a73", 46 }; 47 bool needs_a53_835769_fix = FindVariantInArray(arm64_variants_with_a53_835769_bug, 48 arraysize(arm64_variants_with_a53_835769_bug), 49 variant); 50 51 if (!needs_a53_835769_fix) { 52 // Check to see if this is an expected variant. 53 static const char* arm64_known_variants[] = { 54 "cortex-a35", 55 "cortex-a55", 56 "cortex-a75", 57 "exynos-m1", 58 "exynos-m2", 59 "exynos-m3", 60 "denver64", 61 "kryo" 62 }; 63 if (!FindVariantInArray(arm64_known_variants, arraysize(arm64_known_variants), variant)) { 64 std::ostringstream os; 65 os << "Unexpected CPU variant for Arm64: " << variant; 66 *error_msg = os.str(); 67 return nullptr; 68 } 69 } 70 71 // The variants that need a fix for 843419 are the same that need a fix for 835769. 72 bool needs_a53_843419_fix = needs_a53_835769_fix; 73 74 return Arm64FeaturesUniquePtr( 75 new Arm64InstructionSetFeatures(needs_a53_835769_fix, needs_a53_843419_fix)); 76 } 77 78 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromBitmap(uint32_t bitmap) { 79 bool is_a53 = (bitmap & kA53Bitfield) != 0; 80 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 81 } 82 83 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromCppDefines() { 84 const bool is_a53 = true; // Pessimistically assume all ARM64s are A53s. 85 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 86 } 87 88 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromCpuInfo() { 89 const bool is_a53 = true; // Conservative default. 90 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 91 } 92 93 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromHwcap() { 94 const bool is_a53 = true; // Pessimistically assume all ARM64s are A53s. 95 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 96 } 97 98 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromAssembly() { 99 UNIMPLEMENTED(WARNING); 100 return FromCppDefines(); 101 } 102 103 bool Arm64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const { 104 if (InstructionSet::kArm64 != other->GetInstructionSet()) { 105 return false; 106 } 107 const Arm64InstructionSetFeatures* other_as_arm64 = other->AsArm64InstructionSetFeatures(); 108 return fix_cortex_a53_835769_ == other_as_arm64->fix_cortex_a53_835769_ && 109 fix_cortex_a53_843419_ == other_as_arm64->fix_cortex_a53_843419_; 110 } 111 112 uint32_t Arm64InstructionSetFeatures::AsBitmap() const { 113 return (fix_cortex_a53_835769_ ? kA53Bitfield : 0); 114 } 115 116 std::string Arm64InstructionSetFeatures::GetFeatureString() const { 117 std::string result; 118 if (fix_cortex_a53_835769_) { 119 result += "a53"; 120 } else { 121 result += "-a53"; 122 } 123 return result; 124 } 125 126 std::unique_ptr<const InstructionSetFeatures> 127 Arm64InstructionSetFeatures::AddFeaturesFromSplitString( 128 const std::vector<std::string>& features, std::string* error_msg) const { 129 bool is_a53 = fix_cortex_a53_835769_; 130 for (auto i = features.begin(); i != features.end(); i++) { 131 std::string feature = android::base::Trim(*i); 132 if (feature == "a53") { 133 is_a53 = true; 134 } else if (feature == "-a53") { 135 is_a53 = false; 136 } else { 137 *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str()); 138 return nullptr; 139 } 140 } 141 return std::unique_ptr<const InstructionSetFeatures>( 142 new Arm64InstructionSetFeatures(is_a53, is_a53)); 143 } 144 145 } // namespace art 146