1 /*
2 * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
3 * Copyright (c) 2016-2017, Akshay Jaggi <jaggi@FreeBSD.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Split out from linux.c
19 */
20
21 #include <fcntl.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <string.h>
27
28 #include <sys/ioctl.h>
29 #include <sys/mman.h>
30
31 #include <xenctrl.h>
32 #include <xen/xen.h>
33 #include <xen/xenio.h>
34
35 #include "private.h"
36
37 #define DEVXEN "/kern/xen/privcmd"
38
osdep_gnttab_open(xengnttab_handle * xgt)39 int osdep_gnttab_open(xengnttab_handle *xgt)
40 {
41 int fd = open(DEVXEN, O_RDWR | O_CLOEXEC);
42
43 if ( fd == -1 )
44 return -1;
45 xgt->fd = fd;
46
47 return 0;
48 }
49
osdep_gnttab_close(xengnttab_handle * xgt)50 int osdep_gnttab_close(xengnttab_handle *xgt)
51 {
52 if ( xgt->fd == -1 )
53 return 0;
54
55 return close(xgt->fd);
56 }
57
osdep_gnttab_set_max_grants(xengnttab_handle * xgt,uint32_t count)58 int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
59 {
60 return 0;
61 }
62
osdep_gnttab_grant_map(xengnttab_handle * xgt,uint32_t count,int flags,int prot,uint32_t * domids,uint32_t * refs,uint32_t notify_offset,evtchn_port_t notify_port)63 void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
64 uint32_t count, int flags, int prot,
65 uint32_t *domids, uint32_t *refs,
66 uint32_t notify_offset,
67 evtchn_port_t notify_port)
68 {
69 uint32_t i;
70 int fd = xgt->fd;
71 struct ioctl_gntdev_mmap_grant_ref map;
72 void *addr = NULL;
73 int domids_stride;
74 unsigned int refs_size = count * sizeof(struct ioctl_gntdev_grant_ref);
75 int rv;
76
77 domids_stride = !!(flags & XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN);
78 map.refs = malloc(refs_size);
79
80 for ( i = 0; i < count; i++ )
81 {
82 map.refs[i].domid = domids[i * domids_stride];
83 map.refs[i].ref = refs[i];
84 }
85
86 map.count = count;
87 addr = mmap(NULL, count * XC_PAGE_SIZE,
88 prot, flags | MAP_ANON | MAP_SHARED, -1, 0);
89 if ( map.va == MAP_FAILED )
90 {
91 GTERROR(xgt->logger, "osdep_gnttab_grant_map: mmap failed");
92 munmap((void *)map.va, count * XC_PAGE_SIZE);
93 addr = MAP_FAILED;
94 }
95 map.va = addr;
96
97 map.notify.offset = 0;
98 map.notify.action = 0;
99 if ( notify_offset < XC_PAGE_SIZE * count )
100 {
101 map.notify.offset = notify_offset;
102 map.notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
103 }
104 if ( notify_port != -1 )
105 {
106 map.notify.event_channel_port = notify_port;
107 map.notify.action |= UNMAP_NOTIFY_SEND_EVENT;
108 }
109
110 rv = ioctl(fd, IOCTL_GNTDEV_MMAP_GRANT_REF, &map);
111 if ( rv )
112 {
113 GTERROR(xgt->logger,
114 "ioctl IOCTL_GNTDEV_MMAP_GRANT_REF failed: %d", rv);
115 munmap(addr, count * XC_PAGE_SIZE);
116 addr = MAP_FAILED;
117 }
118
119 free(map.refs);
120
121 return addr;
122 }
123
osdep_gnttab_unmap(xengnttab_handle * xgt,void * start_address,uint32_t count)124 int osdep_gnttab_unmap(xengnttab_handle *xgt,
125 void *start_address,
126 uint32_t count)
127 {
128 int rc;
129 if ( start_address == NULL )
130 {
131 errno = EINVAL;
132 return -1;
133 }
134
135 /* Next, unmap the memory. */
136 rc = munmap(start_address, count * XC_PAGE_SIZE);
137
138 return rc;
139 }
140
osdep_gnttab_grant_copy(xengnttab_handle * xgt,uint32_t count,xengnttab_grant_copy_segment_t * segs)141 int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
142 uint32_t count,
143 xengnttab_grant_copy_segment_t *segs)
144 {
145 errno = ENOSYS;
146 return -1;
147 }
148
osdep_gntshr_open(xengntshr_handle * xgs)149 int osdep_gntshr_open(xengntshr_handle *xgs)
150 {
151
152 int fd = open(DEVXEN, O_RDWR);
153
154 if ( fd == -1 )
155 return -1;
156
157 xgs->fd = fd;
158 return 0;
159 }
160
osdep_gntshr_close(xengntshr_handle * xgs)161 int osdep_gntshr_close(xengntshr_handle *xgs)
162 {
163 if ( xgs->fd == -1 )
164 return 0;
165
166 return close(xgs->fd);
167 }
168
osdep_gntshr_share_pages(xengntshr_handle * xgs,uint32_t domid,int count,uint32_t * refs,int writable,uint32_t notify_offset,evtchn_port_t notify_port)169 void *osdep_gntshr_share_pages(xengntshr_handle *xgs,
170 uint32_t domid, int count,
171 uint32_t *refs, int writable,
172 uint32_t notify_offset,
173 evtchn_port_t notify_port)
174 {
175 int err;
176 int fd = xgs->fd;
177 void *area = NULL;
178 struct ioctl_gntdev_alloc_grant_ref alloc;
179
180 alloc.gref_ids = malloc(count * sizeof(uint32_t));
181 if ( alloc.gref_ids == NULL )
182 return NULL;
183
184 alloc.domid = domid;
185 alloc.flags = writable ? GNTDEV_ALLOC_FLAG_WRITABLE : 0;
186 alloc.count = count;
187 area = mmap(NULL, count * XC_PAGE_SIZE,
188 PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
189
190 if ( area == MAP_FAILED )
191 {
192 GTERROR(xgs->logger, "osdep_gnttab_grant_map: mmap failed");
193 area = MAP_FAILED;
194 goto out;
195 }
196 alloc.va = area;
197
198 alloc.notify.offset = 0;
199 alloc.notify.action = 0;
200 if ( notify_offset < XC_PAGE_SIZE * count )
201 {
202 alloc.notify.offset = notify_offset;
203 alloc.notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
204 }
205 if ( notify_port != -1 )
206 {
207 alloc.notify.event_channel_port = notify_port;
208 alloc.notify.action |= UNMAP_NOTIFY_SEND_EVENT;
209 }
210
211 err = ioctl(fd, IOCTL_GNTDEV_ALLOC_GRANT_REF, &alloc);
212 if ( err )
213 {
214 GSERROR(xgs->logger, "IOCTL_GNTDEV_ALLOC_GRANT_REF failed");
215 munmap(area, count * XC_PAGE_SIZE);
216 area = MAP_FAILED;
217 goto out;
218 }
219
220 memcpy(refs, alloc.gref_ids, count * sizeof(uint32_t));
221
222 out:
223 free(alloc.gref_ids);
224 return area;
225 }
226
osdep_gntshr_unshare(xengntshr_handle * xgs,void * start_address,uint32_t count)227 int osdep_gntshr_unshare(xengntshr_handle *xgs,
228 void *start_address, uint32_t count)
229 {
230 return munmap(start_address, count * XC_PAGE_SIZE);
231 }
232
233 /*
234 * The functions below are Linux-isms that will likely never be implemented
235 * on NetBSD unless NetBSD also implements something akin to Linux dmabuf.
236 */
osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle * xgt,uint32_t domid,uint32_t flags,uint32_t count,const uint32_t * refs,uint32_t * dmabuf_fd)237 int osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
238 uint32_t flags, uint32_t count,
239 const uint32_t *refs,
240 uint32_t *dmabuf_fd)
241 {
242 abort();
243 }
244
osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle * xgt,uint32_t fd,uint32_t wait_to_ms)245 int osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt,
246 uint32_t fd, uint32_t wait_to_ms)
247 {
248 abort();
249 }
250
osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle * xgt,uint32_t domid,uint32_t fd,uint32_t count,uint32_t * refs)251 int osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
252 uint32_t fd, uint32_t count, uint32_t *refs)
253 {
254 abort();
255 }
256
osdep_gnttab_dmabuf_imp_release(xengnttab_handle * xgt,uint32_t fd)257 int osdep_gnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
258 {
259 abort();
260 }
261
262 /*
263 * Local variables:
264 * mode: C
265 * c-file-style: "BSD"
266 * c-basic-offset: 4
267 * tab-width: 4
268 * indent-tabs-mode: nil
269 * End:
270 */
271