1/*
2 * rump_dev_xen.c
3 *
4 * Machinery for setting up the contents of /dev/xen* in a rumpkernel.
5 *
6 * Copyright (c) 2014 Citrix
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this source file (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use, copy, modify,
11 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: $");
29
30#include "rumpxen_xendev.h"
31
32#include "rump_private.h"
33#include "rump_vfs_private.h"
34
35#include <sys/vfs_syscalls.h>
36#include <sys/dirent.h>
37#include <miscfs/kernfs/kernfs.h>
38
39char *xbd_strdup(const char *s)
40{
41	char *r;
42	size_t l = strlen(s) + 1;
43	r = xbd_malloc(l);
44	if (!r)
45		return r;
46	memcpy(r, s, l);
47	return r;
48}
49
50#define DEV_XEN "/dev/xen"
51
52static const struct xen_dev_info {
53	const char *path;
54	void (*xd_init)(void);
55	int (*xd_open)(struct file *fp, void **fdata_r);
56	const struct fileops *fo;
57} devs[] = {
58#define XDEV(cmin, path, init_fn, component)					\
59	[cmin] = { path, init_fn, component##_dev_open,	\
60		   &component##_dev_fileops }
61	XDEV(0, DEV_XEN "/xenbus", NULL, xenbus),
62//	XDEV(1, "/dev/xenevt", xenevt_dev_init, xenevt),  XXX issue #73
63#undef XDEV
64};
65
66#define NUM_DEV_INFOS (sizeof(devs)/sizeof(devs[0]))
67
68static int
69xen_dev_open(dev_t dev, int flags, int mode, struct lwp *l)
70{
71	const struct xen_dev_info *xdinfo;
72	int fd, err;
73	struct file *fp;
74	void *fdata;
75
76	DPRINTF(("xen devsw: opening minor=%lu\n", (unsigned long)minor(dev)));
77
78        if (minor(dev) < 0 || minor(dev) >= NUM_DEV_INFOS)
79		return ENODEV;
80
81	xdinfo = &devs[minor(dev)];
82
83	if (!xdinfo->xd_open)
84		return ENODEV;
85
86	err = fd_allocfile(&fp, &fd);
87	if (err)
88		return err;
89
90	DPRINTF(("%s: opening...\n", xdinfo->path));
91
92	err = xdinfo->xd_open(fp, &fdata);
93	if (err) {
94		fd_abort(curproc, fp, fd);
95		return err;
96	}
97
98	DPRINTF(("%s: opened, fd_clone\n", xdinfo->path));
99
100	return fd_clone(fp, fd, flags, xdinfo->fo, fdata);
101}
102
103static const struct cdevsw xen_dev_cdevsw = {
104	.d_open = xen_dev_open,
105	.d_close = nullclose,
106	.d_read = noread,
107	.d_write = nowrite,
108	.d_ioctl = noioctl,
109	.d_stop = nostop,
110	.d_tty = notty,
111	.d_poll = nopoll,
112	.d_mmap = nommap,
113	.d_kqfilter = nokqfilter,
114	.d_flag = D_OTHER
115};
116
117#define DIR_MODE        (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
118kernfs_parentdir_t *kernxen_pkt;
119static void xenkernfs_init(void)
120{
121	kernfs_entry_t *dkt;
122	KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
123	KERNFS_INITENTRY(dkt, DT_DIR, "xen", NULL, KFSsubdir, VDIR, DIR_MODE);
124	kernfs_addentry(NULL, dkt);
125	kernxen_pkt = KERNFS_ENTOPARENTDIR(dkt);
126}
127
128RUMP_COMPONENT(RUMP_COMPONENT_DEV)
129{
130        devmajor_t bmaj, cmaj;
131	devminor_t cmin;
132        int err;
133	const struct xen_dev_info *xdinfo;
134
135	DPRINTF(("xen devsw: attaching\n"));
136
137	err = do_sys_mkdir(DEV_XEN, 0755, UIO_SYSSPACE);
138	if (err && err != EEXIST)
139		panic("xen devsw: mkdir " DEV_XEN " failed: %d", err);
140
141        bmaj = cmaj = NODEVMAJOR;
142        err = devsw_attach("xen", NULL, &bmaj, &xen_dev_cdevsw, &cmaj);
143	if (err)
144                panic("xen devsw: attach failed: %d", err);
145
146	for (cmin = 0; cmin < NUM_DEV_INFOS; cmin++) {
147	     xdinfo = &devs[cmin];
148	     err = rump_vfs_makeonedevnode(S_IFCHR, xdinfo->path, cmaj, cmin);
149	     if (err)
150		     panic("%s: cannot create device node: %d",
151			   xdinfo->path, err);
152	     if (xdinfo->xd_init)
153		     xdinfo->xd_init();
154	     DPRINTF(("%s: created, %lu.%lu\n",
155		      xdinfo->path, (unsigned long)cmaj, (unsigned long)cmin));
156	}
157
158	xenkernfs_init();
159//	xenprivcmd_init();  XXX issue #73
160}
161
162/*
163 * Local variables:
164 *  c-file-style: "linux"
165 *  indent-tabs-mode: t
166 *  c-indent-level: 8
167 *  c-basic-offset: 8
168 *  tab-width: 8
169 * End:
170 */
171
172