1 /*
2     Copyright (c) 2014-2016 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 
36 namespace COI {
37 
38 #define COI_VERSION1    "COI_1.0"
39 #define COI_VERSION2    "COI_2.0"
40 
41 bool            is_available;
42 static void*    lib_handle;
43 
44 // pointers to functions from COI library
45 COIRESULT (*EngineGetCount)(COI_ISA_TYPE, uint32_t*);
46 COIRESULT (*EngineGetHandle)(COI_ISA_TYPE, uint32_t, COIENGINE*);
47 
48 COIRESULT (*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*);
53 COIRESULT (*ProcessCreateFromFile)(COIENGINE, const char*,
54                                      int, const char**, uint8_t,
55                                      const char**, uint8_t, const char*,
56                                      uint64_t, const char*,COIPROCESS*);
57 COIRESULT (*ProcessSetCacheSize)(COIPROCESS, uint64_t, uint32_t,
58                                  uint64_t, uint32_t, uint32_t,
59                                  const COIEVENT*, COIEVENT*);
60 COIRESULT (*ProcessDestroy)(COIPROCESS, int32_t, uint8_t, int8_t*, uint32_t*);
61 COIRESULT (*ProcessGetFunctionHandles)(COIPROCESS, uint32_t, const char**,
62                                        COIFUNCTION*);
63 COIRESULT (*ProcessLoadLibraryFromMemory)(COIPROCESS, const void*, uint64_t,
64                                           const char*, const char*,
65                                           const char*, uint64_t, uint32_t,
66                                           COILIBRARY*);
67 COIRESULT (*ProcessUnloadLibrary)(COIPROCESS,
68                                   COILIBRARY);
69 COIRESULT (*ProcessRegisterLibraries)(uint32_t, const void**, const uint64_t*,
70                                       const char**, const uint64_t*);
71 
72 COIRESULT (*PipelineCreate)(COIPROCESS, COI_CPU_MASK, uint32_t, COIPIPELINE*);
73 COIRESULT (*PipelineDestroy)(COIPIPELINE);
74 COIRESULT (*PipelineRunFunction)(COIPIPELINE, COIFUNCTION, uint32_t,
75                                  const COIBUFFER*, const COI_ACCESS_FLAGS*,
76                                  uint32_t, const COIEVENT*, const void*,
77                                  uint16_t, void*, uint16_t, COIEVENT*);
78 
79 COIRESULT (*BufferCreate)(uint64_t, COI_BUFFER_TYPE, uint32_t, const void*,
80                           uint32_t, const COIPROCESS*, COIBUFFER*);
81 COIRESULT (*BufferCreateFromMemory)(uint64_t, COI_BUFFER_TYPE, uint32_t,
82                                     void*, uint32_t, const COIPROCESS*,
83                                     COIBUFFER*);
84 COIRESULT (*BufferDestroy)(COIBUFFER);
85 COIRESULT (*BufferMap)(COIBUFFER, uint64_t, uint64_t, COI_MAP_TYPE, uint32_t,
86                        const COIEVENT*, COIEVENT*, COIMAPINSTANCE*, void**);
87 COIRESULT (*BufferUnmap)(COIMAPINSTANCE, uint32_t, const COIEVENT*, COIEVENT*);
88 COIRESULT (*BufferWrite)(COIBUFFER, uint64_t, const void*, uint64_t,
89                          COI_COPY_TYPE, uint32_t, const COIEVENT*, COIEVENT*);
90 COIRESULT (*BufferRead)(COIBUFFER, uint64_t, void*, uint64_t, COI_COPY_TYPE,
91                         uint32_t, const COIEVENT*, COIEVENT*);
92 COIRESULT (*BufferReadMultiD)(COIBUFFER, uint64_t,
93                         void *, void *, COI_COPY_TYPE,
94                         uint32_t, const   COIEVENT*, COIEVENT*);
95 COIRESULT (*BufferWriteMultiD)(COIBUFFER, const   COIPROCESS,
96                        uint64_t, void *, void *,
97                        COI_COPY_TYPE, uint32_t, const   COIEVENT*, COIEVENT*);
98 
99 COIRESULT (*BufferCopy)(COIBUFFER, COIBUFFER, uint64_t, uint64_t, uint64_t,
100                         COI_COPY_TYPE, uint32_t, const COIEVENT*, COIEVENT*);
101 COIRESULT (*BufferGetSinkAddress)(COIBUFFER, uint64_t*);
102 COIRESULT (*BufferSetState)(COIBUFFER, COIPROCESS, COI_BUFFER_STATE,
103                             COI_BUFFER_MOVE_FLAG, uint32_t,
104                             const   COIEVENT*, COIEVENT*);
105 
106 COIRESULT (*EventWait)(uint16_t, const COIEVENT*, int32_t, uint8_t, uint32_t*,
107                        uint32_t*);
108 
109 uint64_t  (*PerfGetCycleFrequency)(void);
110 
111 COIRESULT (*PipelineClearCPUMask) (COI_CPU_MASK);
112 
113 COIRESULT (*PipelineSetCPUMask) (COIPROCESS, uint32_t,
114                                         uint8_t, COI_CPU_MASK);
115 COIRESULT (*EngineGetInfo)(COIENGINE, uint32_t, COI_ENGINE_INFO*);
116 
117 COIRESULT (*EventRegisterCallback)(
118     const COIEVENT,
119     void (*)(COIEVENT, const COIRESULT, const void*),
120     const void*,
121     const uint64_t);
122 
123 COIRESULT (*ProcessConfigureDMA)(const uint64_t, const int);
124 
init(void)125 bool init(void)
126 {
127 #ifndef TARGET_WINNT
128     const char *lib_name = "libcoi_host.so.0";
129 #else // TARGET_WINNT
130     const char *lib_name = "coi_host.dll";
131 #endif // TARGET_WINNT
132 
133     OFFLOAD_DEBUG_TRACE(2, "Loading COI library %s ...\n", lib_name);
134     lib_handle = DL_open(lib_name);
135     if (lib_handle == 0) {
136         OFFLOAD_DEBUG_TRACE(2, "Failed to load the library\n");
137         return false;
138     }
139 
140     EngineGetCount =
141         (COIRESULT (*)(COI_ISA_TYPE, uint32_t*))
142             DL_sym(lib_handle, "COIEngineGetCount", COI_VERSION1);
143     if (EngineGetCount == 0) {
144         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
145                             "COIEngineGetCount");
146         fini();
147         return false;
148     }
149 
150     EngineGetHandle =
151         (COIRESULT (*)(COI_ISA_TYPE, uint32_t, COIENGINE*))
152             DL_sym(lib_handle, "COIEngineGetHandle", COI_VERSION1);
153     if (EngineGetHandle == 0) {
154         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
155                             "COIEngineGetHandle");
156         fini();
157         return false;
158     }
159 
160     ProcessCreateFromMemory =
161         (COIRESULT (*)(COIENGINE, const char*, const void*, uint64_t, int,
162                        const char**, uint8_t, const char**, uint8_t,
163                        const char*, uint64_t, const char*, const char*,
164                        uint64_t, COIPROCESS*))
165             DL_sym(lib_handle, "COIProcessCreateFromMemory", COI_VERSION1);
166     if (ProcessCreateFromMemory == 0) {
167         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
168                             "COIProcessCreateFromMemory");
169         fini();
170         return false;
171     }
172 
173     ProcessSetCacheSize =
174            (COIRESULT (*)(COIPROCESS, uint64_t, uint32_t,
175                                  uint64_t, uint32_t, uint32_t,
176                                  const COIEVENT*, COIEVENT*))
177                DL_sym(lib_handle, "COIProcessSetCacheSize", COI_VERSION1);
178     if (ProcessSetCacheSize == 0) {
179         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
180                             "COIProcessSetCacheSize");
181 #if 0  // for now disable as ProcessSetCacheSize is not available on < MPSS 3.4
182         fini();
183         return false;
184 #endif
185     }
186 
187     ProcessCreateFromFile =
188            (COIRESULT (*)(COIENGINE, const char*, int, const char**, uint8_t,
189                           const char**, uint8_t, const char*, uint64_t,
190                           const char*, COIPROCESS*))
191             DL_sym(lib_handle, "COIProcessCreateFromFile", COI_VERSION1);
192     if (ProcessCreateFromFile == 0) {
193         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
194                             "COIProcessCreateFromFile");
195         fini();
196         return false;
197     }
198 
199     ProcessDestroy =
200         (COIRESULT (*)(COIPROCESS, int32_t, uint8_t, int8_t*,
201                        uint32_t*))
202             DL_sym(lib_handle, "COIProcessDestroy", COI_VERSION1);
203     if (ProcessDestroy == 0) {
204         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
205                             "COIProcessDestroy");
206         fini();
207         return false;
208     }
209 
210     ProcessGetFunctionHandles =
211         (COIRESULT (*)(COIPROCESS, uint32_t, const char**, COIFUNCTION*))
212             DL_sym(lib_handle, "COIProcessGetFunctionHandles", COI_VERSION1);
213     if (ProcessGetFunctionHandles == 0) {
214         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
215                             "COIProcessGetFunctionHandles");
216         fini();
217         return false;
218     }
219 
220     ProcessLoadLibraryFromMemory =
221         (COIRESULT (*)(COIPROCESS, const void*, uint64_t, const char*,
222                        const char*, const char*, uint64_t, uint32_t,
223                        COILIBRARY*))
224             DL_sym(lib_handle, "COIProcessLoadLibraryFromMemory", COI_VERSION2);
225     if (ProcessLoadLibraryFromMemory == 0) {
226         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
227                             "COIProcessLoadLibraryFromMemory");
228         fini();
229         return false;
230     }
231 
232     ProcessUnloadLibrary =
233         (COIRESULT (*)(COIPROCESS,
234                        COILIBRARY))
235             DL_sym(lib_handle, "COIProcessUnloadLibrary", COI_VERSION1);
236     if (ProcessUnloadLibrary == 0) {
237         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
238                             "COIProcessUnloadLibrary");
239         fini();
240         return false;
241     }
242 
243     ProcessRegisterLibraries =
244         (COIRESULT (*)(uint32_t, const void**, const uint64_t*, const char**,
245                        const uint64_t*))
246             DL_sym(lib_handle, "COIProcessRegisterLibraries", COI_VERSION1);
247     if (ProcessRegisterLibraries == 0) {
248         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
249                             "COIProcessRegisterLibraries");
250         fini();
251         return false;
252     }
253 
254     PipelineCreate =
255         (COIRESULT (*)(COIPROCESS, COI_CPU_MASK, uint32_t, COIPIPELINE*))
256             DL_sym(lib_handle, "COIPipelineCreate", COI_VERSION1);
257     if (PipelineCreate == 0) {
258         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
259                             "COIPipelineCreate");
260         fini();
261         return false;
262     }
263 
264     PipelineDestroy =
265         (COIRESULT (*)(COIPIPELINE))
266             DL_sym(lib_handle, "COIPipelineDestroy", COI_VERSION1);
267     if (PipelineDestroy == 0) {
268         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
269                             "COIPipelineDestroy");
270         fini();
271         return false;
272     }
273 
274     PipelineRunFunction =
275         (COIRESULT (*)(COIPIPELINE, COIFUNCTION, uint32_t, const COIBUFFER*,
276                        const COI_ACCESS_FLAGS*, uint32_t, const COIEVENT*,
277                        const void*, uint16_t, void*, uint16_t, COIEVENT*))
278             DL_sym(lib_handle, "COIPipelineRunFunction", COI_VERSION1);
279     if (PipelineRunFunction == 0) {
280         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
281                             "COIPipelineRunFunction");
282         fini();
283         return false;
284     }
285 
286     BufferCreate =
287         (COIRESULT (*)(uint64_t, COI_BUFFER_TYPE, uint32_t, const void*,
288                        uint32_t, const COIPROCESS*, COIBUFFER*))
289             DL_sym(lib_handle, "COIBufferCreate", COI_VERSION1);
290     if (BufferCreate == 0) {
291         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
292                             "COIBufferCreate");
293         fini();
294         return false;
295     }
296 
297     BufferCreateFromMemory =
298         (COIRESULT (*)(uint64_t, COI_BUFFER_TYPE, uint32_t, void*,
299                        uint32_t, const COIPROCESS*, COIBUFFER*))
300             DL_sym(lib_handle, "COIBufferCreateFromMemory", COI_VERSION1);
301     if (BufferCreateFromMemory == 0) {
302         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
303                             "COIBufferCreateFromMemory");
304         fini();
305         return false;
306     }
307 
308     BufferDestroy =
309         (COIRESULT (*)(COIBUFFER))
310             DL_sym(lib_handle, "COIBufferDestroy", COI_VERSION1);
311     if (BufferDestroy == 0) {
312         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
313                             "COIBufferDestroy");
314         fini();
315         return false;
316     }
317 
318     BufferMap =
319         (COIRESULT (*)(COIBUFFER, uint64_t, uint64_t, COI_MAP_TYPE, uint32_t,
320                        const COIEVENT*, COIEVENT*, COIMAPINSTANCE*,
321                        void**))
322             DL_sym(lib_handle, "COIBufferMap", COI_VERSION1);
323     if (BufferMap == 0) {
324         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
325                             "COIBufferMap");
326         fini();
327         return false;
328     }
329 
330     BufferUnmap =
331         (COIRESULT (*)(COIMAPINSTANCE, uint32_t, const COIEVENT*,
332                        COIEVENT*))
333             DL_sym(lib_handle, "COIBufferUnmap", COI_VERSION1);
334     if (BufferUnmap == 0) {
335         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
336                             "COIBufferUnmap");
337         fini();
338         return false;
339     }
340 
341     BufferWrite =
342         (COIRESULT (*)(COIBUFFER, uint64_t, const void*, uint64_t,
343                        COI_COPY_TYPE, uint32_t, const COIEVENT*,
344                        COIEVENT*))
345             DL_sym(lib_handle, "COIBufferWrite", COI_VERSION1);
346     if (BufferWrite == 0) {
347         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
348                             "COIBufferWrite");
349         fini();
350         return false;
351     }
352 
353     BufferRead =
354         (COIRESULT (*)(COIBUFFER, uint64_t, void*, uint64_t,
355                                      COI_COPY_TYPE, uint32_t,
356                                      const COIEVENT*, COIEVENT*))
357             DL_sym(lib_handle, "COIBufferRead", COI_VERSION1);
358     if (BufferRead == 0) {
359         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
360                             "COIBufferRead");
361         fini();
362         return false;
363     }
364 
365     BufferReadMultiD =
366         (COIRESULT (*)(COIBUFFER, uint64_t,
367                        void *, void *, COI_COPY_TYPE,
368                        uint32_t, const   COIEVENT*, COIEVENT*))
369             DL_sym(lib_handle, "COIBufferReadMultiD", COI_VERSION1);
370     // We  accept that coi library has no COIBufferReadMultiD routine.
371     // So there is no check for zero value
372 
373     BufferWriteMultiD =
374         (COIRESULT (*)(COIBUFFER, const   COIPROCESS,
375                        uint64_t, void *, void *,
376                        COI_COPY_TYPE, uint32_t, const   COIEVENT*, COIEVENT*))
377             DL_sym(lib_handle, "COIBufferWriteMultiD", COI_VERSION1);
378     // We  accept that coi library has no COIBufferWriteMultiD routine.
379     // So there is no check for zero value
380 
381     BufferCopy =
382         (COIRESULT (*)(COIBUFFER, COIBUFFER, uint64_t, uint64_t, uint64_t,
383                        COI_COPY_TYPE, uint32_t, const COIEVENT*,
384                        COIEVENT*))
385             DL_sym(lib_handle, "COIBufferCopy", COI_VERSION1);
386     if (BufferCopy == 0) {
387         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
388                             "COIBufferCopy");
389         fini();
390         return false;
391     }
392 
393     BufferGetSinkAddress =
394         (COIRESULT (*)(COIBUFFER, uint64_t*))
395             DL_sym(lib_handle, "COIBufferGetSinkAddress", COI_VERSION1);
396     if (BufferGetSinkAddress == 0) {
397         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
398                             "COIBufferGetSinkAddress");
399         fini();
400         return false;
401     }
402 
403     BufferSetState =
404         (COIRESULT(*)(COIBUFFER, COIPROCESS, COI_BUFFER_STATE,
405                       COI_BUFFER_MOVE_FLAG, uint32_t, const COIEVENT*,
406                       COIEVENT*))
407             DL_sym(lib_handle, "COIBufferSetState", COI_VERSION1);
408     if (BufferSetState == 0) {
409         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
410                             "COIBufferSetState");
411         fini();
412         return false;
413     }
414 
415     EventWait =
416         (COIRESULT (*)(uint16_t, const COIEVENT*, int32_t, uint8_t,
417                        uint32_t*, uint32_t*))
418             DL_sym(lib_handle, "COIEventWait", COI_VERSION1);
419     if (EventWait == 0) {
420         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
421                             "COIEventWait");
422         fini();
423         return false;
424     }
425 
426     PerfGetCycleFrequency =
427         (uint64_t (*)(void))
428             DL_sym(lib_handle, "COIPerfGetCycleFrequency", COI_VERSION1);
429     if (PerfGetCycleFrequency == 0) {
430         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
431                             "COIPerfGetCycleFrequency");
432         fini();
433         return false;
434     }
435 
436     PipelineClearCPUMask =
437         (COIRESULT (*)(COI_CPU_MASK))
438             DL_sym(lib_handle, "COIPipelineClearCPUMask", COI_VERSION1);
439     if (PipelineClearCPUMask == 0) {
440         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
441                             "COIPipelineClearCPUMask");
442         fini();
443         return false;
444     }
445 
446     PipelineSetCPUMask =
447         (COIRESULT (*)(COIPROCESS, uint32_t,uint8_t, COI_CPU_MASK))
448             DL_sym(lib_handle, "COIPipelineSetCPUMask", COI_VERSION1);
449     if (PipelineSetCPUMask == 0) {
450         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
451                             "COIPipelineSetCPUMask");
452         fini();
453         return false;
454     }
455 
456     EngineGetInfo =
457         (COIRESULT (*)(COIENGINE, uint32_t, COI_ENGINE_INFO*))
458             DL_sym(lib_handle, "COIEngineGetInfo", COI_VERSION1);
459     if (EngineGetInfo == 0) {
460         OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in COI library\n",
461                             "COIEngineGetInfo");
462         fini();
463         return false;
464     }
465 
466     EventRegisterCallback =
467         (COIRESULT (*)(COIEVENT,
468          void (*)(COIEVENT, const COIRESULT, const void*),
469          const void*,
470          const uint64_t))
471             DL_sym(lib_handle, "COIEventRegisterCallback", COI_VERSION1);
472 
473     ProcessConfigureDMA =
474         (COIRESULT (*)(const uint64_t, const int))
475             DL_sym(lib_handle, "COIProcessConfigureDMA", COI_VERSION1);
476 
477     is_available = true;
478 
479     return true;
480 }
481 
fini(void)482 void fini(void)
483 {
484     is_available = false;
485 
486     if (lib_handle != 0) {
487 #ifndef TARGET_WINNT
488         DL_close(lib_handle);
489 #endif // TARGET_WINNT
490         lib_handle = 0;
491     }
492 }
493 
494 } // namespace COI
495