1 //===---------------- Utils.cpp - Utilities for Remote RTL ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utilities for data movement and debugging.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Utils.h"
14 #include "omptarget.h"
15 
16 namespace RemoteOffloading {
17 
loadTargetBinaryDescription(const __tgt_bin_desc * Desc,TargetBinaryDescription & Request)18 void loadTargetBinaryDescription(const __tgt_bin_desc *Desc,
19                                  TargetBinaryDescription &Request) {
20   // Keeps track of entries which have already been deep copied.
21   std::vector<void *> DeepCopiedEntryAddrs;
22 
23   // Copy Global Offload Entries
24   for (auto *CurEntry = Desc->HostEntriesBegin;
25        CurEntry != Desc->HostEntriesEnd; CurEntry++) {
26     auto *NewEntry = Request.add_entries();
27     copyOffloadEntry(CurEntry, NewEntry);
28 
29     // Copy the pointer of the offload entry of the image into the Request
30     Request.add_entry_ptrs((uint64_t)CurEntry);
31     DeepCopiedEntryAddrs.push_back(CurEntry);
32   }
33 
34   // Copy Device Images and Device Offload Entries
35   __tgt_device_image *CurImage = Desc->DeviceImages;
36   for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++) {
37     auto *Image = Request.add_images();
38     auto Size = (char *)CurImage->ImageEnd - (char *)CurImage->ImageStart;
39     Image->set_binary(CurImage->ImageStart, Size);
40 
41     // Copy the pointer of the image into the Request
42     auto *NewImagePtr = Request.add_image_ptrs();
43     NewImagePtr->set_img_ptr((uint64_t)CurImage->ImageStart);
44 
45     // Copy Device Offload Entries
46     for (auto *CurEntry = CurImage->EntriesBegin;
47          CurEntry != CurImage->EntriesEnd; CurEntry++) {
48       auto *NewEntry = Image->add_entries();
49 
50       auto Entry = std::find(DeepCopiedEntryAddrs.begin(),
51                              DeepCopiedEntryAddrs.end(), CurEntry);
52       if (Entry != DeepCopiedEntryAddrs.end()) {
53         // Offload entry has already been loaded
54         shallowCopyOffloadEntry(CurEntry, NewEntry);
55       } else { // Offload Entry has not been loaded into the Request
56         copyOffloadEntry(CurEntry, NewEntry);
57         DeepCopiedEntryAddrs.push_back(CurEntry);
58       }
59 
60       // Copy the pointer of the offload entry of the image into the Request
61       NewImagePtr->add_entry_ptrs((uint64_t)CurEntry);
62     }
63   }
64 }
65 
unloadTargetBinaryDescription(const TargetBinaryDescription * Request,__tgt_bin_desc * Desc,std::unordered_map<const void *,__tgt_device_image * > & HostToRemoteDeviceImage)66 void unloadTargetBinaryDescription(
67     const TargetBinaryDescription *Request, __tgt_bin_desc *Desc,
68     std::unordered_map<const void *, __tgt_device_image *>
69         &HostToRemoteDeviceImage) {
70   std::unordered_map<const void *, __tgt_offload_entry *> CopiedOffloadEntries;
71   Desc->NumDeviceImages = Request->images_size();
72   Desc->DeviceImages = new __tgt_device_image[Desc->NumDeviceImages];
73 
74   if (Request->entries_size())
75     Desc->HostEntriesBegin = new __tgt_offload_entry[Request->entries_size()];
76   else {
77     Desc->HostEntriesBegin = nullptr;
78     Desc->HostEntriesEnd = nullptr;
79   }
80 
81   // Copy Global Offload Entries
82   __tgt_offload_entry *CurEntry = Desc->HostEntriesBegin;
83   size_t I = 0;
84   for (auto &Entry : Request->entries()) {
85     copyOffloadEntry(Entry, CurEntry);
86     CopiedOffloadEntries[(void *)Request->entry_ptrs()[I]] = CurEntry;
87     CurEntry++;
88     I++;
89   }
90   Desc->HostEntriesEnd = CurEntry;
91 
92   // Copy Device Images and Device Offload Entries
93   __tgt_device_image *CurImage = Desc->DeviceImages;
94   auto ImageItr = Request->image_ptrs().begin();
95   for (auto Image : Request->images()) {
96     // Copy Device Offload Entries
97     CurEntry = Desc->HostEntriesBegin;
98     bool Found = false;
99 
100     if (!Desc->HostEntriesBegin) {
101       CurImage->EntriesBegin = nullptr;
102       CurImage->EntriesEnd = nullptr;
103     }
104 
105     for (size_t I = 0; I < Image.entries_size(); I++) {
106       auto TgtEntry =
107           CopiedOffloadEntries.find((void *)Request->entry_ptrs()[I]);
108       if (TgtEntry != CopiedOffloadEntries.end()) {
109         if (!Found)
110           CurImage->EntriesBegin = CurEntry;
111 
112         CurImage->EntriesEnd = CurEntry + 1;
113         Found = true;
114       } else {
115         Found = false;
116         copyOffloadEntry(Image.entries()[I], CurEntry);
117         CopiedOffloadEntries[(void *)(Request->entry_ptrs()[I])] = CurEntry;
118       }
119       CurEntry++;
120     }
121 
122     // Copy Device Image
123     CurImage->ImageStart = new uint8_t[Image.binary().size()];
124     memcpy(CurImage->ImageStart,
125            static_cast<const void *>(Image.binary().data()),
126            Image.binary().size());
127     CurImage->ImageEnd =
128         (void *)((char *)CurImage->ImageStart + Image.binary().size());
129 
130     HostToRemoteDeviceImage[(void *)ImageItr->img_ptr()] = CurImage;
131     CurImage++;
132     ImageItr++;
133   }
134 }
135 
freeTargetBinaryDescription(__tgt_bin_desc * Desc)136 void freeTargetBinaryDescription(__tgt_bin_desc *Desc) {
137   __tgt_device_image *CurImage = Desc->DeviceImages;
138   for (auto I = 0; I < Desc->NumDeviceImages; I++, CurImage++)
139     delete[](uint64_t *) CurImage->ImageStart;
140 
141   delete[] Desc->DeviceImages;
142 
143   for (auto *Entry = Desc->HostEntriesBegin; Entry != Desc->HostEntriesEnd;
144        Entry++) {
145     free(Entry->name);
146     free(Entry->addr);
147   }
148 
149   delete[] Desc->HostEntriesBegin;
150 }
151 
freeTargetTable(__tgt_target_table * Table)152 void freeTargetTable(__tgt_target_table *Table) {
153   for (auto *Entry = Table->EntriesBegin; Entry != Table->EntriesEnd; Entry++)
154     free(Entry->name);
155 
156   delete[] Table->EntriesBegin;
157 }
158 
loadTargetTable(__tgt_target_table * Table,TargetTable & TableResponse,__tgt_device_image * Image)159 void loadTargetTable(__tgt_target_table *Table, TargetTable &TableResponse,
160                      __tgt_device_image *Image) {
161   auto *ImageEntry = Image->EntriesBegin;
162   for (__tgt_offload_entry *CurEntry = Table->EntriesBegin;
163        CurEntry != Table->EntriesEnd; CurEntry++, ImageEntry++) {
164     // TODO: This can probably be trimmed substantially.
165     auto *NewEntry = TableResponse.add_entries();
166     NewEntry->set_name(CurEntry->name);
167     NewEntry->set_addr((uint64_t)CurEntry->addr);
168     NewEntry->set_flags(CurEntry->flags);
169     NewEntry->set_reserved(CurEntry->reserved);
170     NewEntry->set_size(CurEntry->size);
171     TableResponse.add_entry_ptrs((int64_t)CurEntry);
172   }
173 }
174 
unloadTargetTable(TargetTable & TableResponse,__tgt_target_table * Table,std::unordered_map<void *,void * > & HostToRemoteTargetTableMap)175 void unloadTargetTable(
176     TargetTable &TableResponse, __tgt_target_table *Table,
177     std::unordered_map<void *, void *> &HostToRemoteTargetTableMap) {
178   Table->EntriesBegin = new __tgt_offload_entry[TableResponse.entries_size()];
179 
180   auto *CurEntry = Table->EntriesBegin;
181   for (size_t I = 0; I < TableResponse.entries_size(); I++) {
182     copyOffloadEntry(TableResponse.entries()[I], CurEntry);
183     HostToRemoteTargetTableMap[CurEntry->addr] =
184         (void *)TableResponse.entry_ptrs()[I];
185     CurEntry++;
186   }
187   Table->EntriesEnd = CurEntry;
188 }
189 
copyOffloadEntry(const TargetOffloadEntry & EntryResponse,__tgt_offload_entry * Entry)190 void copyOffloadEntry(const TargetOffloadEntry &EntryResponse,
191                       __tgt_offload_entry *Entry) {
192   Entry->name = strdup(EntryResponse.name().c_str());
193   Entry->reserved = EntryResponse.reserved();
194   Entry->flags = EntryResponse.flags();
195   Entry->addr = strdup(EntryResponse.data().c_str());
196   Entry->size = EntryResponse.data().size();
197 }
198 
copyOffloadEntry(const DeviceOffloadEntry & EntryResponse,__tgt_offload_entry * Entry)199 void copyOffloadEntry(const DeviceOffloadEntry &EntryResponse,
200                       __tgt_offload_entry *Entry) {
201   Entry->name = strdup(EntryResponse.name().c_str());
202   Entry->reserved = EntryResponse.reserved();
203   Entry->flags = EntryResponse.flags();
204   Entry->addr = (void *)EntryResponse.addr();
205   Entry->size = EntryResponse.size();
206 }
207 
208 /// We shallow copy with just the name because it is a convenient identifier, we
209 /// do actually just match off of the address.
shallowCopyOffloadEntry(const __tgt_offload_entry * Entry,TargetOffloadEntry * EntryResponse)210 void shallowCopyOffloadEntry(const __tgt_offload_entry *Entry,
211                              TargetOffloadEntry *EntryResponse) {
212   EntryResponse->set_name(Entry->name);
213 }
214 
copyOffloadEntry(const __tgt_offload_entry * Entry,TargetOffloadEntry * EntryResponse)215 void copyOffloadEntry(const __tgt_offload_entry *Entry,
216                       TargetOffloadEntry *EntryResponse) {
217   shallowCopyOffloadEntry(Entry, EntryResponse);
218   EntryResponse->set_reserved(Entry->reserved);
219   EntryResponse->set_flags(Entry->flags);
220   EntryResponse->set_data(Entry->addr, Entry->size);
221 }
222 
223 /// Dumps the memory region from Start to End in order to debug memory transfer
224 /// errors within the plugin
dump(const void * Start,const void * End)225 void dump(const void *Start, const void *End) {
226   unsigned char Line[17];
227   const unsigned char *PrintCharacter = (const unsigned char *)Start;
228 
229   unsigned int I = 0;
230   for (; I < ((const int *)End - (const int *)Start); I++) {
231     if ((I % 16) == 0) {
232       if (I != 0)
233         printf("  %s\n", Line);
234 
235       printf("  %04x ", I);
236     }
237 
238     printf(" %02x", PrintCharacter[I]);
239 
240     if ((PrintCharacter[I] < 0x20) || (PrintCharacter[I] > 0x7e))
241       Line[I % 16] = '.';
242     else
243       Line[I % 16] = PrintCharacter[I];
244 
245     Line[(I % 16) + 1] = '\0';
246   }
247 
248   while ((I % 16) != 0) {
249     printf("   ");
250     I++;
251   }
252 
253   printf("  %s\n", Line);
254 }
255 
dump(__tgt_offload_entry * Entry)256 void dump(__tgt_offload_entry *Entry) {
257   fprintf(stderr, "Entry (%p):\n", (void *)Entry);
258   fprintf(stderr, "  Name: %s (%p)\n", Entry->name, (void *)&Entry->name);
259   fprintf(stderr, "  Reserved: %d (%p)\n", Entry->reserved,
260           (void *)&Entry->reserved);
261   fprintf(stderr, "  Flags: %d (%p)\n", Entry->flags, (void *)&Entry->flags);
262   fprintf(stderr, "  Addr: %p\n", Entry->addr);
263   fprintf(stderr, "  Size: %lu\n", Entry->size);
264 }
265 
dump(__tgt_target_table * Table)266 void dump(__tgt_target_table *Table) {
267   for (auto *CurEntry = Table->EntriesBegin; CurEntry != Table->EntriesEnd;
268        CurEntry++)
269     dump(CurEntry);
270 }
271 
dump(TargetOffloadEntry Entry)272 void dump(TargetOffloadEntry Entry) {
273   fprintf(stderr, "Entry: ");
274   fprintf(stderr, "  Name: %s\n", Entry.name().c_str());
275   fprintf(stderr, "  Reserved: %d\n", Entry.reserved());
276   fprintf(stderr, "  Flags: %d\n", Entry.flags());
277   fprintf(stderr, "  Size:  %ld\n", Entry.data().size());
278   dump(static_cast<const void *>(Entry.data().data()),
279        static_cast<const void *>((Entry.data().c_str() + Entry.data().size())));
280 }
281 
dump(__tgt_device_image * Image)282 void dump(__tgt_device_image *Image) {
283   dump(Image->ImageStart, Image->ImageEnd);
284   __tgt_offload_entry *EntryItr = Image->EntriesBegin;
285   for (; EntryItr != Image->EntriesEnd; EntryItr++)
286     dump(EntryItr);
287 }
288 
dump(std::unordered_map<void *,__tgt_offload_entry * > & Map)289 void dump(std::unordered_map<void *, __tgt_offload_entry *> &Map) {
290   fprintf(stderr, "Host to Remote Entry Map:\n");
291   for (auto Entry : Map)
292     fprintf(stderr, "  Host (%p) -> Tgt (%p): Addr((%p))\n", Entry.first,
293             (void *)Entry.second, (void *)Entry.second->addr);
294 }
295 } // namespace RemoteOffloading