From c1ad82a6b7aef452100cf52a068544029bb5377f Mon Sep 17 00:00:00 2001 From: Konstantin Zhuravlyov Date: Fri, 18 Jan 2019 15:41:01 -0500 Subject: [PATCH] Loader updates for code object v3 - Fix loading in some cases - Fix symbol kind Change-Id: I721b4a35972b6d2a6d0ac733ab770b096cc74e17 --- .../hsa-runtime/core/inc/amd_elf_image.hpp | 1 + runtime/hsa-runtime/core/inc/amd_hsa_code.hpp | 4 +- runtime/hsa-runtime/inc/amd_hsa_elf.h | 13 ++ .../libamdhsacode/amd_elf_image.cpp | 3 +- .../libamdhsacode/amd_hsa_code.cpp | 143 +++++++++++++++--- runtime/hsa-runtime/loader/executable.cpp | 134 ++++------------ 6 files changed, 175 insertions(+), 123 deletions(-) diff --git a/runtime/hsa-runtime/core/inc/amd_elf_image.hpp b/runtime/hsa-runtime/core/inc/amd_elf_image.hpp index 6667c3b364..c0cde9336a 100644 --- a/runtime/hsa-runtime/core/inc/amd_elf_image.hpp +++ b/runtime/hsa-runtime/core/inc/amd_elf_image.hpp @@ -208,6 +208,7 @@ namespace amd { virtual uint16_t Machine() = 0; virtual uint16_t Type() = 0; virtual uint32_t EFlags() = 0; + virtual uint32_t ABIVersion() = 0; std::string output() { return out.str(); } diff --git a/runtime/hsa-runtime/core/inc/amd_hsa_code.hpp b/runtime/hsa-runtime/core/inc/amd_hsa_code.hpp index 4d79660e9c..b3fcbc2fbf 100644 --- a/runtime/hsa-runtime/core/inc/amd_hsa_code.hpp +++ b/runtime/hsa-runtime/core/inc/amd_hsa_code.hpp @@ -295,19 +295,19 @@ namespace code { bool PrintToFile(const std::string& filename); void AddNoteCodeObjectVersion(uint32_t major, uint32_t minor); - bool GetNoteCodeObjectVersion(uint32_t* major, uint32_t* minor); bool GetNoteCodeObjectVersion(std::string& version); void AddNoteHsail(uint32_t hsail_major, uint32_t hsail_minor, hsa_profile_t profile, hsa_machine_model_t machine_model, hsa_default_float_rounding_mode_t rounding_mode); bool GetNoteHsail(uint32_t* hsail_major, uint32_t* hsail_minor, hsa_profile_t* profile, hsa_machine_model_t* machine_model, hsa_default_float_rounding_mode_t* default_float_round); void AddNoteIsa(const std::string& vendor_name, const std::string& architecture_name, uint32_t major, uint32_t minor, uint32_t stepping); bool GetNoteIsa(std::string& vendor_name, std::string& architecture_name, uint32_t* major_version, uint32_t* minor_version, uint32_t* stepping); - bool GetNoteIsa(std::string& isaName); void AddNoteProducer(uint32_t major, uint32_t minor, const std::string& producer); bool GetNoteProducer(uint32_t* major, uint32_t* minor, std::string& producer_name); void AddNoteProducerOptions(const std::string& options); void AddNoteProducerOptions(int32_t call_convention, const hsa_ext_control_directives_t& user_directives, const std::string& user_options); bool GetNoteProducerOptions(std::string& options); + bool GetIsa(std::string& isaName); + bool GetCodeObjectVersion(uint32_t* major, uint32_t* minor); hsa_status_t GetInfo(hsa_code_object_info_t attribute, void *value); hsa_status_t GetSymbol(const char *module_name, const char *symbol_name, hsa_code_symbol_t *sym); hsa_status_t IterateSymbols(hsa_code_object_t code_object, diff --git a/runtime/hsa-runtime/inc/amd_hsa_elf.h b/runtime/hsa-runtime/inc/amd_hsa_elf.h index e0702b1751..ac3e5e2c30 100644 --- a/runtime/hsa-runtime/inc/amd_hsa_elf.h +++ b/runtime/hsa-runtime/inc/amd_hsa_elf.h @@ -54,6 +54,19 @@ // FIXME: We really need to start thinking about separating legacy code out, // it is getting messy. +#define EF_AMDGPU_MACH_LC 0x0ff +#define EF_AMDGPU_MACH_AMDGCN_GFX700_LC 0x022 +#define EF_AMDGPU_MACH_AMDGCN_GFX701_LC 0x023 +#define EF_AMDGPU_MACH_AMDGCN_GFX702_LC 0x024 +#define EF_AMDGPU_MACH_AMDGCN_GFX801_LC 0x028 +#define EF_AMDGPU_MACH_AMDGCN_GFX802_LC 0x029 +#define EF_AMDGPU_MACH_AMDGCN_GFX803_LC 0x02a +#define EF_AMDGPU_MACH_AMDGCN_GFX810_LC 0x02b +#define EF_AMDGPU_MACH_AMDGCN_GFX900_LC 0x02c +#define EF_AMDGPU_MACH_AMDGCN_GFX902_LC 0x02d +#define EF_AMDGPU_MACH_AMDGCN_GFX904_LC 0x02e +#define EF_AMDGPU_MACH_AMDGCN_GFX906_LC 0x02f +#define EF_AMDGPU_MACH_AMDGCN_GFX909_LC 0x031 #define EF_AMDGPU_XNACK_LC 0x100 // ELF Section Header Flag Enumeration Values. diff --git a/runtime/hsa-runtime/libamdhsacode/amd_elf_image.cpp b/runtime/hsa-runtime/libamdhsacode/amd_elf_image.cpp index ee9ff3135e..d24e19849c 100644 --- a/runtime/hsa-runtime/libamdhsacode/amd_elf_image.cpp +++ b/runtime/hsa-runtime/libamdhsacode/amd_elf_image.cpp @@ -703,7 +703,8 @@ namespace amd { uint16_t Machine() override { return ehdr.e_machine; } uint16_t Type() override { return ehdr.e_type; } - uint32_t EFlags() override{ return ehdr.e_flags; } + uint32_t EFlags() override { return ehdr.e_flags; } + uint32_t ABIVersion() override { return (uint32_t)(ehdr.e_ident[EI_ABIVERSION]); } GElfStringTable* shstrtab() override; GElfStringTable* strtab() override; diff --git a/runtime/hsa-runtime/libamdhsacode/amd_hsa_code.cpp b/runtime/hsa-runtime/libamdhsacode/amd_hsa_code.cpp index 5579a54f0b..30980d2a06 100644 --- a/runtime/hsa-runtime/libamdhsacode/amd_hsa_code.cpp +++ b/runtime/hsa-runtime/libamdhsacode/amd_hsa_code.cpp @@ -291,7 +291,7 @@ namespace code { bool AmdHsaCode::PullElf() { uint32_t majorVersion, minorVersion; - if (!GetNoteCodeObjectVersion(&majorVersion, &minorVersion)) { + if (!GetCodeObjectVersion(&majorVersion, &minorVersion)) { return false; } if (majorVersion >= 2) { @@ -459,10 +459,17 @@ namespace code { AddAmdNote(NT_AMDGPU_HSA_CODE_OBJECT_VERSION, &desc, sizeof(desc)); } - bool AmdHsaCode::GetNoteCodeObjectVersion(uint32_t* major, uint32_t* minor) + bool AmdHsaCode::GetCodeObjectVersion(uint32_t* major, uint32_t* minor) { amdgpu_hsa_note_code_object_version_t* desc; - if (!GetAmdNote(NT_AMDGPU_HSA_CODE_OBJECT_VERSION, &desc)) { return false; } + if (!GetAmdNote(NT_AMDGPU_HSA_CODE_OBJECT_VERSION, &desc)) { + if (img->ABIVersion() != 0 && img->ABIVersion() != 1) + return false; + + *major = 3; + *minor = 0; + return true; + } *major = desc->major_version; *minor = desc->minor_version; return true; @@ -530,22 +537,120 @@ namespace code { return true; } - bool AmdHsaCode::GetNoteIsa(std::string& isaName) + static std::string ConvertOldTargetNameToNew( + const std::string &OldName, bool IsFinalizer, uint32_t EFlags) { + std::string NewName = ""; + + // FIXME #1: Should 9:0:3 be completely (loader, sc, etc.) removed? + // FIXME #2: What does PAL do with respect to boltzmann/usual fiji/tonga? + if (OldName == "AMD:AMDGPU:7:0:0") + NewName = "amdgcn-amd-amdhsa--gfx700"; + else if (OldName == "AMD:AMDGPU:7:0:1") + NewName = "amdgcn-amd-amdhsa--gfx701"; + else if (OldName == "AMD:AMDGPU:7:0:2") + NewName = "amdgcn-amd-amdhsa--gfx702"; + else if (OldName == "AMD:AMDGPU:7:0:3") + NewName = "amdgcn-amd-amdhsa--gfx703"; + else if (OldName == "AMD:AMDGPU:7:0:4") + NewName = "amdgcn-amd-amdhsa--gfx704"; + else if (OldName == "AMD:AMDGPU:8:0:0") + NewName = "amdgcn-amd-amdhsa--gfx800"; + else if (OldName == "AMD:AMDGPU:8:0:1") + NewName = "amdgcn-amd-amdhsa--gfx801"; + else if (OldName == "AMD:AMDGPU:8:0:2") + NewName = "amdgcn-amd-amdhsa--gfx802"; + else if (OldName == "AMD:AMDGPU:8:0:3") + NewName = "amdgcn-amd-amdhsa--gfx803"; + else if (OldName == "AMD:AMDGPU:8:0:4") + NewName = "amdgcn-amd-amdhsa--gfx804"; + else if (OldName == "AMD:AMDGPU:8:1:0") + NewName = "amdgcn-amd-amdhsa--gfx810"; + else if (OldName == "AMD:AMDGPU:9:0:0") + NewName = "amdgcn-amd-amdhsa--gfx900"; + else if (OldName == "AMD:AMDGPU:9:0:1") + NewName = "amdgcn-amd-amdhsa--gfx900"; + else if (OldName == "AMD:AMDGPU:9:0:2") + NewName = "amdgcn-amd-amdhsa--gfx902"; + else if (OldName == "AMD:AMDGPU:9:0:3") + NewName = "amdgcn-amd-amdhsa--gfx902"; + else if (OldName == "AMD:AMDGPU:9:0:4") + NewName = "amdgcn-amd-amdhsa--gfx904"; + else if (OldName == "AMD:AMDGPU:9:0:6") + NewName = "amdgcn-amd-amdhsa--gfx906"; + else + assert(false && "Unhandled target"); + + if (IsFinalizer && (EFlags & EF_AMDGPU_XNACK)) { + NewName = NewName + "+xnack"; + } else { + if (EFlags != 0 && (EFlags & EF_AMDGPU_XNACK_LC)) { + NewName = NewName + "+xnack"; + } else { + if (OldName == "AMD:AMDGPU:8:0:1") + NewName = NewName + "+xnack"; + else if (OldName == "AMD:AMDGPU:8:1:0") + NewName = NewName + "+xnack"; + else if (OldName == "AMD:AMDGPU:9:0:1") + NewName = NewName + "+xnack"; + else if (OldName == "AMD:AMDGPU:9:0:2") + NewName = NewName + "+xnack"; + else if (OldName == "AMD:AMDGPU:9:0:3") + NewName = NewName + "+xnack"; + } + } + + return NewName; + } + + bool AmdHsaCode::GetIsa(std::string& isaName) { - std::string vendor_name, architecture_name; - uint32_t major_version, minor_version, stepping; - if (!GetNoteIsa(vendor_name, architecture_name, &major_version, &minor_version, &stepping)) { return false; } isaName.clear(); - isaName += vendor_name; - isaName += ":"; - isaName += architecture_name; - isaName += ":"; - isaName += std::to_string(major_version); - isaName += ":"; - isaName += std::to_string(minor_version); - isaName += ":"; - isaName += std::to_string(stepping); - return true; + + uint32_t codeObjectMajorVersion = 0; + uint32_t codeObjectMinorVersion = 0; + + if (!GetCodeObjectVersion(&codeObjectMajorVersion, &codeObjectMinorVersion)) { return false; } + if (codeObjectMajorVersion >= 3) { + isaName += "amdgcn-amd-amdhsa--"; + unsigned MACH = img->EFlags() & EF_AMDGPU_MACH_LC; + switch (MACH) { + case EF_AMDGPU_MACH_AMDGCN_GFX700_LC: isaName += "gfx700"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX701_LC: isaName += "gfx701"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX702_LC: isaName += "gfx702"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX801_LC: isaName += "gfx801"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX802_LC: isaName += "gfx802"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX803_LC: isaName += "gfx803"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX810_LC: isaName += "gfx810"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX900_LC: isaName += "gfx900"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX902_LC: isaName += "gfx902"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX904_LC: isaName += "gfx904"; break; + case EF_AMDGPU_MACH_AMDGCN_GFX906_LC: isaName += "gfx906"; break; + default: return false; + } + + if (img->EFlags() & EF_AMDGPU_XNACK_LC) + isaName += "+xnack"; + + return true; + } else { + std::string vendor_name, architecture_name; + uint32_t major_version, minor_version, stepping; + if (!GetNoteIsa(vendor_name, architecture_name, &major_version, &minor_version, &stepping)) { return false; } + isaName += vendor_name; + isaName += ":"; + isaName += architecture_name; + isaName += ":"; + isaName += std::to_string(major_version); + isaName += ":"; + isaName += std::to_string(minor_version); + isaName += ":"; + isaName += std::to_string(stepping); + + amdgpu_hsa_note_hsail_t *hsailNote; + bool IsFinalizer = GetAmdNote(NT_AMDGPU_HSA_HSAIL, &hsailNote); + isaName = ConvertOldTargetNameToNew(isaName, IsFinalizer, img->EFlags()); + return true; + } } void AmdHsaCode::AddNoteProducer(uint32_t major, uint32_t minor, const std::string& producer) @@ -617,7 +722,7 @@ namespace code { // TODO: Currently returns string representation instead of hsa_isa_t // which is unavailable here. std::string isa; - if (!GetNoteIsa(isa)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } + if (!GetIsa(isa)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } char *svalue = (char*)value; memset(svalue, 0x0, 64); memcpy(svalue, isa.c_str(), (std::min)(size_t(63), isa.length())); @@ -984,7 +1089,7 @@ namespace code { { { uint32_t major_version, minor_version; - if (GetNoteCodeObjectVersion(&major_version, &minor_version)) { + if (GetCodeObjectVersion(&major_version, &minor_version)) { out << "AMD HSA Code Object" << std::endl << " Version " << major_version << "." << minor_version << std::endl; } diff --git a/runtime/hsa-runtime/loader/executable.cpp b/runtime/hsa-runtime/loader/executable.cpp index 10d79cfd05..c3814813cd 100644 --- a/runtime/hsa-runtime/loader/executable.cpp +++ b/runtime/hsa-runtime/loader/executable.cpp @@ -1018,71 +1018,6 @@ static uint32_t NextCodeObjectNum() return dumpN++; } -static std::string ConvertOldTargetNameToNew( - const std::string &OldName, bool IsFinalizer, uint32_t EFlags) { - std::string NewName = ""; - - // FIXME #1: Should 9:0:3 be completely (loader, sc, etc.) removed? - // FIXME #2: What does PAL do with respect to boltzmann/usual fiji/tonga? - if (OldName == "AMD:AMDGPU:7:0:0") - NewName = "amdgcn-amd-amdhsa--gfx700"; - else if (OldName == "AMD:AMDGPU:7:0:1") - NewName = "amdgcn-amd-amdhsa--gfx701"; - else if (OldName == "AMD:AMDGPU:7:0:2") - NewName = "amdgcn-amd-amdhsa--gfx702"; - else if (OldName == "AMD:AMDGPU:7:0:3") - NewName = "amdgcn-amd-amdhsa--gfx703"; - else if (OldName == "AMD:AMDGPU:7:0:4") - NewName = "amdgcn-amd-amdhsa--gfx704"; - else if (OldName == "AMD:AMDGPU:8:0:0") - NewName = "amdgcn-amd-amdhsa--gfx800"; - else if (OldName == "AMD:AMDGPU:8:0:1") - NewName = "amdgcn-amd-amdhsa--gfx801"; - else if (OldName == "AMD:AMDGPU:8:0:2") - NewName = "amdgcn-amd-amdhsa--gfx802"; - else if (OldName == "AMD:AMDGPU:8:0:3") - NewName = "amdgcn-amd-amdhsa--gfx803"; - else if (OldName == "AMD:AMDGPU:8:0:4") - NewName = "amdgcn-amd-amdhsa--gfx804"; - else if (OldName == "AMD:AMDGPU:8:1:0") - NewName = "amdgcn-amd-amdhsa--gfx810"; - else if (OldName == "AMD:AMDGPU:9:0:0") - NewName = "amdgcn-amd-amdhsa--gfx900"; - else if (OldName == "AMD:AMDGPU:9:0:1") - NewName = "amdgcn-amd-amdhsa--gfx900"; - else if (OldName == "AMD:AMDGPU:9:0:2") - NewName = "amdgcn-amd-amdhsa--gfx902"; - else if (OldName == "AMD:AMDGPU:9:0:3") - NewName = "amdgcn-amd-amdhsa--gfx902"; - else if (OldName == "AMD:AMDGPU:9:0:4") - NewName = "amdgcn-amd-amdhsa--gfx904"; - else if (OldName == "AMD:AMDGPU:9:0:6") - NewName = "amdgcn-amd-amdhsa--gfx906"; - else - assert(false && "Unhandled target"); - - if (IsFinalizer && (EFlags & EF_AMDGPU_XNACK)) { - NewName = NewName + "+xnack"; - } else { - if (EFlags != 0 && (EFlags & EF_AMDGPU_XNACK_LC)) { - NewName = NewName + "+xnack"; - } else { - if (OldName == "AMD:AMDGPU:8:0:1") - NewName = NewName + "+xnack"; - else if (OldName == "AMD:AMDGPU:8:1:0") - NewName = NewName + "+xnack"; - else if (OldName == "AMD:AMDGPU:9:0:1") - NewName = NewName + "+xnack"; - else if (OldName == "AMD:AMDGPU:9:0:2") - NewName = NewName + "+xnack"; - else if (OldName == "AMD:AMDGPU:9:0:3") - NewName = NewName + "+xnack"; - } - } - - return NewName; -} - hsa_status_t ExecutableImpl::LoadCodeObject( hsa_agent_t agent, hsa_code_object_t code_object, @@ -1175,32 +1110,28 @@ hsa_status_t ExecutableImpl::LoadCodeObject( } std::string codeIsa; - if (!code->GetNoteIsa(codeIsa)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } + if (!code->GetIsa(codeIsa)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } uint32_t majorVersion, minorVersion; - if (!code->GetNoteCodeObjectVersion(&majorVersion, &minorVersion)) { + if (!code->GetCodeObjectVersion(&majorVersion, &minorVersion)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } - if (majorVersion != 1 && majorVersion != 2) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } + if (majorVersion != 1 && majorVersion != 2 && majorVersion != 3) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } if (agent.handle == 0 && majorVersion == 1) { return HSA_STATUS_ERROR_INVALID_AGENT; } - bool IsFinalizer = true; uint32_t codeHsailMajor; uint32_t codeHsailMinor; hsa_profile_t codeProfile; hsa_machine_model_t codeMachineModel; hsa_default_float_rounding_mode_t codeRoundingMode; if (!code->GetNoteHsail(&codeHsailMajor, &codeHsailMinor, &codeProfile, &codeMachineModel, &codeRoundingMode)) { - // Only finalizer generated the "HSAIL" note. - IsFinalizer = false; codeProfile = HSA_PROFILE_FULL; } if (profile_ != codeProfile) { return HSA_STATUS_ERROR_INCOMPATIBLE_ARGUMENTS; } - codeIsa = ConvertOldTargetNameToNew(codeIsa, IsFinalizer, code->EFlags()); hsa_isa_t objectsIsa = context_->IsaFromName(codeIsa.c_str()); if (!objectsIsa.handle) { return HSA_STATUS_ERROR_INVALID_ISA_NAME; } @@ -1368,7 +1299,34 @@ hsa_status_t ExecutableImpl::LoadDefinitionSymbol(hsa_agent_t agent, if (!address) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } SymbolImpl *symbol = nullptr; - if (sym->IsVariableSymbol()) { + if (string_ends_with(sym->GetSymbolName(), ".kd")) { + // V3. + llvm::amdhsa::kernel_descriptor_t kd; + sym->GetSection()->getData(sym->SectionOffset(), &kd, sizeof(kd)); + + uint32_t kernarg_segment_size = 0; // FIXME. + uint32_t kernarg_segment_alignment = 0; // FIXME. + uint32_t group_segment_size = kd.group_segment_fixed_size; + uint32_t private_segment_size = kd.private_segment_fixed_size; + bool is_dynamic_callstack = false; + + uint64_t size = sym->Size(); + + KernelSymbol *kernel_symbol = new KernelSymbol(true, + sym->GetModuleName(), + sym->GetSymbolName(), + sym->Linkage(), + true, // sym->IsDefinition() + kernarg_segment_size, + kernarg_segment_alignment, + group_segment_size, + private_segment_size, + is_dynamic_callstack, + size, + 64, + address); + symbol = kernel_symbol; + } else if (sym->IsVariableSymbol()) { symbol = new VariableSymbol(true, sym->GetModuleName(), sym->GetSymbolName(), @@ -1427,37 +1385,11 @@ hsa_status_t ExecutableImpl::LoadDefinitionSymbol(hsa_agent_t agent, uint64_t target_address = sym->GetSection()->addr() + sym->SectionOffset() + ((size_t)(&((amd_kernel_code_t*)0)->runtime_loader_kernel_symbol)); uint64_t source_value = (uint64_t) (uintptr_t) &kernel_symbol->debug_info; SymbolSegment(agent, sym)->Copy(target_address, &source_value, sizeof(source_value)); - } else if (string_ends_with(sym->GetSymbolName(), ".kd")) { - // V3. - llvm::amdhsa::kernel_descriptor_t kd; - sym->GetSection()->getData(sym->SectionOffset(), &kd, sizeof(kd)); - - uint32_t kernarg_segment_size = 0; // FIXME. - uint32_t kernarg_segment_alignment = 0; // FIXME. - uint32_t group_segment_size = kd.group_segment_fixed_size; - uint32_t private_segment_size = kd.private_segment_fixed_size; - bool is_dynamic_callstack = false; - - uint64_t size = sym->Size(); - - KernelSymbol *kernel_symbol = new KernelSymbol(true, - sym->GetModuleName(), - sym->GetSymbolName(), - sym->Linkage(), - true, // sym->IsDefinition() - kernarg_segment_size, - kernarg_segment_alignment, - group_segment_size, - private_segment_size, - is_dynamic_callstack, - size, - 64, - address); - symbol = kernel_symbol; } else { assert(!"Unexpected symbol type in LoadDefinitionSymbol"); return HSA_STATUS_ERROR; } + assert(symbol); if (isAgent) { symbol->agent = agent; @@ -1532,7 +1464,7 @@ hsa_status_t ExecutableImpl::ApplyRelocations(hsa_agent_t agent, amd::hsa::code: } else { // Dynamic relocations are supported starting code object v2.1. uint32_t majorVersion, minorVersion; - if (!c->GetNoteCodeObjectVersion(&majorVersion, &minorVersion)) { + if (!c->GetCodeObjectVersion(&majorVersion, &minorVersion)) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; } if (majorVersion < 2) {