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