|
13 | 13 | #include <cstdint>
|
14 | 14 |
|
15 | 15 | #include "Shared/Debug.h"
|
| 16 | +#include "Utils/ELF.h" |
16 | 17 |
|
17 | 18 | #include "omptarget.h"
|
18 | 19 |
|
|
28 | 29 |
|
29 | 30 | using namespace llvm::ELF;
|
30 | 31 |
|
31 |
| -#include "ELF.h" |
32 |
| - |
33 | 32 | namespace llvm {
|
34 | 33 | namespace omp {
|
35 | 34 | namespace target {
|
@@ -71,99 +70,76 @@ inline uint32_t getImplicitArgsSize(uint16_t Version) {
|
71 | 70 | : sizeof(AMDGPUImplicitArgsTy);
|
72 | 71 | }
|
73 | 72 |
|
74 |
| -/// Parse a TargetID to get processor arch and feature map. |
75 |
| -/// Returns processor subarch. |
76 |
| -/// Returns TargetID features in \p FeatureMap argument. |
77 |
| -/// If the \p TargetID contains feature+, FeatureMap it to true. |
78 |
| -/// If the \p TargetID contains feature-, FeatureMap it to false. |
79 |
| -/// If the \p TargetID does not contain a feature (default), do not map it. |
80 |
| -StringRef parseTargetID(StringRef TargetID, StringMap<bool> &FeatureMap) { |
81 |
| - if (TargetID.empty()) |
82 |
| - return llvm::StringRef(); |
83 |
| - |
84 |
| - auto ArchFeature = TargetID.split(":"); |
85 |
| - auto Arch = ArchFeature.first; |
86 |
| - auto Features = ArchFeature.second; |
87 |
| - if (Features.empty()) |
88 |
| - return Arch; |
89 |
| - |
90 |
| - if (Features.contains("sramecc+")) { |
91 |
| - FeatureMap.insert(std::pair<StringRef, bool>("sramecc", true)); |
92 |
| - } else if (Features.contains("sramecc-")) { |
93 |
| - FeatureMap.insert(std::pair<StringRef, bool>("sramecc", false)); |
94 |
| - } |
95 |
| - if (Features.contains("xnack+")) { |
96 |
| - FeatureMap.insert(std::pair<StringRef, bool>("xnack", true)); |
97 |
| - } else if (Features.contains("xnack-")) { |
98 |
| - FeatureMap.insert(std::pair<StringRef, bool>("xnack", false)); |
99 |
| - } |
100 |
| - |
101 |
| - return Arch; |
102 |
| -} |
103 |
| - |
104 |
| -/// Check if an image is compatible with current system's environment. |
105 |
| -bool isImageCompatibleWithEnv(const __tgt_image_info *Info, |
106 |
| - StringRef EnvTargetID) { |
107 |
| - llvm::StringRef ImageTargetID(Info->Arch); |
108 |
| - // Compatible in case of exact match. |
109 |
| - if (ImageTargetID == EnvTargetID) { |
110 |
| - DP("Compatible: Exact match \t[Image: %s]\t:\t[Env: %s]\n", |
111 |
| - ImageTargetID.data(), EnvTargetID.data()); |
112 |
| - return true; |
113 |
| - } |
114 |
| - |
115 |
| - // Incompatible if Archs mismatch. |
116 |
| - StringMap<bool> ImgMap, EnvMap; |
117 |
| - StringRef ImgArch = utils::parseTargetID(ImageTargetID, ImgMap); |
118 |
| - StringRef EnvArch = utils::parseTargetID(EnvTargetID, EnvMap); |
119 |
| - |
120 |
| - // Both EnvArch and ImgArch can't be empty here. |
121 |
| - if (EnvArch.empty() || ImgArch.empty() || !ImgArch.contains(EnvArch)) { |
122 |
| - DP("Incompatible: Processor mismatch \t[Image: %s]\t:\t[Env: %s]\n", |
123 |
| - ImageTargetID.data(), EnvTargetID.data()); |
| 73 | +/// Check if an image is compatible with current system's environment. The |
| 74 | +/// system environment is given as a 'target-id' which has the form: |
| 75 | +/// |
| 76 | +/// <target-id> := <processor> ( ":" <target-feature> ( "+" | "-" ) )* |
| 77 | +/// |
| 78 | +/// If a feature is not specific as '+' or '-' it is assumed to be in an 'any' |
| 79 | +/// and is compatible with either '+' or '-'. The HSA runtime returns this |
| 80 | +/// information using the target-id, while we use the ELF header to determine |
| 81 | +/// these features. |
| 82 | +inline bool isImageCompatibleWithEnv(StringRef ImageArch, uint32_t ImageFlags, |
| 83 | + StringRef EnvTargetID) { |
| 84 | + StringRef EnvArch = EnvTargetID.split(":").first; |
| 85 | + |
| 86 | + // Trivial check if the base processors match. |
| 87 | + if (EnvArch != ImageArch) |
124 | 88 | return false;
|
125 |
| - } |
126 | 89 |
|
127 |
| - // Incompatible if image has more features than the environment, |
128 |
| - // irrespective of type or sign of features. |
129 |
| - if (ImgMap.size() > EnvMap.size()) { |
130 |
| - DP("Incompatible: Image has more features than the Environment \t[Image: " |
131 |
| - "%s]\t:\t[Env: %s]\n", |
132 |
| - ImageTargetID.data(), EnvTargetID.data()); |
133 |
| - return false; |
| 90 | + // Check if the image is requesting xnack on or off. |
| 91 | + switch (ImageFlags & EF_AMDGPU_FEATURE_XNACK_V4) { |
| 92 | + case EF_AMDGPU_FEATURE_XNACK_OFF_V4: |
| 93 | + // The image is 'xnack-' so the environment must be 'xnack-'. |
| 94 | + if (!EnvTargetID.contains("xnack-")) |
| 95 | + return false; |
| 96 | + break; |
| 97 | + case EF_AMDGPU_FEATURE_XNACK_ON_V4: |
| 98 | + // The image is 'xnack+' so the environment must be 'xnack+'. |
| 99 | + if (!EnvTargetID.contains("xnack+")) |
| 100 | + return false; |
| 101 | + break; |
| 102 | + case EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4: |
| 103 | + case EF_AMDGPU_FEATURE_XNACK_ANY_V4: |
| 104 | + default: |
| 105 | + break; |
134 | 106 | }
|
135 | 107 |
|
136 |
| - // Compatible if each target feature specified by the environment is |
137 |
| - // compatible with target feature of the image. The target feature is |
138 |
| - // compatible if the iamge does not specify it (meaning Any), or if it |
139 |
| - // specifies it with the same value (meaning On or Off). |
140 |
| - for (const auto &ImgFeature : ImgMap) { |
141 |
| - auto EnvFeature = EnvMap.find(ImgFeature.first()); |
142 |
| - if (EnvFeature == EnvMap.end() || |
143 |
| - (EnvFeature->first() == ImgFeature.first() && |
144 |
| - EnvFeature->second != ImgFeature.second)) { |
145 |
| - DP("Incompatible: Value of Image's non-ANY feature is not matching with " |
146 |
| - "the Environment's non-ANY feature \t[Image: %s]\t:\t[Env: %s]\n", |
147 |
| - ImageTargetID.data(), EnvTargetID.data()); |
| 108 | + // Check if the image is requesting sramecc on or off. |
| 109 | + switch (ImageFlags & EF_AMDGPU_FEATURE_SRAMECC_V4) { |
| 110 | + case EF_AMDGPU_FEATURE_SRAMECC_OFF_V4: |
| 111 | + // The image is 'sramecc-' so the environment must be 'sramecc-'. |
| 112 | + if (!EnvTargetID.contains("sramecc-")) |
148 | 113 | return false;
|
149 |
| - } |
| 114 | + break; |
| 115 | + case EF_AMDGPU_FEATURE_SRAMECC_ON_V4: |
| 116 | + // The image is 'sramecc+' so the environment must be 'sramecc+'. |
| 117 | + if (!EnvTargetID.contains("sramecc+")) |
| 118 | + return false; |
| 119 | + break; |
| 120 | + case EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4: |
| 121 | + case EF_AMDGPU_FEATURE_SRAMECC_ANY_V4: |
| 122 | + break; |
150 | 123 | }
|
151 | 124 |
|
152 |
| - // Image is compatible if all features of Environment are: |
153 |
| - // - either, present in the Image's features map with the same sign, |
154 |
| - // - or, the feature is missing from Image's features map i.e. it is |
155 |
| - // set to ANY |
156 |
| - DP("Compatible: Target IDs are compatible \t[Image: %s]\t:\t[Env: %s]\n", |
157 |
| - ImageTargetID.data(), EnvTargetID.data()); |
158 |
| - |
159 | 125 | return true;
|
160 | 126 | }
|
161 | 127 |
|
162 | 128 | // Check target image for XNACK mode (XNACK+, XNACK-ANY, XNACK-)
|
163 | 129 | [[nodiscard]] XnackBuildMode
|
164 | 130 | extractXnackModeFromBinary(const __tgt_device_image *TgtImage) {
|
165 | 131 | assert((TgtImage != nullptr) && "TgtImage is nullptr.");
|
166 |
| - u_int16_t EFlags = ::utils::elf::elf_get_eflags(TgtImage); |
| 132 | + StringRef Buffer(reinterpret_cast<const char *>(TgtImage->ImageStart), |
| 133 | + target::getPtrDiff(TgtImage->ImageEnd, TgtImage->ImageStart)); |
| 134 | + auto ElfOrErr = |
| 135 | + ELF64LEObjectFile::create(MemoryBufferRef(Buffer, /*Identifier=*/""), |
| 136 | + /*InitContent=*/false); |
| 137 | + if (auto Err = ElfOrErr.takeError()) { |
| 138 | + consumeError(std::move(Err)); |
| 139 | + DP("An error occured while reading ELF to extract XNACK mode\n"); |
| 140 | + return ELF::EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4; |
| 141 | + } |
| 142 | + u_int16_t EFlags = ElfOrErr->getPlatformFlags(); |
167 | 143 |
|
168 | 144 | utils::XnackBuildMode XnackFlags = EFlags & ELF::EF_AMDGPU_FEATURE_XNACK_V4;
|
169 | 145 |
|
|
0 commit comments