fix: ignore subDeviceId token instead of skipping builtins resolve

Previous implementation skipped resolving the subDeviceId token, which
caused in returning the LinkedPartially status if token was present.
It could result in ZE_RESULT_ERROR_INVALID_MODULE_UNLINKED when kernel
was created and crashing an app.

Related-To: NEO-6875, HSD-14015133115
Signed-off-by: Naklicki, Mateusz <mateusz.naklicki@intel.com>
This commit is contained in:
Naklicki, Mateusz
2023-09-04 14:11:37 +00:00
committed by Compute-Runtime-Automation
parent 6d1c673a70
commit ff57bec1f0
14 changed files with 94 additions and 34 deletions

View File

@@ -55,6 +55,7 @@ struct WhiteBox<::L0::Module> : public ::L0::ModuleImp {
using BaseClass::device;
using BaseClass::exportedFunctionsSurface;
using BaseClass::importedSymbolAllocations;
using BaseClass::isaSegmentsForPatching;
using BaseClass::isFullyLinked;
using BaseClass::isFunctionSymbolExportEnabled;
using BaseClass::isGlobalSymbolExportEnabled;

View File

@@ -2018,6 +2018,73 @@ TEST_F(ModuleDynamicLinkTest, givenUnresolvedSymbolsWhenModuleIsCreatedThenIsaAl
EXPECT_FALSE(module->isFullyLinked);
}
TEST_F(ModuleDynamicLinkTest, givenModuleWithUnresolvedSymbolWhenKernelIsCreatedThenErrorIsReturned) {
auto zebinData = std::make_unique<ZebinTestData::ZebinWithL0TestCommonModule>(device->getHwInfo());
const auto &src = zebinData->storage;
ze_module_desc_t moduleDesc = {};
moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.data());
moduleDesc.inputSize = src.size();
ModuleBuildLog *moduleBuildLog = nullptr;
auto module = std::make_unique<Module>(device, moduleBuildLog, ModuleType::User);
ASSERT_NE(nullptr, module.get());
NEO::Linker::RelocationInfo unresolvedRelocation;
unresolvedRelocation.symbolName = "unresolved";
auto linkerInput = std::make_unique<::WhiteBox<NEO::LinkerInput>>();
linkerInput->dataRelocations.push_back(unresolvedRelocation);
linkerInput->traits.requiresPatchingOfGlobalVariablesBuffer = true;
module->unresolvedExternalsInfo.push_back({unresolvedRelocation});
module->translationUnit->programInfo.linkerInput = std::move(linkerInput);
module->initialize(&moduleDesc, neoDevice);
ASSERT_FALSE(module->isFullyLinked);
ze_kernel_handle_t kernelHandle;
ze_kernel_desc_t kernelDesc = {};
kernelDesc.pKernelName = "nonexistent_kernel";
ze_result_t res = module->createKernel(&kernelDesc, &kernelHandle);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_MODULE_UNLINKED, res);
}
TEST_F(ModuleDynamicLinkTest, givenModuleWithSubDeviceIDSymbolToResolveWhenKernelIsCreatedThenSuccessIsReturned) {
auto zebinData = std::make_unique<ZebinTestData::ZebinWithL0TestCommonModule>(device->getHwInfo());
const auto &src = zebinData->storage;
ze_module_desc_t moduleDesc = {};
moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.data());
moduleDesc.inputSize = src.size();
ModuleBuildLog *moduleBuildLog = nullptr;
auto module = std::make_unique<Module>(device, moduleBuildLog, ModuleType::User);
ASSERT_NE(nullptr, module.get());
module->unresolvedExternalsInfo.push_back({{"__SubDeviceID", 0, NEO::Linker::RelocationInfo::Type::AddressLow, NEO::SegmentType::Instructions}, 0u, false});
module->unresolvedExternalsInfo.push_back({{"__SubDeviceID", 64, NEO::Linker::RelocationInfo::Type::AddressHigh, NEO::SegmentType::Instructions}, 0u, false});
std::vector<char> instructionSegment;
instructionSegment.resize(128u);
module->isaSegmentsForPatching.push_back({instructionSegment.data(), 64u});
module->isaSegmentsForPatching.push_back({&instructionSegment[64], 64u});
module->initialize(&moduleDesc, neoDevice);
ASSERT_TRUE(module->isFullyLinked);
ze_kernel_handle_t kernelHandle;
ze_kernel_desc_t kernelDesc = {};
kernelDesc.pKernelName = "test";
ze_result_t res = module->createKernel(&kernelDesc, &kernelHandle);
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
Kernel::fromHandle(kernelHandle)->destroy();
}
TEST_F(ModuleDynamicLinkTests, givenModuleWithFunctionDependenciesWhenOtherModuleDefinesThisFunctionThenBarrierCountIsProperlyResolved) {
std::vector<ze_module_handle_t> hModules = {module0->toHandle(), module1->toHandle()};

View File

@@ -325,14 +325,8 @@ LinkingStatus Linker::link(const SegmentInfo &globalVariablesSegInfo, const Segm
patchDataSegments(globalVariablesSegInfo, globalConstantsSegInfo, globalVariablesSeg, globalConstantsSeg,
outUnresolvedExternals, pDevice, constantsInitData, constantsInitDataSize, variablesInitData, variablesInitDataSize);
removeLocalSymbolsFromRelocatedSymbols();
resolveImplicitArgs(kernelDescriptors, pDevice);
auto &productHelper = pDevice->getProductHelper();
auto releaseHelper = pDevice->getReleaseHelper();
if (productHelper.isResolvingBuiltinsNeeded(releaseHelper)) {
resolveBuiltins(pDevice, outUnresolvedExternals, instructionsSegments);
}
resolveBuiltins(pDevice, outUnresolvedExternals, instructionsSegments);
if (initialUnresolvedExternalsCount < outUnresolvedExternals.size()) {
return LinkingStatus::LinkedPartially;
@@ -662,16 +656,20 @@ void Linker::resolveImplicitArgs(const KernelDescriptorsT &kernelDescriptors, De
}
void Linker::resolveBuiltins(Device *pDevice, UnresolvedExternals &outUnresolvedExternals, const std::vector<PatchableSegment> &instructionsSegments) {
auto &productHelper = pDevice->getProductHelper();
auto releaseHelper = pDevice->getReleaseHelper();
int vecIndex = static_cast<int>(outUnresolvedExternals.size() - 1u);
for (; vecIndex >= 0; --vecIndex) {
if (outUnresolvedExternals[vecIndex].unresolvedRelocation.symbolName == subDeviceID) {
RelocatedSymbol<SymbolInfo> symbol;
symbol.gpuAddress = static_cast<uintptr_t>(pDevice->getDefaultEngine().commandStreamReceiver->getWorkPartitionAllocationGpuAddress());
auto relocAddress = ptrOffset(instructionsSegments[outUnresolvedExternals[vecIndex].instructionsSegmentId].hostPointer,
static_cast<uintptr_t>(outUnresolvedExternals[vecIndex].unresolvedRelocation.offset));
NEO::Linker::patchAddress(relocAddress, symbol.gpuAddress, outUnresolvedExternals[vecIndex].unresolvedRelocation);
if (productHelper.isResolvingSubDeviceIDNeeded(releaseHelper)) {
RelocatedSymbol<SymbolInfo> symbol;
symbol.gpuAddress = static_cast<uintptr_t>(pDevice->getDefaultEngine().commandStreamReceiver->getWorkPartitionAllocationGpuAddress());
auto relocAddress = ptrOffset(instructionsSegments[outUnresolvedExternals[vecIndex].instructionsSegmentId].hostPointer,
static_cast<uintptr_t>(outUnresolvedExternals[vecIndex].unresolvedRelocation.offset));
NEO::Linker::patchAddress(relocAddress, symbol.gpuAddress, outUnresolvedExternals[vecIndex].unresolvedRelocation);
}
outUnresolvedExternals[vecIndex] = outUnresolvedExternals[outUnresolvedExternals.size() - 1u];
outUnresolvedExternals.resize(outUnresolvedExternals.size() - 1u);
}

View File

@@ -209,7 +209,7 @@ class ProductHelper {
virtual bool isCachingOnCpuAvailable() const = 0;
virtual bool isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const = 0;
virtual bool getMediaFrequencyTileIndex(const ReleaseHelper *releaseHelper, uint32_t &tileIndex) const = 0;
virtual bool isResolvingBuiltinsNeeded(const ReleaseHelper *releaseHelper) const = 0;
virtual bool isResolvingSubDeviceIDNeeded(const ReleaseHelper *releaseHelper) const = 0;
virtual std::optional<GfxMemoryAllocationMethod> getPreferredAllocationMethod(AllocationType allocationType) const = 0;
virtual uint64_t overridePatIndex(bool isUncachedType, uint64_t patIndex) const = 0;

View File

@@ -809,9 +809,9 @@ std::optional<GfxMemoryAllocationMethod> ProductHelperHw<gfxProduct>::getPreferr
}
template <PRODUCT_FAMILY gfxProduct>
bool ProductHelperHw<gfxProduct>::isResolvingBuiltinsNeeded(const ReleaseHelper *releaseHelper) const {
bool ProductHelperHw<gfxProduct>::isResolvingSubDeviceIDNeeded(const ReleaseHelper *releaseHelper) const {
if (releaseHelper) {
return releaseHelper->isResolvingBuiltinsNeeded();
return releaseHelper->isResolvingSubDeviceIDNeeded();
}
return true;
}

View File

@@ -159,7 +159,7 @@ class ProductHelperHw : public ProductHelper {
bool isCachingOnCpuAvailable() const override;
bool isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const override;
bool getMediaFrequencyTileIndex(const ReleaseHelper *releaseHelper, uint32_t &tileIndex) const override;
bool isResolvingBuiltinsNeeded(const ReleaseHelper *releaseHelper) const override;
bool isResolvingSubDeviceIDNeeded(const ReleaseHelper *releaseHelper) const override;
std::optional<GfxMemoryAllocationMethod> getPreferredAllocationMethod(AllocationType allocationType) const override;
uint64_t overridePatIndex(bool isUncachedType, uint64_t patIndex) const override;

View File

@@ -33,7 +33,7 @@ class ReleaseHelper {
virtual bool isBFloat16ConversionSupported() const = 0;
virtual int getProductMaxPreferredSlmSize(int preferredEnumValue) const = 0;
virtual bool getMediaFrequencyTileIndex(uint32_t &tileIndex) const = 0;
virtual bool isResolvingBuiltinsNeeded() const = 0;
virtual bool isResolvingSubDeviceIDNeeded() const = 0;
protected:
ReleaseHelper(HardwareIpVersion hardwareIpVersion) : hardwareIpVersion(hardwareIpVersion) {}
@@ -56,7 +56,7 @@ class ReleaseHelperHw : public ReleaseHelper {
bool isBFloat16ConversionSupported() const override;
int getProductMaxPreferredSlmSize(int preferredEnumValue) const override;
bool getMediaFrequencyTileIndex(uint32_t &tileIndex) const override;
bool isResolvingBuiltinsNeeded() const override;
bool isResolvingSubDeviceIDNeeded() const override;
private:
ReleaseHelperHw(HardwareIpVersion hardwareIpVersion) : ReleaseHelper(hardwareIpVersion) {}

View File

@@ -54,7 +54,7 @@ bool ReleaseHelperHw<releaseType>::getMediaFrequencyTileIndex(uint32_t &tileInde
}
template <ReleaseType releaseType>
bool ReleaseHelperHw<releaseType>::isResolvingBuiltinsNeeded() const {
bool ReleaseHelperHw<releaseType>::isResolvingSubDeviceIDNeeded() const {
return true;
}
} // namespace NEO

View File

@@ -845,18 +845,12 @@ HWTEST_F(LinkerTests, givenUnresolvedExternalsWhenLinkThenSubDeviceIDSymbolsAreC
patchableGlobalVarSeg, patchableConstVarSeg, instructionsSegments,
unresolvedExternals, pDevice, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions);
auto releaseHelper = pDevice->getReleaseHelper();
auto &productHelper = pDevice->getProductHelper();
size_t expectedUnresolvedExternals = productHelper.isResolvingBuiltinsNeeded(releaseHelper) ? 2u : 4u;
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, relocatedSymbols.size());
EXPECT_EQ(expectedUnresolvedExternals, unresolvedExternals.size());
EXPECT_EQ(2u, unresolvedExternals.size());
if (productHelper.isResolvingBuiltinsNeeded(releaseHelper)) {
for (auto &symbol : unresolvedExternals) {
EXPECT_NE(NEO::Linker::subDeviceID, symbol.unresolvedRelocation.symbolName);
}
for (auto &symbol : unresolvedExternals) {
EXPECT_NE(NEO::Linker::subDeviceID, symbol.unresolvedRelocation.symbolName);
}
auto gpuAddressAs64bit = pDevice->getDefaultEngine().commandStreamReceiver->getWorkPartitionAllocationGpuAddress();

View File

@@ -27,7 +27,7 @@ TEST(ReleaseHelperTest, givenReleaseHelper1255ThenCorrectPropertiesAreReturned)
EXPECT_EQ(revision < 4, releaseHelper->isPrefetchDisablingRequired());
EXPECT_TRUE(releaseHelper->isSplitMatrixMultiplyAccumulateSupported());
EXPECT_TRUE(releaseHelper->isBFloat16ConversionSupported());
EXPECT_TRUE(releaseHelper->isResolvingBuiltinsNeeded());
EXPECT_TRUE(releaseHelper->isResolvingSubDeviceIDNeeded());
}
}

View File

@@ -27,7 +27,7 @@ TEST(ReleaseHelperTest, givenReleaseHelper1256ThenCorrectPropertiesAreReturned)
EXPECT_FALSE(releaseHelper->isPrefetchDisablingRequired());
EXPECT_TRUE(releaseHelper->isSplitMatrixMultiplyAccumulateSupported());
EXPECT_TRUE(releaseHelper->isBFloat16ConversionSupported());
EXPECT_TRUE(releaseHelper->isResolvingBuiltinsNeeded());
EXPECT_TRUE(releaseHelper->isResolvingSubDeviceIDNeeded());
}
}

View File

@@ -27,7 +27,7 @@ TEST(ReleaseHelperTest, givenReleaseHelper1257ThenCorrectPropertiesAreReturned)
EXPECT_FALSE(releaseHelper->isPrefetchDisablingRequired());
EXPECT_TRUE(releaseHelper->isSplitMatrixMultiplyAccumulateSupported());
EXPECT_TRUE(releaseHelper->isBFloat16ConversionSupported());
EXPECT_TRUE(releaseHelper->isResolvingBuiltinsNeeded());
EXPECT_TRUE(releaseHelper->isResolvingSubDeviceIDNeeded());
}
}

View File

@@ -28,7 +28,7 @@ TEST(ReleaseHelperTest, givenReleaseHelper1270ThenCorrectPropertiesAreReturned)
EXPECT_FALSE(releaseHelper->isPrefetchDisablingRequired());
EXPECT_FALSE(releaseHelper->isSplitMatrixMultiplyAccumulateSupported());
EXPECT_FALSE(releaseHelper->isBFloat16ConversionSupported());
EXPECT_TRUE(releaseHelper->isResolvingBuiltinsNeeded());
EXPECT_TRUE(releaseHelper->isResolvingSubDeviceIDNeeded());
}
}

View File

@@ -28,7 +28,7 @@ TEST(ReleaseHelperTest, givenReleaseHelper1271ThenCorrectPropertiesAreReturned)
EXPECT_FALSE(releaseHelper->isPrefetchDisablingRequired());
EXPECT_FALSE(releaseHelper->isSplitMatrixMultiplyAccumulateSupported());
EXPECT_FALSE(releaseHelper->isBFloat16ConversionSupported());
EXPECT_TRUE(releaseHelper->isResolvingBuiltinsNeeded());
EXPECT_TRUE(releaseHelper->isResolvingSubDeviceIDNeeded());
}
}