From 1a4755694e71b51a2963a195e9bdf947c42a8923 Mon Sep 17 00:00:00 2001 From: Kacper Nowak Date: Thu, 9 Feb 2023 17:39:29 +0000 Subject: [PATCH] feat(zebin): Add support for SHT_ZEBIN_GTPIN_INFO type section This commit adds support for decoding SHT_ZEBIN_GTPIN_INFO type sections. For each section, passed data will be stored in kernel info (for corresponding kernel). Related-To: NEO-7689 Signed-off-by: Kacper Nowak --- .../device_binary_format/elf/zebin_elf.h | 2 +- .../device_binary_format/zebin_decoder.cpp | 29 +++++++++- .../device_binary_format/zebin_decoder.h | 4 ++ .../zebin_decoder_tests.cpp | 58 ++++++++++++++++++- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/shared/source/device_binary_format/elf/zebin_elf.h b/shared/source/device_binary_format/elf/zebin_elf.h index 339e641f93..1fa7afffda 100644 --- a/shared/source/device_binary_format/elf/zebin_elf.h +++ b/shared/source/device_binary_format/elf/zebin_elf.h @@ -56,7 +56,7 @@ inline constexpr ConstStringRef debugPrefix = ".debug_"; inline constexpr ConstStringRef debugInfo = ".debug_info"; inline constexpr ConstStringRef debugAbbrev = ".debug_abbrev"; inline constexpr ConstStringRef zeInfo = ".ze_info"; -inline constexpr ConstStringRef gtpinInfo = ".gtpin_info"; +inline constexpr ConstStringRef gtpinInfo = ".gtpin_info."; inline constexpr ConstStringRef noteIntelGT = ".note.intelgt.compat"; inline constexpr ConstStringRef buildOptions = ".misc.buildOptions"; inline constexpr ConstStringRef vIsaAsmPrefix = ".visaasm."; diff --git a/shared/source/device_binary_format/zebin_decoder.cpp b/shared/source/device_binary_format/zebin_decoder.cpp index 0f657dd3c0..cdf91aa0be 100644 --- a/shared/source/device_binary_format/zebin_decoder.cpp +++ b/shared/source/device_binary_format/zebin_decoder.cpp @@ -270,8 +270,12 @@ DecodeError extractZebinSections(NEO::Elf::Elf &elf, ZebinSections &elf, std::stri return DecodeError::InvalidBinary; } + auto gtpinInfoForKernel = getKernelGtpinInfo(kernelName, elf, zebinSections); + if (false == gtpinInfoForKernel.empty()) { + kernelInfo->igcInfoForGtpin = reinterpret_cast(gtpinInfoForKernel.begin()); + } + kernelInfo->heapInfo.pKernelHeap = kernelInstructions.begin(); kernelInfo->heapInfo.KernelHeapSize = static_cast(kernelInstructions.size()); kernelInfo->heapInfo.KernelUnpaddedSize = static_cast(kernelInstructions.size()); @@ -797,6 +806,22 @@ ArrayRef getKernelHeap(ConstStringRef &kernelName, Elf::Elf getKernelGtpinInfo(ConstStringRef &kernelName, Elf::Elf &elf, const ZebinSections &zebinSections); +template ArrayRef getKernelGtpinInfo(ConstStringRef &kernelName, Elf::Elf &elf, const ZebinSections &zebinSections); +template +ArrayRef getKernelGtpinInfo(ConstStringRef &kernelName, Elf::Elf &elf, const ZebinSections &zebinSections) { + auto sectionHeaderNamesData = elf.sectionHeaders[elf.elfFileHeader->shStrNdx].data; + ConstStringRef sectionHeaderNamesString(reinterpret_cast(sectionHeaderNamesData.begin()), sectionHeaderNamesData.size()); + for (auto *gtpinInfoSection : zebinSections.gtpinInfoSections) { + ConstStringRef sectionName = ConstStringRef(sectionHeaderNamesString.begin() + gtpinInfoSection->header->name); + auto sufix = sectionName.substr(static_cast(NEO::Elf::SectionsNamesZebin::gtpinInfo.length())); + if (sufix == kernelName) { + return gtpinInfoSection->data; + } + } + return {}; +} + DecodeError decodeZeInfo(ProgramInfo &dst, ConstStringRef zeInfo, std::string &outErrReason, std::string &outWarning) { Yaml::YamlParser yamlParser; bool parseSuccess = yamlParser.parse(zeInfo, outErrReason, outWarning); diff --git a/shared/source/device_binary_format/zebin_decoder.h b/shared/source/device_binary_format/zebin_decoder.h index ee0c880e8e..53fd11064d 100644 --- a/shared/source/device_binary_format/zebin_decoder.h +++ b/shared/source/device_binary_format/zebin_decoder.h @@ -28,6 +28,7 @@ template struct ZebinSections { using SectionHeaderData = typename NEO::Elf::Elf::SectionHeaderAndData; StackVec textKernelSections; + StackVec gtpinInfoSections; StackVec zeInfoSections; StackVec globalDataSections; StackVec globalZeroInitDataSections; @@ -104,6 +105,9 @@ NEO::DecodeError decodeZebin(ProgramInfo &dst, NEO::Elf::Elf &elf, std: template ArrayRef getKernelHeap(ConstStringRef &kernelName, Elf::Elf &elf, const ZebinSections &zebinSections); +template +ArrayRef getKernelGtpinInfo(ConstStringRef &kernelName, Elf::Elf &elf, const ZebinSections &zebinSections); + NEO::DecodeError decodeZeInfo(ProgramInfo &dst, ConstStringRef zeInfo, std::string &outErrReason, std::string &outWarning); void setKernelMiscInfoPosition(ConstStringRef metadata, NEO::ProgramInfo &dst); diff --git a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp index a3d4544fed..f6bb2864cf 100644 --- a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp +++ b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp @@ -149,7 +149,8 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) { elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SectionsNamesZebin::symtab, std::string{}); elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, std::string{}); elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, std::string{}); - elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo, std::string{}); + elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "someKernel", std::string{}); + elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "someOtherKernel", std::string{}); elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_VISA_ASM, NEO::Elf::SectionsNamesZebin::vIsaAsmPrefix.str() + "someKernel", std::string{}); elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_MISC, NEO::Elf::SectionsNamesZebin::buildOptions, std::string{}); elfEncoder.appendSection(NEO::Elf::SHT_NOBITS, NEO::Elf::SectionsNamesZebin::dataConstZeroInit.str(), std::string{}); @@ -172,6 +173,8 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) { EXPECT_TRUE(errors.empty()) << errors; ASSERT_EQ(2U, sections.textKernelSections.size()); + ASSERT_EQ(2U, sections.gtpinInfoSections.size()); + ASSERT_EQ(1U, sections.globalDataSections.size()); ASSERT_EQ(1U, sections.constDataSections.size()); ASSERT_EQ(1U, sections.constDataStringSections.size()); @@ -186,6 +189,8 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) { const char *strings = stringSection.data.toArrayRef().begin(); EXPECT_STREQ((NEO::Elf::SectionsNamesZebin::textPrefix.str() + "someKernel").c_str(), strings + sections.textKernelSections[0]->header->name); EXPECT_STREQ((NEO::Elf::SectionsNamesZebin::textPrefix.str() + "someOtherKernel").c_str(), strings + sections.textKernelSections[1]->header->name); + EXPECT_STREQ((NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "someKernel").c_str(), strings + sections.gtpinInfoSections[0]->header->name); + EXPECT_STREQ((NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "someOtherKernel").c_str(), strings + sections.gtpinInfoSections[1]->header->name); EXPECT_STREQ(NEO::Elf::SectionsNamesZebin::dataGlobal.data(), strings + sections.globalDataSections[0]->header->name); EXPECT_STREQ(NEO::Elf::SectionsNamesZebin::dataConst.data(), strings + sections.constDataSections[0]->header->name); EXPECT_STREQ(NEO::Elf::SectionsNamesZebin::dataConstString.data(), strings + sections.constDataStringSections[0]->header->name); @@ -196,7 +201,7 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) { EXPECT_STREQ(NEO::Elf::SectionsNamesZebin::dataGlobalZeroInit.data(), strings + sections.globalZeroInitDataSections[0]->header->name); } -TEST(ExtractZebinSections, GivenMispelledConstDataSectionThenAllowItButEmitError) { +TEST(ExtractZebinSections, GivenMispelledConstDataSectionThenAllowItButEmitWarning) { NEO::Elf::ElfEncoder<> elfEncoder; elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, ".data.global_const", std::string{}); auto encodedElf = elfEncoder.encode(); @@ -219,6 +224,24 @@ TEST(ExtractZebinSections, GivenMispelledConstDataSectionThenAllowItButEmitError EXPECT_STREQ(".data.global_const", strings + sections.constDataSections[0]->header->name); } +TEST(ExtractZebinSections, GivenUnknownZebinGtpinInfoSectionThenEmitWarning) { + NEO::Elf::ElfEncoder<> elfEncoder; + elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, ".unknown", std::string{}); + auto encodedElf = elfEncoder.encode(); + std::string elferrors; + std::string elfwarnings; + auto decodedElf = NEO::Elf::decodeElf(encodedElf, elferrors, elfwarnings); + + NEO::ZebinSections sections; + std::string errors; + std::string warnings; + auto decodeError = NEO::extractZebinSections(decodedElf, sections, errors, warnings); + EXPECT_EQ(NEO::DecodeError::Success, decodeError); + std::string expectedWarning{"DeviceBinaryFormat::Zebin : Unhandled SHT_ZEBIN_GTPIN_INFO section : .unknown, currently supports only : " + NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "KERNEL_NAME\n"}; + EXPECT_STREQ(expectedWarning.c_str(), warnings.c_str()); + EXPECT_TRUE(errors.empty()) << errors; +} + TEST(ExtractZebinSections, GivenUnknownMiscSectionThenEmitWarning) { NEO::Elf::ElfEncoder<> elfEncoder; elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "someKernel", std::string{}); @@ -3817,6 +3840,37 @@ kernels: EXPECT_STREQ("DeviceBinaryFormat::Zebin : Could not find text section for kernel some_kernel\n", errors.c_str()); } +TEST(DecodeZebinTest, givenGtpinInfoSectionsWhenDecodingZebinThenProperlySetIgcInfoForGtpinForEachCorrespondingKernel) { + std::string errors, warnings; + ZebinTestData::ValidEmptyProgram zebin; + const uint8_t data[0x10]{0u}; + zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "someOtherKernel", ArrayRef::fromAny(data, 0x10)); + + std::array mockGtpinData1{}; + mockGtpinData1.fill(7u); + std::array mockGtpinData2{}; + mockGtpinData2.fill(16u); + zebin.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + zebin.kernelName, ArrayRef::fromAny(mockGtpinData1.data(), mockGtpinData1.size())); + zebin.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo.str() + "someOtherKernel", ArrayRef::fromAny(mockGtpinData2.data(), mockGtpinData2.size())); + + auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings); + ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings; + + NEO::ProgramInfo programInfo; + programInfo.kernelInfos.reserve(2); + auto kernelInfo1 = new KernelInfo(); + kernelInfo1->kernelDescriptor.kernelMetadata.kernelName = zebin.kernelName; + programInfo.kernelInfos.push_back(kernelInfo1); + auto kernelInfo2 = new KernelInfo(); + kernelInfo2->kernelDescriptor.kernelMetadata.kernelName = "someOtherKernel"; + programInfo.kernelInfos.push_back(kernelInfo2); + + auto err = decodeZebin(programInfo, elf, errors, warnings); + EXPECT_EQ(NEO::DecodeError::Success, err); + EXPECT_EQ(0, memcmp(reinterpret_cast(kernelInfo1->igcInfoForGtpin), mockGtpinData1.data(), mockGtpinData1.size())); + EXPECT_EQ(0, memcmp(reinterpret_cast(kernelInfo2->igcInfoForGtpin), mockGtpinData2.data(), mockGtpinData2.size())); +} + TEST_F(decodeZeInfoKernelEntryTest, GivenValidExecutionEnvironmentThenPopulateKernelDescriptorProperly) { ConstStringRef zeinfo = R"===( kernels: