Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Jul 2023 20:04:31 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d8bfccb22093 - main - fwctl_fetch: A small test utility for the fwctl bhyve device.
Message-ID:  <202307072004.367K4VOG029563@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=d8bfccb220939e121b6323700c634a5dff95b4ac

commit d8bfccb220939e121b6323700c634a5dff95b4ac
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2023-07-07 20:02:13 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2023-07-07 20:02:13 +0000

    fwctl_fetch: A small test utility for the fwctl bhyve device.
    
    This can be run inside a bhyve guest to query the value of fwctl
    nodes.  Note that fwctl in bhyve only supports a single hw.ncpu node.
    
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D40803
---
 tools/tools/bhyve/Makefile      |   8 +++
 tools/tools/bhyve/fwctl_fetch.c | 137 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 145 insertions(+)

diff --git a/tools/tools/bhyve/Makefile b/tools/tools/bhyve/Makefile
new file mode 100644
index 000000000000..3d9ea4167bab
--- /dev/null
+++ b/tools/tools/bhyve/Makefile
@@ -0,0 +1,8 @@
+PROGS=	fwctl_fetch
+MAN=
+BINDIR?=	/usr/local/bin
+
+# fwctl_fetch: fetch the value of fwctl nodes from a guest
+LIBADD.fwctl_fetch+=	util
+
+.include <bsd.progs.mk>
diff --git a/tools/tools/bhyve/fwctl_fetch.c b/tools/tools/bhyve/fwctl_fetch.c
new file mode 100644
index 000000000000..f3139cf4f010
--- /dev/null
+++ b/tools/tools/bhyve/fwctl_fetch.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2023 John Baldwin <jhb@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <err.h>
+#include <fcntl.h>
+#include <libutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <machine/cpufunc.h>
+
+#define	OP_GET		3
+#define	OP_GET_LEN	4
+
+/* I/O ports */
+#define	FWCTL_OUT	0x510
+#define	FWCTL_IN	0x511
+
+static void
+reset_fwctl(void)
+{
+	char buf[4];
+
+	outw(FWCTL_OUT, 0);
+	for (u_int i = 0; i < 4; i++)
+		buf[i] = inb(FWCTL_IN);
+	if (memcmp(buf, "BHYV", 4) != 0)
+		errx(1, "Signature mismatch: %.4s", buf);
+}
+
+static void
+send_node_name(const char *name)
+{
+	uint32_t value;
+	size_t len;
+
+	len = strlen(name) + 1;
+	while (len > 4) {
+		memcpy(&value, name, 4);
+		outl(FWCTL_OUT, value);
+		name += 4;
+		len -= 4;
+	}
+
+	if (len > 0) {
+		value = 0;
+		memcpy(&value, name, len);
+		outl(FWCTL_OUT, value);
+	}
+}
+
+static void
+fwctl_op(uint32_t op, uint32_t id, const char *name, void *buf, size_t len)
+{
+	char *cp;
+	uint32_t value, rsplen;
+
+	/* Length */
+	outl(FWCTL_OUT, 12 + strlen(name) + 1);
+
+	/* Operation */
+	outl(FWCTL_OUT, op);
+
+	/* Transaction ID */
+	outl(FWCTL_OUT, id);
+
+	send_node_name(name);
+
+	/* Length */
+	rsplen = inl(FWCTL_IN);
+
+	/* If there is an error, the response will have no payload. */
+	if (rsplen < 4 * sizeof(value))
+		errx(1, "Invalid response length (%u): %u", id, rsplen);
+
+	/* Operation */
+	value = inl(FWCTL_IN);
+	if (value != op)
+		errx(1, "Invalid response type (%u): %u", id, value);
+
+	/* Transaction ID */
+	value = inl(FWCTL_IN);
+	if (value != id)
+		errx(1, "Invalid response ID (%u): %u", id, value);
+
+	/* Error */
+	value = inl(FWCTL_IN);
+	if (value != 0)
+		errx(1, "Error from op %u (%u): %u", op, id, value);
+
+	/* If there wasn't an error, require payload length to match */
+	if (rsplen != 4 * sizeof(value) + len)
+		errx(1, "Response payload length mismatch (%u): %zu vs %zu", id,
+		    rsplen - 4 * sizeof(value), len);
+
+	cp = buf;
+	while (len > 0) {
+		value = inl(FWCTL_IN);
+		memcpy(cp, &value, 4);
+		cp += 4;
+		len -= 4;
+	}
+}
+
+int
+main(int ac, char **av)
+{
+	char *p;
+	size_t len, buflen, len2;
+
+	if (ac != 2)
+		errx(1, "Need node name");
+
+	if (open("/dev/io", O_RDWR) == -1)
+		err(1, "Failed to open /dev/io");
+
+	reset_fwctl();
+
+	fwctl_op(OP_GET_LEN, 1, av[1], &len, sizeof(len));
+	if (len == 0)
+		errx(1, "Node has length of 0");
+
+	/* Buffer includes embedded length followed by value. */
+	buflen = sizeof(size_t) + roundup2(len, 4);
+	p = malloc(buflen);
+	fwctl_op(OP_GET, 2, av[1], p, buflen);
+	memcpy(&len2, p, sizeof(len2));
+	if (len2 != len)
+		errx(1, "Length mismatch: %zu vs %zu", len, len2);
+	hexdump(p + sizeof(len2), len, NULL, 0);
+
+	return (0);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202307072004.367K4VOG029563>