296 lines
10 KiB
C++
296 lines
10 KiB
C++
//===---------------- Utils.cpp - Utilities for Remote RTL ----------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Utilities for data movement and debugging.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Utils.h"
|
|
#include "omptarget.h"
|
|
|
|
namespace RemoteOffloading {
|
|
|
|
void loadTargetBinaryDescription(const __tgt_bin_desc *Desc,
|
|
TargetBinaryDescription &Request) {
|
|
// Keeps track of entries which have already been deep copied.
|
|
std::vector<void *> DeepCopiedEntryAddrs;
|
|
|
|
// Copy Global Offload Entries
|
|
for (auto *CurEntry = Desc->HostEntriesBegin;
|
|
CurEntry != Desc->HostEntriesEnd; CurEntry++) {
|
|
auto *NewEntry = Request.add_entries();
|
|
copyOffloadEntry(CurEntry, NewEntry);
|
|
|
|
// Copy the pointer of the offload entry of the image into the Request
|
|
Request.add_entry_ptrs((uint64_t)CurEntry);
|
|
DeepCopiedEntryAddrs.push_back(CurEntry);
|
|
}
|
|
|
|
// Copy Device Images and Device Offload Entries
|
|
__tgt_device_image *CurImage = Desc->DeviceImages;
|
|
for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++) {
|
|
auto *Image = Request.add_images();
|
|
auto Size = (char *)CurImage->ImageEnd - (char *)CurImage->ImageStart;
|
|
Image->set_binary(CurImage->ImageStart, Size);
|
|
|
|
// Copy the pointer of the image into the Request
|
|
auto *NewImagePtr = Request.add_image_ptrs();
|
|
NewImagePtr->set_img_ptr((uint64_t)CurImage->ImageStart);
|
|
|
|
// Copy Device Offload Entries
|
|
for (auto *CurEntry = CurImage->EntriesBegin;
|
|
CurEntry != CurImage->EntriesEnd; CurEntry++) {
|
|
auto *NewEntry = Image->add_entries();
|
|
|
|
auto Entry = std::find(DeepCopiedEntryAddrs.begin(),
|
|
DeepCopiedEntryAddrs.end(), CurEntry);
|
|
if (Entry != DeepCopiedEntryAddrs.end()) {
|
|
// Offload entry has already been loaded
|
|
shallowCopyOffloadEntry(CurEntry, NewEntry);
|
|
} else { // Offload Entry has not been loaded into the Request
|
|
copyOffloadEntry(CurEntry, NewEntry);
|
|
DeepCopiedEntryAddrs.push_back(CurEntry);
|
|
}
|
|
|
|
// Copy the pointer of the offload entry of the image into the Request
|
|
NewImagePtr->add_entry_ptrs((uint64_t)CurEntry);
|
|
}
|
|
}
|
|
}
|
|
|
|
void unloadTargetBinaryDescription(
|
|
const TargetBinaryDescription *Request, __tgt_bin_desc *Desc,
|
|
std::unordered_map<const void *, __tgt_device_image *>
|
|
&HostToRemoteDeviceImage) {
|
|
std::unordered_map<const void *, __tgt_offload_entry *> CopiedOffloadEntries;
|
|
Desc->NumDeviceImages = Request->images_size();
|
|
Desc->DeviceImages = new __tgt_device_image[Desc->NumDeviceImages];
|
|
|
|
if (Request->entries_size())
|
|
Desc->HostEntriesBegin = new __tgt_offload_entry[Request->entries_size()];
|
|
else {
|
|
Desc->HostEntriesBegin = nullptr;
|
|
Desc->HostEntriesEnd = nullptr;
|
|
}
|
|
|
|
// Copy Global Offload Entries
|
|
__tgt_offload_entry *CurEntry = Desc->HostEntriesBegin;
|
|
size_t I = 0;
|
|
for (auto &Entry : Request->entries()) {
|
|
copyOffloadEntry(Entry, CurEntry);
|
|
CopiedOffloadEntries[(void *)Request->entry_ptrs()[I]] = CurEntry;
|
|
CurEntry++;
|
|
I++;
|
|
}
|
|
Desc->HostEntriesEnd = CurEntry;
|
|
|
|
// Copy Device Images and Device Offload Entries
|
|
__tgt_device_image *CurImage = Desc->DeviceImages;
|
|
auto ImageItr = Request->image_ptrs().begin();
|
|
for (auto Image : Request->images()) {
|
|
// Copy Device Offload Entries
|
|
CurEntry = Desc->HostEntriesBegin;
|
|
bool Found = false;
|
|
|
|
if (!Desc->HostEntriesBegin) {
|
|
CurImage->EntriesBegin = nullptr;
|
|
CurImage->EntriesEnd = nullptr;
|
|
}
|
|
|
|
for (size_t I = 0; I < Image.entries_size(); I++) {
|
|
auto TgtEntry =
|
|
CopiedOffloadEntries.find((void *)Request->entry_ptrs()[I]);
|
|
if (TgtEntry != CopiedOffloadEntries.end()) {
|
|
if (!Found)
|
|
CurImage->EntriesBegin = CurEntry;
|
|
|
|
CurImage->EntriesEnd = CurEntry + 1;
|
|
Found = true;
|
|
} else {
|
|
Found = false;
|
|
copyOffloadEntry(Image.entries()[I], CurEntry);
|
|
CopiedOffloadEntries[(void *)(Request->entry_ptrs()[I])] = CurEntry;
|
|
}
|
|
CurEntry++;
|
|
}
|
|
|
|
// Copy Device Image
|
|
CurImage->ImageStart = new uint8_t[Image.binary().size()];
|
|
memcpy(CurImage->ImageStart,
|
|
static_cast<const void *>(Image.binary().data()),
|
|
Image.binary().size());
|
|
CurImage->ImageEnd =
|
|
(void *)((char *)CurImage->ImageStart + Image.binary().size());
|
|
|
|
HostToRemoteDeviceImage[(void *)ImageItr->img_ptr()] = CurImage;
|
|
CurImage++;
|
|
ImageItr++;
|
|
}
|
|
}
|
|
|
|
void freeTargetBinaryDescription(__tgt_bin_desc *Desc) {
|
|
__tgt_device_image *CurImage = Desc->DeviceImages;
|
|
for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++)
|
|
delete[](uint64_t *) CurImage->ImageStart;
|
|
|
|
delete[] Desc->DeviceImages;
|
|
|
|
for (auto *Entry = Desc->HostEntriesBegin; Entry != Desc->HostEntriesEnd;
|
|
Entry++) {
|
|
free(Entry->name);
|
|
free(Entry->addr);
|
|
}
|
|
|
|
delete[] Desc->HostEntriesBegin;
|
|
}
|
|
|
|
void freeTargetTable(__tgt_target_table *Table) {
|
|
for (auto *Entry = Table->EntriesBegin; Entry != Table->EntriesEnd; Entry++)
|
|
free(Entry->name);
|
|
|
|
delete[] Table->EntriesBegin;
|
|
}
|
|
|
|
void loadTargetTable(__tgt_target_table *Table, TargetTable &TableResponse,
|
|
__tgt_device_image *Image) {
|
|
auto *ImageEntry = Image->EntriesBegin;
|
|
for (__tgt_offload_entry *CurEntry = Table->EntriesBegin;
|
|
CurEntry != Table->EntriesEnd; CurEntry++, ImageEntry++) {
|
|
// TODO: This can probably be trimmed substantially.
|
|
auto *NewEntry = TableResponse.add_entries();
|
|
NewEntry->set_name(CurEntry->name);
|
|
NewEntry->set_addr((uint64_t)CurEntry->addr);
|
|
NewEntry->set_flags(CurEntry->flags);
|
|
NewEntry->set_reserved(CurEntry->reserved);
|
|
NewEntry->set_size(CurEntry->size);
|
|
TableResponse.add_entry_ptrs((int64_t)CurEntry);
|
|
}
|
|
}
|
|
|
|
void unloadTargetTable(
|
|
TargetTable &TableResponse, __tgt_target_table *Table,
|
|
std::unordered_map<void *, void *> &HostToRemoteTargetTableMap) {
|
|
Table->EntriesBegin = new __tgt_offload_entry[TableResponse.entries_size()];
|
|
|
|
auto *CurEntry = Table->EntriesBegin;
|
|
for (size_t I = 0; I < TableResponse.entries_size(); I++) {
|
|
copyOffloadEntry(TableResponse.entries()[I], CurEntry);
|
|
HostToRemoteTargetTableMap[CurEntry->addr] =
|
|
(void *)TableResponse.entry_ptrs()[I];
|
|
CurEntry++;
|
|
}
|
|
Table->EntriesEnd = CurEntry;
|
|
}
|
|
|
|
void copyOffloadEntry(const TargetOffloadEntry &EntryResponse,
|
|
__tgt_offload_entry *Entry) {
|
|
Entry->name = strdup(EntryResponse.name().c_str());
|
|
Entry->reserved = EntryResponse.reserved();
|
|
Entry->flags = EntryResponse.flags();
|
|
Entry->addr = strdup(EntryResponse.data().c_str());
|
|
Entry->size = EntryResponse.data().size();
|
|
}
|
|
|
|
void copyOffloadEntry(const DeviceOffloadEntry &EntryResponse,
|
|
__tgt_offload_entry *Entry) {
|
|
Entry->name = strdup(EntryResponse.name().c_str());
|
|
Entry->reserved = EntryResponse.reserved();
|
|
Entry->flags = EntryResponse.flags();
|
|
Entry->addr = (void *)EntryResponse.addr();
|
|
Entry->size = EntryResponse.size();
|
|
}
|
|
|
|
/// We shallow copy with just the name because it is a convenient identifier, we
|
|
/// do actually just match off of the address.
|
|
void shallowCopyOffloadEntry(const __tgt_offload_entry *Entry,
|
|
TargetOffloadEntry *EntryResponse) {
|
|
EntryResponse->set_name(Entry->name);
|
|
}
|
|
|
|
void copyOffloadEntry(const __tgt_offload_entry *Entry,
|
|
TargetOffloadEntry *EntryResponse) {
|
|
shallowCopyOffloadEntry(Entry, EntryResponse);
|
|
EntryResponse->set_reserved(Entry->reserved);
|
|
EntryResponse->set_flags(Entry->flags);
|
|
EntryResponse->set_data(Entry->addr, Entry->size);
|
|
}
|
|
|
|
/// Dumps the memory region from Start to End in order to debug memory transfer
|
|
/// errors within the plugin
|
|
void dump(const void *Start, const void *End) {
|
|
unsigned char Line[17];
|
|
const unsigned char *PrintCharacter = (const unsigned char *)Start;
|
|
|
|
unsigned int I = 0;
|
|
for (; I < ((const int *)End - (const int *)Start); I++) {
|
|
if ((I % 16) == 0) {
|
|
if (I != 0)
|
|
printf(" %s\n", Line);
|
|
|
|
printf(" %04x ", I);
|
|
}
|
|
|
|
printf(" %02x", PrintCharacter[I]);
|
|
|
|
if ((PrintCharacter[I] < 0x20) || (PrintCharacter[I] > 0x7e))
|
|
Line[I % 16] = '.';
|
|
else
|
|
Line[I % 16] = PrintCharacter[I];
|
|
|
|
Line[(I % 16) + 1] = '\0';
|
|
}
|
|
|
|
while ((I % 16) != 0) {
|
|
printf(" ");
|
|
I++;
|
|
}
|
|
|
|
printf(" %s\n", Line);
|
|
}
|
|
|
|
void dump(__tgt_offload_entry *Entry) {
|
|
fprintf(stderr, "Entry (%p):\n", (void *)Entry);
|
|
fprintf(stderr, " Name: %s (%p)\n", Entry->name, (void *)&Entry->name);
|
|
fprintf(stderr, " Reserved: %d (%p)\n", Entry->reserved,
|
|
(void *)&Entry->reserved);
|
|
fprintf(stderr, " Flags: %d (%p)\n", Entry->flags, (void *)&Entry->flags);
|
|
fprintf(stderr, " Addr: %p\n", Entry->addr);
|
|
fprintf(stderr, " Size: %lu\n", Entry->size);
|
|
}
|
|
|
|
void dump(__tgt_target_table *Table) {
|
|
for (auto *CurEntry = Table->EntriesBegin; CurEntry != Table->EntriesEnd;
|
|
CurEntry++)
|
|
dump(CurEntry);
|
|
}
|
|
|
|
void dump(TargetOffloadEntry Entry) {
|
|
fprintf(stderr, "Entry: ");
|
|
fprintf(stderr, " Name: %s\n", Entry.name().c_str());
|
|
fprintf(stderr, " Reserved: %d\n", Entry.reserved());
|
|
fprintf(stderr, " Flags: %d\n", Entry.flags());
|
|
fprintf(stderr, " Size: %ld\n", Entry.data().size());
|
|
dump(static_cast<const void *>(Entry.data().data()),
|
|
static_cast<const void *>((Entry.data().c_str() + Entry.data().size())));
|
|
}
|
|
|
|
void dump(__tgt_device_image *Image) {
|
|
dump(Image->ImageStart, Image->ImageEnd);
|
|
__tgt_offload_entry *EntryItr = Image->EntriesBegin;
|
|
for (; EntryItr != Image->EntriesEnd; EntryItr++)
|
|
dump(EntryItr);
|
|
}
|
|
|
|
void dump(std::unordered_map<void *, __tgt_offload_entry *> &Map) {
|
|
fprintf(stderr, "Host to Remote Entry Map:\n");
|
|
for (auto Entry : Map)
|
|
fprintf(stderr, " Host (%p) -> Tgt (%p): Addr((%p))\n", Entry.first,
|
|
(void *)Entry.second, (void *)Entry.second->addr);
|
|
}
|
|
} // namespace RemoteOffloading
|