1 /******************************************************************************
2 *
3 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation;
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Split from xc_freebsd_osdep.c
20 */
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <sys/mman.h>
30 #include <sys/ioctl.h>
31
32 #include "private.h"
33
34 #define PRIVCMD_DEV "/dev/xen/privcmd"
35
osdep_xencall_open(xencall_handle * xcall)36 int osdep_xencall_open(xencall_handle *xcall)
37 {
38 int fd = open(PRIVCMD_DEV, O_RDWR|O_CLOEXEC);
39
40 /*
41 * This file descriptor is opaque to the caller, thus we are
42 * polite and try and ensure it doesn't propagate (ie leak)
43 * outside the process, by using O_CLOEXEC.
44 */
45
46 if ( fd == -1 )
47 {
48 PERROR("Could not obtain handle on privileged command interface "
49 PRIVCMD_DEV);
50 return -1;
51 }
52
53 xcall->fd = fd;
54 return 0;
55 }
56
osdep_xencall_close(xencall_handle * xcall)57 int osdep_xencall_close(xencall_handle *xcall)
58 {
59 int fd = xcall->fd;
60 if ( fd == -1 )
61 return 0;
62 return close(fd);
63 }
64
osdep_hypercall(xencall_handle * xcall,privcmd_hypercall_t * hypercall)65 int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
66 {
67 int fd = xcall->fd;
68 int ret;
69
70 ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
71
72 return (ret == 0) ? hypercall->retval : ret;
73 }
74
osdep_alloc_pages(xencall_handle * xcall,size_t npages)75 void *osdep_alloc_pages(xencall_handle *xcall, size_t npages)
76 {
77 size_t size = npages * PAGE_SIZE;
78 void *p;
79
80 /* Address returned by mmap is page aligned. */
81 p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
82 -1, 0);
83 if (p == NULL)
84 return NULL;
85
86 /*
87 * Since FreeBSD doesn't have the MAP_LOCKED flag,
88 * lock memory using mlock.
89 */
90 if ( mlock(p, size) < 0 )
91 {
92 munmap(p, size);
93 return NULL;
94 }
95
96 return p;
97 }
98
osdep_free_pages(xencall_handle * xcall,void * ptr,size_t npages)99 void osdep_free_pages(xencall_handle *xcall, void *ptr, size_t npages)
100 {
101 int saved_errno = errno;
102 /* Unlock pages */
103 munlock(ptr, npages * PAGE_SIZE);
104
105 munmap(ptr, npages * PAGE_SIZE);
106 /* We MUST propagate the hypercall errno, not unmap call's. */
107 errno = saved_errno;
108 }
109
xencall_buffers_never_fault(xencall_handle * xcall)110 int xencall_buffers_never_fault(xencall_handle *xcall)
111 {
112 return 1;
113 }
114
115 /*
116 * Local variables:
117 * mode: C
118 * c-file-style: "BSD"
119 * c-basic-offset: 4
120 * tab-width: 4
121 * indent-tabs-mode: nil
122 * End:
123 */
124