1*6bb51422Spooka /* $NetBSD: puffs_rumpglue.c,v 1.16 2016/01/26 23:12:17 pooka Exp $ */
24f69d01dSpooka
34f69d01dSpooka /*
44f69d01dSpooka * Copyright (c) 2008 Antti Kantee. All Rights Reserved.
54f69d01dSpooka *
64f69d01dSpooka * Development of this software was supported by the
74f69d01dSpooka * Research Foundation of Helsinki University of Technology
84f69d01dSpooka *
94f69d01dSpooka * Redistribution and use in source and binary forms, with or without
104f69d01dSpooka * modification, are permitted provided that the following conditions
114f69d01dSpooka * are met:
124f69d01dSpooka * 1. Redistributions of source code must retain the above copyright
134f69d01dSpooka * notice, this list of conditions and the following disclaimer.
144f69d01dSpooka * 2. Redistributions in binary form must reproduce the above copyright
154f69d01dSpooka * notice, this list of conditions and the following disclaimer in the
164f69d01dSpooka * documentation and/or other materials provided with the distribution.
174f69d01dSpooka *
184f69d01dSpooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
194f69d01dSpooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
204f69d01dSpooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
214f69d01dSpooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
224f69d01dSpooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
234f69d01dSpooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
244f69d01dSpooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
254f69d01dSpooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
264f69d01dSpooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
274f69d01dSpooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
284f69d01dSpooka * SUCH DAMAGE.
294f69d01dSpooka */
304f69d01dSpooka
314f69d01dSpooka #include <sys/cdefs.h>
32*6bb51422Spooka __KERNEL_RCSID(0, "$NetBSD: puffs_rumpglue.c,v 1.16 2016/01/26 23:12:17 pooka Exp $");
334f69d01dSpooka
344f69d01dSpooka #include <sys/param.h>
354f69d01dSpooka #include <sys/conf.h>
364f69d01dSpooka #include <sys/file.h>
374f69d01dSpooka #include <sys/filedesc.h>
384f69d01dSpooka #include <sys/kthread.h>
394f69d01dSpooka #include <sys/mount.h>
404f69d01dSpooka
414b9a5d92Spooka #include <dev/putter/putter.h>
424f69d01dSpooka #include <dev/putter/putter_sys.h>
434f69d01dSpooka
44*6bb51422Spooka #include <rump-sys/vfs.h>
45*6bb51422Spooka
46bdf6e0b0Spooka #include <rump/rump.h>
47bdf6e0b0Spooka #include <rump/rumpuser.h>
484f69d01dSpooka
494f69d01dSpooka void putterattach(void); /* XXX: from autoconf */
504f69d01dSpooka dev_type_open(puttercdopen);
514f69d01dSpooka
524f69d01dSpooka struct ptargs {
534f69d01dSpooka int comfd;
544f69d01dSpooka int fpfd;
554f69d01dSpooka struct filedesc *fdp;
564f69d01dSpooka };
574f69d01dSpooka
584f69d01dSpooka #define BUFSIZE (64*1024)
594f69d01dSpooka extern int hz;
604f69d01dSpooka
614f69d01dSpooka /*
624f69d01dSpooka * Read requests from /dev/puffs and forward them to comfd
634f69d01dSpooka *
644f69d01dSpooka * XXX: the init detection is really sucky, but let's not
654f69d01dSpooka * waste too much energy for a better one here
664f69d01dSpooka */
674f69d01dSpooka static void
readthread(void * arg)684f69d01dSpooka readthread(void *arg)
694f69d01dSpooka {
704f69d01dSpooka struct ptargs *pap = arg;
714f69d01dSpooka struct file *fp;
724f69d01dSpooka register_t rv;
734f69d01dSpooka char *buf;
744f69d01dSpooka off_t off;
754f69d01dSpooka int error, inited;
764f69d01dSpooka
774f69d01dSpooka buf = kmem_alloc(BUFSIZE, KM_SLEEP);
784f69d01dSpooka inited = 0;
794f69d01dSpooka
804f69d01dSpooka retry:
814f69d01dSpooka kpause(NULL, 0, hz/4, NULL);
824f69d01dSpooka
834f69d01dSpooka for (;;) {
8432a34307Spooka size_t n;
854f69d01dSpooka
864f69d01dSpooka off = 0;
87a9ca7a37Sad fp = fd_getfile(pap->fpfd);
8865bd814eSchristos if (fp == NULL)
8965bd814eSchristos error = EINVAL;
9065bd814eSchristos else
914f69d01dSpooka error = dofileread(pap->fpfd, fp, buf, BUFSIZE,
924f69d01dSpooka &off, 0, &rv);
934f69d01dSpooka if (error) {
944f69d01dSpooka if (error == ENOENT && inited == 0)
954f69d01dSpooka goto retry;
964f69d01dSpooka if (error == ENXIO)
974b9a5d92Spooka break;
984f69d01dSpooka panic("fileread failed: %d", error);
994f69d01dSpooka }
1004f69d01dSpooka inited = 1;
1014f69d01dSpooka
1024f69d01dSpooka while (rv) {
1030dc3609eSpooka struct rumpuser_iovec iov;
1040dc3609eSpooka
1050dc3609eSpooka iov.iov_base = buf;
1060dc3609eSpooka iov.iov_len = rv;
1070dc3609eSpooka
10832a34307Spooka error = rumpuser_iovwrite(pap->comfd, &iov, 1,
10932a34307Spooka RUMPUSER_IOV_NOSEEK, &n);
11032a34307Spooka if (error)
1114f69d01dSpooka panic("fileread failed: %d", error);
1124f69d01dSpooka if (n == 0)
1134f69d01dSpooka panic("fileread failed: closed");
1144f69d01dSpooka rv -= n;
1154f69d01dSpooka }
1164f69d01dSpooka }
1174b9a5d92Spooka
1184b9a5d92Spooka kthread_exit(0);
1194f69d01dSpooka }
1204f69d01dSpooka
1214f69d01dSpooka /* Read requests from comfd and proxy them to /dev/puffs */
1224f69d01dSpooka static void
writethread(void * arg)1234f69d01dSpooka writethread(void *arg)
1244f69d01dSpooka {
1254f69d01dSpooka struct ptargs *pap = arg;
1264f69d01dSpooka struct file *fp;
1274b9a5d92Spooka struct putter_hdr *phdr;
1284f69d01dSpooka register_t rv;
1294f69d01dSpooka char *buf;
130827e91ddSpooka off_t off;
131827e91ddSpooka size_t toread;
1324f69d01dSpooka int error;
1334f69d01dSpooka
1344f69d01dSpooka buf = kmem_alloc(BUFSIZE, KM_SLEEP);
1354b9a5d92Spooka phdr = (struct putter_hdr *)buf;
1364f69d01dSpooka
1374f69d01dSpooka for (;;) {
13832a34307Spooka size_t n;
1394f69d01dSpooka
1404b9a5d92Spooka /*
1414b9a5d92Spooka * Need to write everything to the "kernel" in one chunk,
1424b9a5d92Spooka * so make sure we have it here.
1434b9a5d92Spooka */
144827e91ddSpooka off = 0;
1454b9a5d92Spooka toread = sizeof(struct putter_hdr);
1464b9a5d92Spooka do {
1470dc3609eSpooka struct rumpuser_iovec iov;
1480dc3609eSpooka
1490dc3609eSpooka iov.iov_base = buf+off;
1500dc3609eSpooka iov.iov_len = toread;
15132a34307Spooka error = rumpuser_iovread(pap->comfd, &iov, 1,
15232a34307Spooka RUMPUSER_IOV_NOSEEK, &n);
15332a34307Spooka if (error)
15432a34307Spooka panic("rumpuser_read %zd %d", n, error);
1554b9a5d92Spooka if (n == 0)
156aa224b94Spooka goto out;
157827e91ddSpooka off += n;
158827e91ddSpooka if (off >= sizeof(struct putter_hdr))
159827e91ddSpooka toread = phdr->pth_framelen - off;
1604b9a5d92Spooka else
161827e91ddSpooka toread = off - sizeof(struct putter_hdr);
1624b9a5d92Spooka } while (toread);
1634b9a5d92Spooka
164827e91ddSpooka off = 0;
165827e91ddSpooka rv = 0;
1664b9a5d92Spooka fp = fd_getfile(pap->fpfd);
16765bd814eSchristos if (fp == NULL)
16865bd814eSchristos error = EINVAL;
16965bd814eSchristos else
17065bd814eSchristos error = dofilewrite(pap->fpfd, fp, buf,
17165bd814eSchristos phdr->pth_framelen, &off, 0, &rv);
1724b9a5d92Spooka if (error == ENXIO)
173aa224b94Spooka goto out;
1744b9a5d92Spooka KASSERT(rv == phdr->pth_framelen);
1754b9a5d92Spooka }
176aa224b94Spooka out:
1774b9a5d92Spooka
1784b9a5d92Spooka kthread_exit(0);
1794f69d01dSpooka }
1804f69d01dSpooka
1814f69d01dSpooka int
rump_syspuffs_glueinit(int fd,int * newfd)182d09e2773Spooka rump_syspuffs_glueinit(int fd, int *newfd)
1834f69d01dSpooka {
1844f69d01dSpooka struct ptargs *pap;
1854f69d01dSpooka int rv;
1864f69d01dSpooka
187f4ce96e8Spooka if ((rv = rump_init()) != 0)
188f4ce96e8Spooka return rv;
189f4ce96e8Spooka
1904f69d01dSpooka putterattach();
1914f69d01dSpooka rv = puttercdopen(makedev(178, 0), 0, 0, curlwp);
1924f69d01dSpooka if (rv && rv != EMOVEFD)
1934f69d01dSpooka return rv;
1944f69d01dSpooka
1954f69d01dSpooka pap = kmem_alloc(sizeof(struct ptargs), KM_SLEEP);
1964f69d01dSpooka pap->comfd = fd;
1974f69d01dSpooka pap->fpfd = curlwp->l_dupfd;
1984f69d01dSpooka pap->fdp = curlwp->l_proc->p_fd;
1994f69d01dSpooka
200524046d7Schristos rv = kthread_create(PRI_NONE, 0, NULL, readthread, pap, NULL,
201524046d7Schristos "rputter");
202524046d7Schristos if (rv)
203524046d7Schristos return rv;
204524046d7Schristos
205524046d7Schristos rv = kthread_create(PRI_NONE, 0, NULL, writethread, pap, NULL,
206524046d7Schristos "wputter");
207524046d7Schristos if (rv)
208524046d7Schristos return rv;
2094f69d01dSpooka
2104f69d01dSpooka *newfd = curlwp->l_dupfd;
2114f69d01dSpooka return 0;
2124f69d01dSpooka }
213