1/*
2    Copyright (c) 2014 Intel Corporation.  All Rights Reserved.
3
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7
8      * Redistributions of source code must retain the above copyright
9        notice, this list of conditions and the following disclaimer.
10      * Redistributions in binary form must reproduce the above copyright
11        notice, this list of conditions and the following disclaimer in the
12        documentation and/or other materials provided with the distribution.
13      * Neither the name of Intel Corporation nor the names of its
14        contributors may be used to endorse or promote products derived
15        from this software without specific prior written permission.
16
17    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30
31// The COI host interface
32
33#include "coi_client.h"
34#include "../offload_common.h"
35
36namespace COI {
37
38#define COI_VERSION1    "COI_1.0"
39#define COI_VERSION2    "COI_2.0"
40
41bool            is_available;
42static void*    lib_handle;
43
44// pointers to functions from COI library
45COIRESULT (*EngineGetCount)(COI_ISA_TYPE, uint32_t*);
46COIRESULT (*EngineGetHandle)(COI_ISA_TYPE, uint32_t, COIENGINE*);
47
48COIRESULT (*ProcessCreateFromMemory)(COIENGINE, const char*, const void*,
49                                     uint64_t, int, const char**, uint8_t,
50                                     const char**, uint8_t, const char*,
51                                     uint64_t, const char*, const char*,
52                                     uint64_t, COIPROCESS*);
53COIRESULT (*ProcessDestroy)(COIPROCESS, int32_t, uint8_t, int8_t*, uint32_t*);
54COIRESULT (*ProcessGetFunctionHandles)(COIPROCESS, uint32_t, const char**,
55                                       COIFUNCTION*);
56COIRESULT (*ProcessLoadLibraryFromMemory)(COIPROCESS, const void*, uint64_t,
57                                          const char*, const char*,
58                                          const char*, uint64_t, uint32_t,
59                                          COILIBRARY*);
60COIRESULT (*ProcessRegisterLibraries)(uint32_t, const void**, const uint64_t*,
61                                      const char**, const uint64_t*);
62
63COIRESULT (*PipelineCreate)(COIPROCESS, COI_CPU_MASK, uint32_t, COIPIPELINE*);
64COIRESULT (*PipelineDestroy)(COIPIPELINE);
65COIRESULT (*PipelineRunFunction)(COIPIPELINE, COIFUNCTION, uint32_t,
66                                 const COIBUFFER*, const COI_ACCESS_FLAGS*,
67                                 uint32_t, const COIEVENT*, const void*,
68                                 uint16_t, void*, uint16_t, COIEVENT*);
69
70COIRESULT (*BufferCreate)(uint64_t, COI_BUFFER_TYPE, uint32_t, const void*,
71                          uint32_t, const COIPROCESS*, COIBUFFER*);
72COIRESULT (*BufferCreateFromMemory)(uint64_t, COI_BUFFER_TYPE, uint32_t,
73                                    void*, uint32_t, const COIPROCESS*,
74                                    COIBUFFER*);
75COIRESULT (*BufferDestroy)(COIBUFFER);
76COIRESULT (*BufferMap)(COIBUFFER, uint64_t, uint64_t, COI_MAP_TYPE, uint32_t,
77                       const COIEVENT*, COIEVENT*, COIMAPINSTANCE*, void**);
78COIRESULT (*BufferUnmap)(COIMAPINSTANCE, uint32_t, const COIEVENT*, COIEVENT*);
79COIRESULT (*BufferWrite)(COIBUFFER, uint64_t, const void*, uint64_t,
80                         COI_COPY_TYPE, uint32_t, const COIEVENT*, COIEVENT*);
81COIRESULT (*BufferRead)(COIBUFFER, uint64_t, void*, uint64_t, COI_COPY_TYPE,
82                        uint32_t, const COIEVENT*, COIEVENT*);
83COIRESULT (*BufferCopy)(COIBUFFER, COIBUFFER, uint64_t, uint64_t, uint64_t,
84                        COI_COPY_TYPE, uint32_t, const COIEVENT*, COIEVENT*);
85COIRESULT (*BufferGetSinkAddress)(COIBUFFER, uint64_t*);
86COIRESULT (*BufferSetState)(COIBUFFER, COIPROCESS, COI_BUFFER_STATE,
87                            COI_BUFFER_MOVE_FLAG, uint32_t,
88                            const   COIEVENT*, COIEVENT*);
89
90COIRESULT (*EventWait)(uint16_t, const COIEVENT*, int32_t, uint8_t, uint32_t*,
91                       uint32_t*);
92
93uint64_t  (*PerfGetCycleFrequency)(void);
94
95bool init(void)
96{
97#ifndef TARGET_WINNT
98    const char *lib_name = "libcoi_host.so.0";
99#else // TARGET_WINNT
100    const char *lib_name = "coi_host.dll";
101#endif // TARGET_WINNT
102
103    OFFLOAD_DEBUG_TRACE(2, "Loading COI library %s ...\n", lib_name);
104    lib_handle = DL_open(lib_name);
105    if (lib_handle == 0) {
106        OFFLOAD_DEBUG_TRACE(2, "Failed to load the library\n");
107        return false;
108    }
109
110    EngineGetCount =
111        (COIRESULT (*)(COI_ISA_TYPE, uint32_t*))
112            DL_sym(lib_handle, "COIEngineGetCount", COI_VERSION1);
113    if (EngineGetCount == 0) {
114        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
115                            "COIEngineGetCount");
116        fini();
117        return false;
118    }
119
120    EngineGetHandle =
121        (COIRESULT (*)(COI_ISA_TYPE, uint32_t, COIENGINE*))
122            DL_sym(lib_handle, "COIEngineGetHandle", COI_VERSION1);
123    if (EngineGetHandle == 0) {
124        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
125                            "COIEngineGetHandle");
126        fini();
127        return false;
128    }
129
130    ProcessCreateFromMemory =
131        (COIRESULT (*)(COIENGINE, const char*, const void*, uint64_t, int,
132                       const char**, uint8_t, const char**, uint8_t,
133                       const char*, uint64_t, const char*, const char*,
134                       uint64_t, COIPROCESS*))
135            DL_sym(lib_handle, "COIProcessCreateFromMemory", COI_VERSION1);
136    if (ProcessCreateFromMemory == 0) {
137        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
138                            "COIProcessCreateFromMemory");
139        fini();
140        return false;
141    }
142
143    ProcessDestroy =
144        (COIRESULT (*)(COIPROCESS, int32_t, uint8_t, int8_t*,
145                       uint32_t*))
146            DL_sym(lib_handle, "COIProcessDestroy", COI_VERSION1);
147    if (ProcessDestroy == 0) {
148        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
149                            "COIProcessDestroy");
150        fini();
151        return false;
152    }
153
154    ProcessGetFunctionHandles =
155        (COIRESULT (*)(COIPROCESS, uint32_t, const char**, COIFUNCTION*))
156            DL_sym(lib_handle, "COIProcessGetFunctionHandles", COI_VERSION1);
157    if (ProcessGetFunctionHandles == 0) {
158        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
159                            "COIProcessGetFunctionHandles");
160        fini();
161        return false;
162    }
163
164    ProcessLoadLibraryFromMemory =
165        (COIRESULT (*)(COIPROCESS, const void*, uint64_t, const char*,
166                       const char*, const char*, uint64_t, uint32_t,
167                       COILIBRARY*))
168            DL_sym(lib_handle, "COIProcessLoadLibraryFromMemory", COI_VERSION2);
169    if (ProcessLoadLibraryFromMemory == 0) {
170        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
171                            "COIProcessLoadLibraryFromMemory");
172        fini();
173        return false;
174    }
175
176    ProcessRegisterLibraries =
177        (COIRESULT (*)(uint32_t, const void**, const uint64_t*, const char**,
178                       const uint64_t*))
179            DL_sym(lib_handle, "COIProcessRegisterLibraries", COI_VERSION1);
180    if (ProcessRegisterLibraries == 0) {
181        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
182                            "COIProcessRegisterLibraries");
183        fini();
184        return false;
185    }
186
187    PipelineCreate =
188        (COIRESULT (*)(COIPROCESS, COI_CPU_MASK, uint32_t, COIPIPELINE*))
189            DL_sym(lib_handle, "COIPipelineCreate", COI_VERSION1);
190    if (PipelineCreate == 0) {
191        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
192                            "COIPipelineCreate");
193        fini();
194        return false;
195    }
196
197    PipelineDestroy =
198        (COIRESULT (*)(COIPIPELINE))
199            DL_sym(lib_handle, "COIPipelineDestroy", COI_VERSION1);
200    if (PipelineDestroy == 0) {
201        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
202                            "COIPipelineDestroy");
203        fini();
204        return false;
205    }
206
207    PipelineRunFunction =
208        (COIRESULT (*)(COIPIPELINE, COIFUNCTION, uint32_t, const COIBUFFER*,
209                       const COI_ACCESS_FLAGS*, uint32_t, const COIEVENT*,
210                       const void*, uint16_t, void*, uint16_t, COIEVENT*))
211            DL_sym(lib_handle, "COIPipelineRunFunction", COI_VERSION1);
212    if (PipelineRunFunction == 0) {
213        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
214                            "COIPipelineRunFunction");
215        fini();
216        return false;
217    }
218
219    BufferCreate =
220        (COIRESULT (*)(uint64_t, COI_BUFFER_TYPE, uint32_t, const void*,
221                       uint32_t, const COIPROCESS*, COIBUFFER*))
222            DL_sym(lib_handle, "COIBufferCreate", COI_VERSION1);
223    if (BufferCreate == 0) {
224        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
225                            "COIBufferCreate");
226        fini();
227        return false;
228    }
229
230    BufferCreateFromMemory =
231        (COIRESULT (*)(uint64_t, COI_BUFFER_TYPE, uint32_t, void*,
232                       uint32_t, const COIPROCESS*, COIBUFFER*))
233            DL_sym(lib_handle, "COIBufferCreateFromMemory", COI_VERSION1);
234    if (BufferCreateFromMemory == 0) {
235        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
236                            "COIBufferCreateFromMemory");
237        fini();
238        return false;
239    }
240
241    BufferDestroy =
242        (COIRESULT (*)(COIBUFFER))
243            DL_sym(lib_handle, "COIBufferDestroy", COI_VERSION1);
244    if (BufferDestroy == 0) {
245        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
246                            "COIBufferDestroy");
247        fini();
248        return false;
249    }
250
251    BufferMap =
252        (COIRESULT (*)(COIBUFFER, uint64_t, uint64_t, COI_MAP_TYPE, uint32_t,
253                       const COIEVENT*, COIEVENT*, COIMAPINSTANCE*,
254                       void**))
255            DL_sym(lib_handle, "COIBufferMap", COI_VERSION1);
256    if (BufferMap == 0) {
257        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
258                            "COIBufferMap");
259        fini();
260        return false;
261    }
262
263    BufferUnmap =
264        (COIRESULT (*)(COIMAPINSTANCE, uint32_t, const COIEVENT*,
265                       COIEVENT*))
266            DL_sym(lib_handle, "COIBufferUnmap", COI_VERSION1);
267    if (BufferUnmap == 0) {
268        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
269                            "COIBufferUnmap");
270        fini();
271        return false;
272    }
273
274    BufferWrite =
275        (COIRESULT (*)(COIBUFFER, uint64_t, const void*, uint64_t,
276                       COI_COPY_TYPE, uint32_t, const COIEVENT*,
277                       COIEVENT*))
278            DL_sym(lib_handle, "COIBufferWrite", COI_VERSION1);
279    if (BufferWrite == 0) {
280        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
281                            "COIBufferWrite");
282        fini();
283        return false;
284    }
285
286    BufferRead =
287        (COIRESULT (*)(COIBUFFER, uint64_t, void*, uint64_t,
288                                     COI_COPY_TYPE, uint32_t,
289                                     const COIEVENT*, COIEVENT*))
290            DL_sym(lib_handle, "COIBufferRead", COI_VERSION1);
291    if (BufferRead == 0) {
292        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
293                            "COIBufferRead");
294        fini();
295        return false;
296    }
297
298    BufferCopy =
299        (COIRESULT (*)(COIBUFFER, COIBUFFER, uint64_t, uint64_t, uint64_t,
300                       COI_COPY_TYPE, uint32_t, const COIEVENT*,
301                       COIEVENT*))
302            DL_sym(lib_handle, "COIBufferCopy", COI_VERSION1);
303    if (BufferCopy == 0) {
304        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
305                            "COIBufferCopy");
306        fini();
307        return false;
308    }
309
310    BufferGetSinkAddress =
311        (COIRESULT (*)(COIBUFFER, uint64_t*))
312            DL_sym(lib_handle, "COIBufferGetSinkAddress", COI_VERSION1);
313    if (BufferGetSinkAddress == 0) {
314        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
315                            "COIBufferGetSinkAddress");
316        fini();
317        return false;
318    }
319
320    BufferSetState =
321        (COIRESULT(*)(COIBUFFER, COIPROCESS, COI_BUFFER_STATE,
322                      COI_BUFFER_MOVE_FLAG, uint32_t, const COIEVENT*,
323                      COIEVENT*))
324            DL_sym(lib_handle, "COIBufferSetState", COI_VERSION1);
325    if (BufferSetState == 0) {
326        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
327                            "COIBufferSetState");
328        fini();
329        return false;
330    }
331
332    EventWait =
333        (COIRESULT (*)(uint16_t, const COIEVENT*, int32_t, uint8_t,
334                       uint32_t*, uint32_t*))
335            DL_sym(lib_handle, "COIEventWait", COI_VERSION1);
336    if (EventWait == 0) {
337        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
338                            "COIEventWait");
339        fini();
340        return false;
341    }
342
343    PerfGetCycleFrequency =
344        (uint64_t (*)(void))
345            DL_sym(lib_handle, "COIPerfGetCycleFrequency", COI_VERSION1);
346    if (PerfGetCycleFrequency == 0) {
347        OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
348                            "COIPerfGetCycleFrequency");
349        fini();
350        return false;
351    }
352
353    is_available = true;
354
355    return true;
356}
357
358void fini(void)
359{
360    is_available = false;
361
362    if (lib_handle != 0) {
363#ifndef TARGET_WINNT
364        DL_close(lib_handle);
365#endif // TARGET_WINNT
366        lib_handle = 0;
367    }
368}
369
370} // namespace COI
371