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