1//===- RPC.h - Interface for remote procedure calls from the GPU ----------===//
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#include "RPC.h"
10
11#include "Shared/Debug.h"
12
13#include "PluginInterface.h"
14
15#if defined(LIBOMPTARGET_RPC_SUPPORT)
16#include "llvm-libc-types/rpc_opcodes_t.h"
17#include "llvmlibc_rpc_server.h"
18#endif
19
20using namespace llvm;
21using namespace omp;
22using namespace target;
23
24RPCServerTy::RPCServerTy(plugin::GenericPluginTy &Plugin)
25 : Handles(Plugin.getNumDevices()) {}
26
27llvm::Expected<bool>
28RPCServerTy::isDeviceUsingRPC(plugin::GenericDeviceTy &Device,
29 plugin::GenericGlobalHandlerTy &Handler,
30 plugin::DeviceImageTy &Image) {
31#ifdef LIBOMPTARGET_RPC_SUPPORT
32 return Handler.isSymbolInImage(Device, Image, rpc_client_symbol_name);
33#else
34 return false;
35#endif
36}
37
38Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device,
39 plugin::GenericGlobalHandlerTy &Handler,
40 plugin::DeviceImageTy &Image) {
41#ifdef LIBOMPTARGET_RPC_SUPPORT
42 auto Alloc = [](uint64_t Size, void *Data) {
43 plugin::GenericDeviceTy &Device =
44 *reinterpret_cast<plugin::GenericDeviceTy *>(Data);
45 return Device.allocate(Size, nullptr, TARGET_ALLOC_HOST);
46 };
47 uint64_t NumPorts =
48 std::min(Device.requestedRPCPortCount(), RPC_MAXIMUM_PORT_COUNT);
49 rpc_device_t RPCDevice;
50 if (rpc_status_t Err = rpc_server_init(&RPCDevice, NumPorts,
51 Device.getWarpSize(), Alloc, &Device))
52 return plugin::Plugin::error(
53 "Failed to initialize RPC server for device %d: %d",
54 Device.getDeviceId(), Err);
55
56 // Register a custom opcode handler to perform plugin specific allocation.
57 auto MallocHandler = [](rpc_port_t Port, void *Data) {
58 rpc_recv_and_send(
59 Port,
60 [](rpc_buffer_t *Buffer, void *Data) {
61 plugin::GenericDeviceTy &Device =
62 *reinterpret_cast<plugin::GenericDeviceTy *>(Data);
63 Buffer->data[0] = reinterpret_cast<uintptr_t>(Device.allocate(
64 Buffer->data[0], nullptr, TARGET_ALLOC_DEVICE_NON_BLOCKING));
65 },
66 Data);
67 };
68 if (rpc_status_t Err =
69 rpc_register_callback(RPCDevice, RPC_MALLOC, MallocHandler, &Device))
70 return plugin::Plugin::error(
71 "Failed to register RPC malloc handler for device %d: %d\n",
72 Device.getDeviceId(), Err);
73
74 // Register a custom opcode handler to perform plugin specific deallocation.
75 auto FreeHandler = [](rpc_port_t Port, void *Data) {
76 rpc_recv(
77 Port,
78 [](rpc_buffer_t *Buffer, void *Data) {
79 plugin::GenericDeviceTy &Device =
80 *reinterpret_cast<plugin::GenericDeviceTy *>(Data);
81 Device.free(reinterpret_cast<void *>(Buffer->data[0]),
82 TARGET_ALLOC_DEVICE_NON_BLOCKING);
83 },
84 Data);
85 };
86 if (rpc_status_t Err =
87 rpc_register_callback(RPCDevice, RPC_FREE, FreeHandler, &Device))
88 return plugin::Plugin::error(
89 "Failed to register RPC free handler for device %d: %d\n",
90 Device.getDeviceId(), Err);
91
92 // Get the address of the RPC client from the device.
93 void *ClientPtr;
94 plugin::GlobalTy ClientGlobal(rpc_client_symbol_name, sizeof(void *));
95 if (auto Err =
96 Handler.getGlobalMetadataFromDevice(Device, Image, ClientGlobal))
97 return Err;
98
99 if (auto Err = Device.dataRetrieve(&ClientPtr, ClientGlobal.getPtr(),
100 sizeof(void *), nullptr))
101 return Err;
102
103 const void *ClientBuffer = rpc_get_client_buffer(RPCDevice);
104 if (auto Err = Device.dataSubmit(ClientPtr, ClientBuffer,
105 rpc_get_client_size(), nullptr))
106 return Err;
107 Handles[Device.getDeviceId()] = RPCDevice.handle;
108#endif
109 return Error::success();
110}
111
112Error RPCServerTy::runServer(plugin::GenericDeviceTy &Device) {
113#ifdef LIBOMPTARGET_RPC_SUPPORT
114 rpc_device_t RPCDevice{Handles[Device.getDeviceId()]};
115 if (rpc_status_t Err = rpc_handle_server(RPCDevice))
116 return plugin::Plugin::error(
117 "Error while running RPC server on device %d: %d", Device.getDeviceId(),
118 Err);
119#endif
120 return Error::success();
121}
122
123Error RPCServerTy::deinitDevice(plugin::GenericDeviceTy &Device) {
124#ifdef LIBOMPTARGET_RPC_SUPPORT
125 rpc_device_t RPCDevice{Handles[Device.getDeviceId()]};
126 auto Dealloc = [](void *Ptr, void *Data) {
127 plugin::GenericDeviceTy &Device =
128 *reinterpret_cast<plugin::GenericDeviceTy *>(Data);
129 Device.free(Ptr, TARGET_ALLOC_HOST);
130 };
131 if (rpc_status_t Err = rpc_server_shutdown(RPCDevice, Dealloc, &Device))
132 return plugin::Plugin::error(
133 "Failed to shut down RPC server for device %d: %d",
134 Device.getDeviceId(), Err);
135#endif
136 return Error::success();
137}
138

source code of offload/plugins-nextgen/common/src/RPC.cpp