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/stringprintf.h" 23 #include "android-base/strings.h" 24 25 #include "base/logging.h" 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 "exynos-m1", 56 "exynos-m2", 57 "denver64", 58 "kryo" 59 }; 60 if (!FindVariantInArray(arm64_known_variants, arraysize(arm64_known_variants), variant)) { 61 std::ostringstream os; 62 os << "Unexpected CPU variant for Arm64: " << variant; 63 *error_msg = os.str(); 64 return nullptr; 65 } 66 } 67 68 // The variants that need a fix for 843419 are the same that need a fix for 835769. 69 bool needs_a53_843419_fix = needs_a53_835769_fix; 70 71 return Arm64FeaturesUniquePtr( 72 new Arm64InstructionSetFeatures(needs_a53_835769_fix, needs_a53_843419_fix)); 73 } 74 75 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromBitmap(uint32_t bitmap) { 76 bool is_a53 = (bitmap & kA53Bitfield) != 0; 77 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 78 } 79 80 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromCppDefines() { 81 const bool is_a53 = true; // Pessimistically assume all ARM64s are A53s. 82 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 83 } 84 85 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromCpuInfo() { 86 const bool is_a53 = true; // Conservative default. 87 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 88 } 89 90 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromHwcap() { 91 const bool is_a53 = true; // Pessimistically assume all ARM64s are A53s. 92 return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(is_a53, is_a53)); 93 } 94 95 Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromAssembly() { 96 UNIMPLEMENTED(WARNING); 97 return FromCppDefines(); 98 } 99 100 bool Arm64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const { 101 if (kArm64 != other->GetInstructionSet()) { 102 return false; 103 } 104 const Arm64InstructionSetFeatures* other_as_arm64 = other->AsArm64InstructionSetFeatures(); 105 return fix_cortex_a53_835769_ == other_as_arm64->fix_cortex_a53_835769_ && 106 fix_cortex_a53_843419_ == other_as_arm64->fix_cortex_a53_843419_; 107 } 108 109 uint32_t Arm64InstructionSetFeatures::AsBitmap() const { 110 return (fix_cortex_a53_835769_ ? kA53Bitfield : 0); 111 } 112 113 std::string Arm64InstructionSetFeatures::GetFeatureString() const { 114 std::string result; 115 if (fix_cortex_a53_835769_) { 116 result += "a53"; 117 } else { 118 result += "-a53"; 119 } 120 return result; 121 } 122 123 std::unique_ptr<const InstructionSetFeatures> 124 Arm64InstructionSetFeatures::AddFeaturesFromSplitString( 125 const std::vector<std::string>& features, std::string* error_msg) const { 126 bool is_a53 = fix_cortex_a53_835769_; 127 for (auto i = features.begin(); i != features.end(); i++) { 128 std::string feature = android::base::Trim(*i); 129 if (feature == "a53") { 130 is_a53 = true; 131 } else if (feature == "-a53") { 132 is_a53 = false; 133 } else { 134 *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str()); 135 return nullptr; 136 } 137 } 138 return std::unique_ptr<const InstructionSetFeatures>( 139 new Arm64InstructionSetFeatures(is_a53, is_a53)); 140 } 141 142 } // namespace art 143