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#if defined(LINUX) || defined(FREEBSD)
32#include <mm_malloc.h>
33#endif
34
35#include "offload_common.h"
36
37// The debug routines
38
39#if OFFLOAD_DEBUG > 0
40
41void __dump_bytes(
42    int trace_level,
43    const void *data,
44    int len
45)
46{
47    if (console_enabled > trace_level) {
48        const uint8_t *arr = (const uint8_t*) data;
49        char buffer[4096];
50        char *bufferp;
51        int count = 0;
52
53        bufferp = buffer;
54        while (len--) {
55            sprintf(bufferp, "%02x", *arr++);
56            bufferp += 2;
57            count++;
58            if ((count&3) == 0) {
59                sprintf(bufferp, " ");
60                bufferp++;
61            }
62            if ((count&63) == 0) {
63                OFFLOAD_DEBUG_TRACE(trace_level, "%s\n", buffer);
64                bufferp = buffer;
65                count = 0;
66            }
67        }
68        if (count) {
69            OFFLOAD_DEBUG_TRACE(trace_level, "%s\n", buffer);
70        }
71    }
72}
73#endif // OFFLOAD_DEBUG
74
75// The Marshaller and associated routines
76
77void Marshaller::send_data(
78    const void *data,
79    int64_t length
80)
81{
82    OFFLOAD_DEBUG_TRACE(2, "send_data(%p, %lld)\n",
83                        data, length);
84    memcpy(buffer_ptr, data, (size_t)length);
85    buffer_ptr += length;
86    tfr_size += length;
87}
88
89void Marshaller::receive_data(
90    void *data,
91    int64_t length
92)
93{
94    OFFLOAD_DEBUG_TRACE(2, "receive_data(%p, %lld)\n",
95                        data, length);
96    memcpy(data, buffer_ptr, (size_t)length);
97    buffer_ptr += length;
98    tfr_size += length;
99}
100
101// Send function pointer
102void Marshaller::send_func_ptr(
103    const void* data
104)
105{
106    const char* name;
107    size_t      length;
108
109    if (data != 0) {
110        name = __offload_funcs.find_name(data);
111        if (name == 0) {
112#if OFFLOAD_DEBUG > 0
113            if (console_enabled > 2) {
114                __offload_funcs.dump();
115            }
116#endif // OFFLOAD_DEBUG > 0
117
118            LIBOFFLOAD_ERROR(c_send_func_ptr, data);
119            exit(1);
120        }
121        length = strlen(name) + 1;
122    }
123    else {
124        name = "";
125        length = 1;
126    }
127
128    memcpy(buffer_ptr, name, length);
129    buffer_ptr += length;
130    tfr_size += length;
131}
132
133// Receive function pointer
134void Marshaller::receive_func_ptr(
135    const void** data
136)
137{
138    const char* name;
139    size_t      length;
140
141    name = (const char*) buffer_ptr;
142    if (name[0] != '\0') {
143        *data = __offload_funcs.find_addr(name);
144        if (*data == 0) {
145#if OFFLOAD_DEBUG > 0
146            if (console_enabled > 2) {
147                __offload_funcs.dump();
148            }
149#endif // OFFLOAD_DEBUG > 0
150
151            LIBOFFLOAD_ERROR(c_receive_func_ptr, name);
152            exit(1);
153        }
154        length = strlen(name) + 1;
155    }
156    else {
157        *data = 0;
158        length = 1;
159    }
160
161    buffer_ptr += length;
162    tfr_size += length;
163}
164
165// End of the Marshaller and associated routines
166
167extern void *OFFLOAD_MALLOC(
168    size_t size,
169    size_t align
170)
171{
172    void *ptr;
173    int   err;
174
175    OFFLOAD_DEBUG_TRACE(2, "%s(%lld, %lld)\n", __func__, size, align);
176
177    if (align < sizeof(void*)) {
178        align = sizeof(void*);
179    }
180
181    ptr = _mm_malloc(size, align);
182    if (ptr == NULL) {
183        LIBOFFLOAD_ERROR(c_offload_malloc, size, align);
184        exit(1);
185    }
186
187    OFFLOAD_DEBUG_TRACE(2, "%s returned %p\n", __func__, ptr);
188
189    return ptr;
190}
191