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 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 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 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 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 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 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 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 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. 210 void shallowCopyOffloadEntry(const __tgt_offload_entry *Entry, 211 TargetOffloadEntry *EntryResponse) { 212 EntryResponse->set_name(Entry->name); 213 } 214 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 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 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 266 void dump(__tgt_target_table *Table) { 267 for (auto *CurEntry = Table->EntriesBegin; CurEntry != Table->EntriesEnd; 268 CurEntry++) 269 dump(CurEntry); 270 } 271 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 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 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 296