direct-io.hg

view tools/libxc/xc_linux.c @ 11672:7e79259c2c17

[LINUX] Make evtchn device use a dynamic minor number.

Also update the code in tools to create the device node if udev fails.
The tools now read the sysfs system to find the minor number needed.

Original patch from Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Sep 29 14:20:52 2006 +0100 (2006-09-29)
parents 59adc1f7dfca
children f7b7daed94d6
line source
1 /******************************************************************************
2 *
3 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2 of the
9 * License.
10 */
12 #include "xc_private.h"
14 #include <xen/memory.h>
15 #include <xen/sys/evtchn.h>
16 #include <unistd.h>
17 #include <fcntl.h>
19 int xc_interface_open(void)
20 {
21 int flags, saved_errno;
22 int fd = open("/proc/xen/privcmd", O_RDWR);
24 if ( fd == -1 )
25 {
26 PERROR("Could not obtain handle on privileged command interface");
27 return -1;
28 }
30 /* Although we return the file handle as the 'xc handle' the API
31 does not specify / guarentee that this integer is in fact
32 a file handle. Thus we must take responsiblity to ensure
33 it doesn't propagate (ie leak) outside the process */
34 if ( (flags = fcntl(fd, F_GETFD)) < 0 )
35 {
36 PERROR("Could not get file handle flags");
37 goto error;
38 }
39 flags |= FD_CLOEXEC;
40 if ( fcntl(fd, F_SETFD, flags) < 0 )
41 {
42 PERROR("Could not set file handle flags");
43 goto error;
44 }
46 return fd;
48 error:
49 saved_errno = errno;
50 close(fd);
51 errno = saved_errno;
52 return -1;
53 }
55 int xc_interface_close(int xc_handle)
56 {
57 return close(xc_handle);
58 }
60 void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
61 xen_pfn_t *arr, int num)
62 {
63 privcmd_mmapbatch_t ioctlx;
64 void *addr;
65 addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
66 if ( addr == MAP_FAILED )
67 return NULL;
69 ioctlx.num=num;
70 ioctlx.dom=dom;
71 ioctlx.addr=(unsigned long)addr;
72 ioctlx.arr=arr;
73 if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
74 {
75 int saved_errno = errno;
76 perror("XXXXXXXX");
77 (void)munmap(addr, num*PAGE_SIZE);
78 errno = saved_errno;
79 return NULL;
80 }
81 return addr;
83 }
85 void *xc_map_foreign_range(int xc_handle, uint32_t dom,
86 int size, int prot,
87 unsigned long mfn)
88 {
89 privcmd_mmap_t ioctlx;
90 privcmd_mmap_entry_t entry;
91 void *addr;
92 addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
93 if ( addr == MAP_FAILED )
94 return NULL;
96 ioctlx.num=1;
97 ioctlx.dom=dom;
98 ioctlx.entry=&entry;
99 entry.va=(unsigned long) addr;
100 entry.mfn=mfn;
101 entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
102 if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0 )
103 {
104 int saved_errno = errno;
105 (void)munmap(addr, size);
106 errno = saved_errno;
107 return NULL;
108 }
109 return addr;
110 }
112 int xc_map_foreign_ranges(int xc_handle, uint32_t dom,
113 privcmd_mmap_entry_t *entries, int nr)
114 {
115 privcmd_mmap_t ioctlx;
117 ioctlx.num = nr;
118 ioctlx.dom = dom;
119 ioctlx.entry = entries;
121 return ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx);
122 }
124 static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data)
125 {
126 return ioctl(xc_handle, cmd, data);
127 }
129 int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
130 {
131 return do_privcmd(xc_handle,
132 IOCTL_PRIVCMD_HYPERCALL,
133 (unsigned long)hypercall);
134 }
136 #define MTAB "/proc/mounts"
137 #define MAX_PATH 255
138 #define _STR(x) #x
139 #define STR(x) _STR(x)
141 static int find_sysfsdir(char *sysfsdir)
142 {
143 FILE *fp;
144 char type[MAX_PATH + 1];
146 if ( (fp = fopen(MTAB, "r")) == NULL )
147 return -1;
149 while ( fscanf(fp, "%*s %"
150 STR(MAX_PATH)
151 "s %"
152 STR(MAX_PATH)
153 "s %*s %*d %*d\n",
154 sysfsdir, type) == 2 )
155 {
156 if ( strncmp(type, "sysfs", 5) == 0 )
157 break;
158 }
160 fclose(fp);
162 return ((strncmp(type, "sysfs", 5) == 0) ? 0 : -1);
163 }
165 int xc_find_device_number(const char *name)
166 {
167 FILE *fp;
168 int i, major, minor;
169 char sysfsdir[MAX_PATH + 1];
170 static char *classlist[] = { "xen", "misc" };
172 for ( i = 0; i < (sizeof(classlist) / sizeof(classlist[0])); i++ )
173 {
174 if ( find_sysfsdir(sysfsdir) < 0 )
175 goto not_found;
177 /* <base>/class/<classname>/<devname>/dev */
178 strncat(sysfsdir, "/class/", MAX_PATH);
179 strncat(sysfsdir, classlist[i], MAX_PATH);
180 strncat(sysfsdir, "/", MAX_PATH);
181 strncat(sysfsdir, name, MAX_PATH);
182 strncat(sysfsdir, "/dev", MAX_PATH);
184 if ( (fp = fopen(sysfsdir, "r")) != NULL )
185 goto found;
186 }
188 not_found:
189 errno = -ENOENT;
190 return -1;
192 found:
193 if ( fscanf(fp, "%d:%d", &major, &minor) != 2 )
194 {
195 fclose(fp);
196 goto not_found;
197 }
199 fclose(fp);
201 return makedev(major, minor);
202 }
204 #define EVTCHN_DEV_NAME "/dev/xen/evtchn"
206 int xc_evtchn_open(void)
207 {
208 struct stat st;
209 int fd;
210 int devnum;
212 devnum = xc_find_device_number("evtchn");
214 /* Make sure any existing device file links to correct device. */
215 if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
216 (st.st_rdev != devnum) )
217 (void)unlink(EVTCHN_DEV_NAME);
219 reopen:
220 if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 )
221 {
222 if ( (errno == ENOENT) &&
223 ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
224 (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, devnum) == 0) )
225 goto reopen;
227 PERROR("Could not open event channel interface");
228 return -1;
229 }
231 return fd;
232 }
234 int xc_evtchn_close(int xce_handle)
235 {
236 return close(xce_handle);
237 }
239 int xc_evtchn_fd(int xce_handle)
240 {
241 return xce_handle;
242 }
244 int xc_evtchn_notify(int xce_handle, evtchn_port_t port)
245 {
246 struct ioctl_evtchn_notify notify;
248 notify.port = port;
250 return ioctl(xce_handle, IOCTL_EVTCHN_NOTIFY, &notify);
251 }
253 evtchn_port_t xc_evtchn_bind_interdomain(int xce_handle, int domid,
254 evtchn_port_t remote_port)
255 {
256 struct ioctl_evtchn_bind_interdomain bind;
258 bind.remote_domain = domid;
259 bind.remote_port = remote_port;
261 return ioctl(xce_handle, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
262 }
264 int xc_evtchn_unbind(int xce_handle, evtchn_port_t port)
265 {
266 struct ioctl_evtchn_unbind unbind;
268 unbind.port = port;
270 return ioctl(xce_handle, IOCTL_EVTCHN_UNBIND, &unbind);
271 }
273 evtchn_port_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq)
274 {
275 struct ioctl_evtchn_bind_virq bind;
277 bind.virq = virq;
279 return ioctl(xce_handle, IOCTL_EVTCHN_BIND_VIRQ, &bind);
280 }
282 static int dorw(int fd, char *data, size_t size, int do_write)
283 {
284 size_t offset = 0;
285 ssize_t len;
287 while ( offset < size )
288 {
289 if (do_write)
290 len = write(fd, data + offset, size - offset);
291 else
292 len = read(fd, data + offset, size - offset);
294 if ( len == -1 )
295 {
296 if ( errno == EINTR )
297 continue;
298 return -1;
299 }
301 offset += len;
302 }
304 return 0;
305 }
307 evtchn_port_t xc_evtchn_pending(int xce_handle)
308 {
309 evtchn_port_t port;
311 if ( dorw(xce_handle, (char *)&port, sizeof(port), 0) == -1 )
312 return -1;
314 return port;
315 }
317 int xc_evtchn_unmask(int xce_handle, evtchn_port_t port)
318 {
319 return dorw(xce_handle, (char *)&port, sizeof(port), 1);
320 }
322 /*
323 * Local variables:
324 * mode: C
325 * c-set-style: "BSD"
326 * c-basic-offset: 4
327 * tab-width: 4
328 * indent-tabs-mode: nil
329 * End:
330 */