summaryrefslogtreecommitdiff
path: root/runtime/arch/instruction_set_features.h
blob: cee8c5d42fa33b23b96ba270f7ccf1b4cc61a61d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
#define ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_

#include <iosfwd>
#include <memory>
#include <vector>

#include "arch/instruction_set.h"
#include "base/macros.h"

namespace art {

class ArmInstructionSetFeatures;
class Arm64InstructionSetFeatures;
class X86InstructionSetFeatures;
class X86_64InstructionSetFeatures;

// Abstraction used to describe features of a different instruction sets.
class InstructionSetFeatures {
 public:
  // Process a CPU variant string for the given ISA and create an InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromVariant(InstructionSet isa,
                                                                   const std::string& variant,
                                                                   std::string* error_msg);

  // Process a CPU variant string for the given ISA and make sure the features advertised
  // are supported by the hardware. This is needed for Pixel3a which wrongly
  // reports itself as cortex-a75.
  static std::unique_ptr<const InstructionSetFeatures> FromVariantAndHwcap(
      InstructionSet isa, const std::string& variant, std::string* error_msg);

  // Parse a bitmap for the given isa and create an InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromBitmap(InstructionSet isa,
                                                                  uint32_t bitmap);

  // Turn C pre-processor #defines into the equivalent instruction set features for kRuntimeISA.
  static std::unique_ptr<const InstructionSetFeatures> FromCppDefines();

  // Check if run-time detection of instruction set features is supported.
  //
  // Return: true - if run-time detection is supported on a target device.
  //         false - otherwise
  static bool IsRuntimeDetectionSupported() {
    return FromRuntimeDetection() != nullptr;
  }

  // Use run-time detection to get instruction set features.
  //
  // Return: a set of detected features or nullptr if runtime detection is not
  //         supported on a target.
  static std::unique_ptr<const InstructionSetFeatures> FromRuntimeDetection();

  // Process /proc/cpuinfo and use kRuntimeISA to produce InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromCpuInfo();

  // Process the auxiliary vector AT_HWCAP entry and use kRuntimeISA to produce
  // InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromHwcap();

  // Use assembly tests of the current runtime (ie kRuntimeISA) to determine the
  // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
  static std::unique_ptr<const InstructionSetFeatures> FromAssembly();

  // Use external cpu_features library.
  static std::unique_ptr<const InstructionSetFeatures> FromCpuFeatures();

  // Parse a string of the form "div,-atomic_ldrd_strd" adding and removing these features to
  // create a new InstructionSetFeatures.
  std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromString(
      const std::string& feature_list, std::string* error_msg) const WARN_UNUSED;

  // Are these features the same as the other given features?
  virtual bool Equals(const InstructionSetFeatures* other) const = 0;

  // For testing purposes we want to make sure that the system we run on has at
  // least the options we claim it has. In this cases Equals() does not
  // suffice and will cause the test to fail, since the runtime cpu feature
  // detection claims more capabilities then statically specified from the
  // build system.
  //
  // A good example of this is the armv8 ART test target that declares
  // "CPU_VARIANT=generic". If the generic target is specified and the code
  // is run on a platform with enhanced capabilities, the
  // instruction_set_features test will fail if we resort to using Equals()
  // between statically defined cpu features and runtime cpu features.
  //
  // For now we default this to Equals() in case the architecture does not
  // provide it.
  virtual bool HasAtLeast(const InstructionSetFeatures* other) const {
    return Equals(other);
  }

  // Return the ISA these features relate to.
  virtual InstructionSet GetInstructionSet() const = 0;

  // Return a bitmap that represents the features. ISA specific.
  virtual uint32_t AsBitmap() const = 0;

  // Return a string of the form "div,lpae" or "none".
  virtual std::string GetFeatureString() const = 0;

  // Down cast this ArmInstructionFeatures.
  const ArmInstructionSetFeatures* AsArmInstructionSetFeatures() const;

  // Down cast this Arm64InstructionFeatures.
  const Arm64InstructionSetFeatures* AsArm64InstructionSetFeatures() const;

  // Down cast this X86InstructionFeatures.
  const X86InstructionSetFeatures* AsX86InstructionSetFeatures() const;

  // Down cast this X86_64InstructionFeatures.
  const X86_64InstructionSetFeatures* AsX86_64InstructionSetFeatures() const;

  virtual ~InstructionSetFeatures() {}

 protected:
  InstructionSetFeatures() {}

  // Returns true if variant appears in the array variants.
  static bool FindVariantInArray(const char* const variants[], size_t num_variants,
                                 const std::string& variant);

  // Add architecture specific features in sub-classes.
  virtual std::unique_ptr<const InstructionSetFeatures>
      AddFeaturesFromSplitString(const std::vector<std::string>& features,
                                 std::string* error_msg) const = 0;

  // Add run-time detected architecture specific features in sub-classes.
  virtual std::unique_ptr<const InstructionSetFeatures>
      AddRuntimeDetectedFeatures(const InstructionSetFeatures *features ATTRIBUTE_UNUSED) const;

 private:
  DISALLOW_COPY_AND_ASSIGN(InstructionSetFeatures);
};
std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs);

}  // namespace art

#endif  // ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_