This interface function does not actually need the device image type. It's unused in the function, so it should be able to be safely removed. The motivation for this is to facilitate downsteam porting of the amd-stg-open RPC module into the nextgen plugin so we can delete the old plugin entirely. For that to work we need to be able to call this function at kernel-launch time, which doesn't have the image. Also it's cleaner. Reviewed By: jplehr Differential Revision: https://reviews.llvm.org/D144436
163 lines
6.0 KiB
C++
163 lines
6.0 KiB
C++
//===- GlobalHandler.cpp - Target independent global & env. var handling --===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Target independent global handler and environment manager.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "GlobalHandler.h"
|
|
#include "ELFSymbols.h"
|
|
#include "PluginInterface.h"
|
|
#include "Utilities.h"
|
|
|
|
#include <cstring>
|
|
|
|
using namespace llvm;
|
|
using namespace omp;
|
|
using namespace target;
|
|
using namespace plugin;
|
|
|
|
const ELF64LEObjectFile *
|
|
GenericGlobalHandlerTy::getOrCreateELFObjectFile(const GenericDeviceTy &Device,
|
|
DeviceImageTy &Image) {
|
|
|
|
auto Search = ELFObjectFiles.find(Image.getId());
|
|
if (Search != ELFObjectFiles.end())
|
|
// The ELF object file was already there.
|
|
return &Search->second;
|
|
|
|
// The ELF object file we are checking is not created yet.
|
|
Expected<ELF64LEObjectFile> ElfOrErr =
|
|
ELF64LEObjectFile::create(Image.getMemoryBuffer());
|
|
if (!ElfOrErr) {
|
|
consumeError(ElfOrErr.takeError());
|
|
return nullptr;
|
|
}
|
|
|
|
auto Result =
|
|
ELFObjectFiles.try_emplace(Image.getId(), std::move(ElfOrErr.get()));
|
|
assert(Result.second && "Map insertion failed");
|
|
assert(Result.first != ELFObjectFiles.end() && "Map insertion failed");
|
|
|
|
return &Result.first->second;
|
|
}
|
|
|
|
Error GenericGlobalHandlerTy::getGlobalMetadataFromELF(
|
|
const DeviceImageTy &Image, const ELF64LE::Sym &Symbol,
|
|
const ELF64LE::Shdr &Section, GlobalTy &ImageGlobal) {
|
|
|
|
// The global's address is computed as the image begin + the ELF section
|
|
// offset + the ELF symbol value.
|
|
ImageGlobal.setPtr(
|
|
advanceVoidPtr(Image.getStart(), Section.sh_offset + Symbol.st_value));
|
|
|
|
// Set the global's size.
|
|
ImageGlobal.setSize(Symbol.st_size);
|
|
|
|
return Plugin::success();
|
|
}
|
|
|
|
Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
|
|
GenericDeviceTy &Device, DeviceImageTy &Image, const GlobalTy &HostGlobal,
|
|
bool Device2Host) {
|
|
|
|
GlobalTy DeviceGlobal(HostGlobal.getName(), HostGlobal.getSize());
|
|
|
|
// Get the metadata from the global on the device.
|
|
if (auto Err = getGlobalMetadataFromDevice(Device, Image, DeviceGlobal))
|
|
return Err;
|
|
|
|
// Perform the actual transfer.
|
|
return moveGlobalBetweenDeviceAndHost(Device, HostGlobal, DeviceGlobal,
|
|
Device2Host);
|
|
}
|
|
|
|
/// Actually move memory between host and device. See readGlobalFromDevice and
|
|
/// writeGlobalToDevice for the interface description.
|
|
Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
|
|
GenericDeviceTy &Device, const GlobalTy &HostGlobal,
|
|
const GlobalTy &DeviceGlobal, bool Device2Host) {
|
|
|
|
// Transfer the data from the source to the destination.
|
|
if (Device2Host) {
|
|
if (auto Err =
|
|
Device.dataRetrieve(HostGlobal.getPtr(), DeviceGlobal.getPtr(),
|
|
HostGlobal.getSize(), nullptr))
|
|
return Err;
|
|
} else {
|
|
if (auto Err = Device.dataSubmit(DeviceGlobal.getPtr(), HostGlobal.getPtr(),
|
|
HostGlobal.getSize(), nullptr))
|
|
return Err;
|
|
}
|
|
|
|
DP("Succesfully %s %u bytes associated with global symbol '%s' %s the device "
|
|
"(%p -> %p).\n",
|
|
Device2Host ? "read" : "write", HostGlobal.getSize(),
|
|
HostGlobal.getName().data(), Device2Host ? "from" : "to",
|
|
DeviceGlobal.getPtr(), HostGlobal.getPtr());
|
|
|
|
return Plugin::success();
|
|
}
|
|
|
|
Error GenericGlobalHandlerTy::getGlobalMetadataFromImage(
|
|
GenericDeviceTy &Device, DeviceImageTy &Image, GlobalTy &ImageGlobal) {
|
|
|
|
// Get the ELF object file for the image. Notice the ELF object may already
|
|
// be created in previous calls, so we can reuse it.
|
|
const ELF64LEObjectFile *ELFObj = getOrCreateELFObjectFile(Device, Image);
|
|
if (!ELFObj)
|
|
return Plugin::error("Unable to create ELF object for image %p",
|
|
Image.getStart());
|
|
|
|
// Search the ELF symbol using the the symbol name.
|
|
auto SymOrErr = getELFSymbol(*ELFObj, ImageGlobal.getName());
|
|
if (!SymOrErr)
|
|
return Plugin::error("Failed ELF lookup of global '%s': %s",
|
|
ImageGlobal.getName().data(),
|
|
toString(SymOrErr.takeError()).data());
|
|
|
|
if (!*SymOrErr)
|
|
return Plugin::error("Failed to find global symbol '%s' in the ELF image",
|
|
ImageGlobal.getName().data());
|
|
|
|
// Get the section to which the symbol belongs.
|
|
auto SecOrErr = ELFObj->getELFFile().getSection((*SymOrErr)->st_shndx);
|
|
if (!SecOrErr)
|
|
return Plugin::error("Failed to get ELF section from global '%s': %s",
|
|
ImageGlobal.getName().data(),
|
|
toString(SecOrErr.takeError()).data());
|
|
|
|
// Setup the global symbol's address and size.
|
|
return getGlobalMetadataFromELF(Image, **SymOrErr, **SecOrErr, ImageGlobal);
|
|
}
|
|
|
|
Error GenericGlobalHandlerTy::readGlobalFromImage(GenericDeviceTy &Device,
|
|
DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal) {
|
|
|
|
GlobalTy ImageGlobal(HostGlobal.getName(), -1);
|
|
if (auto Err = getGlobalMetadataFromImage(Device, Image, ImageGlobal))
|
|
return Err;
|
|
|
|
if (ImageGlobal.getSize() != HostGlobal.getSize())
|
|
return Plugin::error("Transfer failed because global symbol '%s' has "
|
|
"%u bytes in the ELF image but %u bytes on the host",
|
|
HostGlobal.getName().data(), ImageGlobal.getSize(),
|
|
HostGlobal.getSize());
|
|
|
|
DP("Global symbol '%s' was found in the ELF image and %u bytes will copied "
|
|
"from %p to %p.\n",
|
|
HostGlobal.getName().data(), HostGlobal.getSize(), ImageGlobal.getPtr(),
|
|
HostGlobal.getPtr());
|
|
|
|
// Perform the copy from the image to the host memory.
|
|
std::memcpy(HostGlobal.getPtr(), ImageGlobal.getPtr(), HostGlobal.getSize());
|
|
|
|
return Plugin::success();
|
|
}
|