BHyVeに新しい仮想デバイスを追加してみる

BHyVe Hackathon用にサンプルの仮想デバイスを書いてみた。

実行イメージ

bhyve-tap0# cat /dev/bvtest 
Hello from BHyVe

仕組み

  • inl(BVTEST_LEN_PORT)で文字列の長さを取得
  • outl(BVTEST_OFF_PORT, offset)で読み取りたい1文字のオフセットを設定
  • inl(BVTEST_IO_PORT)で1文字取得

実装

diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 1769a17..b0c3f0f 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -454,6 +454,7 @@ contrib/x86emu/x86emu.c		optional x86bios | atkbd | dpms | vesa
 #
 dev/bvm/bvm_console.c		optional	bvmconsole
 dev/bvm/bvm_dbg.c		optional	bvmdebug
+dev/bvtest/bvtest.c		optional	bvtest
 #
 # x86 shared code between IA32, AMD64 and PC98 architectures
 #
diff --git a/sys/dev/bvtest/bvtest.c b/sys/dev/bvtest/bvtest.c
new file mode 100644
index 0000000..e0a8392
--- /dev/null
+++ b/sys/dev/bvtest/bvtest.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2007 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/sx.h>
+#include <sys/uio.h>
+#include <sys/module.h>
+
+#define	BVTEST_IO_PORT	0x230
+#define	BVTEST_OFF_PORT	0x234
+#define	BVTEST_LEN_PORT	0x238
+
+static d_open_t		bvtest_open;
+static d_read_t		bvtest_read;
+static d_write_t	bvtest_write;
+
+static struct cdev *bvtest_dev;
+static struct sx bvtest_lock;
+
+static struct cdevsw bvtest_cdevsw = {
+	.d_version =	D_VERSION,
+	.d_open =	bvtest_open,
+	.d_read =	bvtest_read,
+	.d_write =	bvtest_write,
+	.d_name =	"bvtest",
+};
+
+static int
+bvtest_open(struct cdev *dev __unused, int flags, int fmt __unused,
+    struct thread *td)
+{
+	int error = 0;
+
+	if (flags & FWRITE)
+		error = securelevel_gt(td->td_ucred, 0);
+
+	return (error);
+}
+
+static int
+bvtest_read(struct cdev *dev, struct uio *uio, int flags)
+{
+	int err = 0;
+	int len = inl(BVTEST_LEN_PORT);
+	char buf[len];
+	int amt = MIN(uio->uio_resid, (len - uio->uio_offset > 0) ?
+		len - uio->uio_offset : 0);
+
+	for (int i = 0; i < len; i++) {
+		outl(BVTEST_OFF_PORT, i);
+		buf[i] = inl(BVTEST_IO_PORT);
+	}
+
+	if ((err = uiomove(buf + uio->uio_offset, amt, uio)) != 0) {
+		uprintf("uiomove failed!\n");
+	}
+
+	return (err);
+}
+
+static int
+bvtest_write(struct cdev *dev, struct uio *uio, int flags)
+{
+	uio->uio_resid = 0;
+
+	return (0);
+}
+
+static int
+bvtest_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		sx_init(&bvtest_lock, "bvtest");
+		bvtest_dev = make_dev(&bvtest_cdevsw, 0,
+		    UID_ROOT, GID_KMEM, 0640, "bvtest");
+		break;
+	case MOD_UNLOAD:
+	case MOD_SHUTDOWN:
+		destroy_dev(bvtest_dev);
+		sx_destroy(&bvtest_lock);
+		break;
+	default:
+		return (EOPNOTSUPP);
+	}
+	return (0);
+}
+DEV_MODULE(bvtest, bvtest_modevent, NULL);
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 8f4e948..8b28bf4 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -721,6 +721,7 @@ _wpifw=		wpifw
 .if ${MK_ZFS} != "no" || defined(ALL_MODULES)
 _zfs=		zfs
 .endif
+_bvtest=	bvtest
 .endif
 
 .if ${MACHINE_CPUARCH} == "arm"
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index b381b8c..2a80471 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -8,6 +8,7 @@ SRCS=	atpic.c consport.c dbgport.c elcr.c fbsdrun.c inout.c
 SRCS+=  instruction_emul.c mevent.c
 SRCS+=	pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c
 SRCS+=	pci_virtio_net.c pci_uart.c pit_8254.c post.c rtc.c uart.c xmsr.c
+SRCS+=	bvtest.c
 
 NO_MAN=
 
diff --git a/usr.sbin/bhyve/bvtest.c b/usr.sbin/bhyve/bvtest.c
new file mode 100644
index 0000000..16880a1
--- /dev/null
+++ b/usr.sbin/bhyve/bvtest.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "inout.h"
+
+#define	BVTEST_IO_PORT	0x230
+#define	BVTEST_OFF_PORT	0x234
+#define	BVTEST_LEN_PORT	0x238
+
+static const char *buf = "Hello from BHyVe\n";
+static int off = 0;
+
+static int
+bvtest_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+		uint32_t *eax, void *arg)
+{
+	if (!(in && bytes == 4))
+		return (-1);
+	*eax = buf[off];
+	return (0);
+}
+
+static int
+bvtest_off_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+		uint32_t *eax, void *arg)
+{
+	if (!(!in && bytes == 4))
+		return (-1);
+	off = *eax;
+	return (0);
+}
+
+static int
+bvtest_len_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+		uint32_t *eax, void *arg)
+{
+	if (!(in && bytes == 4))
+		return (-1);
+	*eax = strlen(buf);
+	return (0);
+}
+
+INOUT_PORT(bvtest_io, BVTEST_IO_PORT, IOPORT_F_IN, bvtest_io_handler);
+INOUT_PORT(bvtest_off, BVTEST_OFF_PORT, IOPORT_F_OUT, bvtest_off_handler);
+INOUT_PORT(bvtest_len, BVTEST_LEN_PORT, IOPORT_F_IN, bvtest_len_handler);

ダウンロード

gistからどうぞ