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_netbsd.c
20  */
21 
22 
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <malloc.h>
26 #include <errno.h>
27 #include <sys/mman.h>
28 #include <sys/ioctl.h>
29 
30 #include "private.h"
31 
osdep_xencall_open(xencall_handle * xcall)32 int osdep_xencall_open(xencall_handle *xcall)
33 {
34     int flags, saved_errno;
35     int fd = open("/kern/xen/privcmd", O_RDWR);
36 
37     if ( fd == -1 )
38     {
39         PERROR("Could not obtain handle on privileged command interface");
40         return -1;
41     }
42 
43     /* Although we return the file handle as the 'xc handle' the API
44        does not specify / guarentee that this integer is in fact
45        a file handle. Thus we must take responsiblity to ensure
46        it doesn't propagate (ie leak) outside the process */
47     if ( (flags = fcntl(fd, F_GETFD)) < 0 )
48     {
49         PERROR("Could not get file handle flags");
50         goto error;
51     }
52     flags |= FD_CLOEXEC;
53     if ( fcntl(fd, F_SETFD, flags) < 0 )
54     {
55         PERROR("Could not set file handle flags");
56         goto error;
57     }
58 
59     xcall->fd = fd;
60     return 0;
61 
62  error:
63     saved_errno = errno;
64     close(fd);
65     errno = saved_errno;
66     return -1;
67 }
68 
osdep_xencall_close(xencall_handle * xcall)69 int osdep_xencall_close(xencall_handle *xcall)
70 {
71     int fd = xcall->fd;
72     return close(fd);
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     int ret;
80 
81     ret = posix_memalign(&p, PAGE_SIZE, size);
82     if ( ret != 0 || !p )
83         return NULL;
84 
85     if ( mlock(p, size) < 0 )
86     {
87         free(p);
88         return NULL;
89     }
90     return p;
91 }
92 
osdep_free_pages(xencall_handle * xcall,void * ptr,size_t npages)93 void osdep_free_pages(xencall_handle *xcall, void *ptr, size_t npages)
94 {
95     munlock(ptr, npages * PAGE_SIZE);
96     free(ptr);
97 }
98 
osdep_hypercall(xencall_handle * xcall,privcmd_hypercall_t * hypercall)99 long osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
100 {
101     int fd = xcall->fd;
102     int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
103 
104     /*
105      * Since NetBSD ioctl can only return 0 on success or < 0 on
106      * error, if we want to return a value from ioctl we should
107      * do so by setting hypercall->retval, to mimic Linux ioctl
108      * implementation.
109      */
110     if (error < 0)
111         return error;
112     else
113         return hypercall->retval;
114 }
115 
xencall_buffers_never_fault(xencall_handle * xcall)116 int xencall_buffers_never_fault(xencall_handle *xcall)
117 {
118     return 1;
119 }
120 
121 /*
122  * Local variables:
123  * mode: C
124  * c-file-style: "BSD"
125  * c-basic-offset: 4
126  * tab-width: 4
127  * indent-tabs-mode: nil
128  * End:
129  */
130