L0 Function Pointer Handling for kernels & correct error

- Enable Support for L0 Function Pointers for Kernels and Exported
Functions
- Return ZE_RESULT_ERROR_INVALID_FUNCTION_NAME given no function of that
name is a kernel or exported function

Signed-off-by: Neil R Spruit <neil.r.spruit@intel.com>
This commit is contained in:
Neil R Spruit
2022-05-28 00:18:38 +00:00
committed by Compute-Runtime-Automation
parent c2e3d24a1d
commit e2132de30e
2 changed files with 131 additions and 3 deletions

View File

@@ -845,12 +845,30 @@ bool ModuleImp::linkBinary() {
}
ze_result_t ModuleImp::getFunctionPointer(const char *pFunctionName, void **pfnFunction) {
// Check if the function is in the exported symbol table
auto symbolIt = symbols.find(pFunctionName);
if ((symbolIt == symbols.end()) || (symbolIt->second.symbol.segment != NEO::SegmentType::Instructions)) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
if ((symbolIt != symbols.end()) && (symbolIt->second.symbol.segment == NEO::SegmentType::Instructions)) {
*pfnFunction = reinterpret_cast<void *>(symbolIt->second.gpuAddress);
}
// If the Function Pointer is not in the exported symbol table, then this function might be a kernel.
// Check if the function name matches a kernel and return the gpu address to that function
if (*pfnFunction == nullptr) {
auto kernelImmData = this->getKernelImmutableData(pFunctionName);
if (kernelImmData != nullptr) {
auto isaAllocation = kernelImmData->getIsaGraphicsAllocation();
*pfnFunction = reinterpret_cast<void *>(isaAllocation->getGpuAddress());
// Ensure that any kernel in this module which uses this kernel module function pointer has access to the memory.
for (auto &data : this->getKernelImmutableDataVector()) {
if (data.get() != kernelImmData) {
data.get()->getResidencyContainer().insert(data.get()->getResidencyContainer().end(), isaAllocation);
}
}
}
}
*pfnFunction = reinterpret_cast<void *>(symbolIt->second.gpuAddress);
if (*pfnFunction == nullptr) {
return ZE_RESULT_ERROR_INVALID_FUNCTION_NAME;
}
return ZE_RESULT_SUCCESS;
}

View File

@@ -1144,6 +1144,18 @@ TEST_F(ModulePropertyTest, givenCallToGetPropertiesWithUnresolvedSymbolsThenFlag
EXPECT_EQ(expectedFlags, moduleProperties.flags);
}
struct ModuleFunctionPointerTests : public Test<ModuleFixture> {
void SetUp() override {
Test<ModuleFixture>::SetUp();
module0 = std::make_unique<WhiteBox<::L0::Module>>(device, nullptr, ModuleType::User);
}
void TearDown() override {
module0.reset(nullptr);
Test<ModuleFixture>::TearDown();
}
std::unique_ptr<WhiteBox<::L0::Module>> module0;
};
struct ModuleDynamicLinkTests : public Test<DeviceFixture> {
void SetUp() override {
Test<DeviceFixture>::SetUp();
@@ -1726,6 +1738,104 @@ TEST_F(ModuleDynamicLinkTests, givenModuleWithFunctionDependenciesWhenOtherModul
EXPECT_EQ(ZE_RESULT_ERROR_MODULE_LINK_FAILURE, res);
}
TEST_F(ModuleFunctionPointerTests, givenModuleWithExportedSymbolThenGetFunctionPointerReturnsGpuAddressToFunction) {
uint64_t gpuAddress = 0x12345;
NEO::SymbolInfo symbolInfo{};
symbolInfo.segment = NEO::SegmentType::Instructions;
NEO::Linker::RelocatedSymbol relocatedSymbol{symbolInfo, gpuAddress};
char kernelHeap[MemoryConstants::pageSize] = {};
auto kernelInfo = std::make_unique<NEO::KernelInfo>();
kernelInfo->heapInfo.pKernelHeap = kernelHeap;
kernelInfo->heapInfo.KernelHeapSize = MemoryConstants::pageSize;
module0->getTranslationUnit()->programInfo.kernelInfos.push_back(kernelInfo.release());
auto kernelImmData = std::make_unique<WhiteBox<::L0::KernelImmutableData>>(device);
kernelImmData->isaGraphicsAllocation.reset(neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::AllocationType::KERNEL_ISA, neoDevice->getDeviceBitfield()}));
module0->kernelImmDatas.push_back(std::move(kernelImmData));
module0->symbols["externalFunction"] = relocatedSymbol;
void *functionPointer = nullptr;
ze_result_t res = module0->getFunctionPointer("externalFunction", &functionPointer);
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
EXPECT_EQ(reinterpret_cast<uint64_t>(functionPointer), gpuAddress);
}
TEST_F(ModuleFunctionPointerTests, givenInvalidFunctionNameAndModuleWithExportedSymbolThenGetFunctionPointerReturnsFailure) {
uint64_t gpuAddress = 0x12345;
NEO::SymbolInfo symbolInfo{};
symbolInfo.segment = NEO::SegmentType::Instructions;
NEO::Linker::RelocatedSymbol relocatedSymbol{symbolInfo, gpuAddress};
char kernelHeap[MemoryConstants::pageSize] = {};
auto kernelInfo = std::make_unique<NEO::KernelInfo>();
kernelInfo->heapInfo.pKernelHeap = kernelHeap;
kernelInfo->heapInfo.KernelHeapSize = MemoryConstants::pageSize;
kernelInfo->kernelDescriptor.kernelMetadata.kernelName = "kernelFunction";
module0->getTranslationUnit()->programInfo.kernelInfos.push_back(kernelInfo.release());
NEO::KernelDescriptor kernelDescriptor;
kernelDescriptor.kernelMetadata.kernelName = "kernelFunction";
auto kernelImmData = std::make_unique<WhiteBox<::L0::KernelImmutableData>>(device);
kernelImmData->isaGraphicsAllocation.reset(neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::AllocationType::KERNEL_ISA, neoDevice->getDeviceBitfield()}));
kernelImmData->kernelDescriptor = &kernelDescriptor;
printf("kern %p\n", kernelImmData->kernelDescriptor);
module0->kernelImmDatas.push_back(std::move(kernelImmData));
module0->symbols["externalFunction"] = relocatedSymbol;
void *functionPointer = nullptr;
ze_result_t res = module0->getFunctionPointer("Invalid", &functionPointer);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_FUNCTION_NAME, res);
}
TEST_F(ModuleFunctionPointerTests, givenModuleWithExportedSymbolThenGetFunctionPointerReturnsGpuAddressToKernelFunction) {
uint64_t gpuAddress = 0x12345;
NEO::SymbolInfo symbolInfo{};
symbolInfo.segment = NEO::SegmentType::Instructions;
NEO::Linker::RelocatedSymbol relocatedSymbol{symbolInfo, gpuAddress};
char kernelHeap[MemoryConstants::pageSize] = {};
auto kernelInfo = std::make_unique<NEO::KernelInfo>();
kernelInfo->heapInfo.pKernelHeap = kernelHeap;
kernelInfo->heapInfo.KernelHeapSize = MemoryConstants::pageSize;
kernelInfo->kernelDescriptor.kernelMetadata.kernelName = "kernelFunction";
module0->getTranslationUnit()->programInfo.kernelInfos.push_back(kernelInfo.release());
NEO::KernelDescriptor kernelDescriptor;
kernelDescriptor.kernelMetadata.kernelName = "kernelFunction";
auto kernelImmData = std::make_unique<WhiteBox<::L0::KernelImmutableData>>(device);
kernelImmData->isaGraphicsAllocation.reset(neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::AllocationType::KERNEL_ISA, neoDevice->getDeviceBitfield()}));
kernelImmData->kernelDescriptor = &kernelDescriptor;
printf("kern %p\n", kernelImmData->kernelDescriptor);
module0->kernelImmDatas.push_back(std::move(kernelImmData));
module0->symbols["externalFunction"] = relocatedSymbol;
void *functionPointer = nullptr;
ze_result_t res = module0->getFunctionPointer("kernelFunction", &functionPointer);
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
EXPECT_EQ(reinterpret_cast<uint64_t>(functionPointer), module0->kernelImmDatas[0]->getIsaGraphicsAllocation()->getGpuAddress());
}
class DeviceModuleSetArgBufferTest : public ModuleFixture, public ::testing::Test {
public:
void SetUp() override {