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