git: 3c12bcba78ea - stable/13 - bhyve: add emulation for qemu's fwcfg data port

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Tue, 28 Feb 2023 10:14:14 UTC
The branch stable/13 has been updated by corvink:

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

commit 3c12bcba78ea2b6a9299f30f60c5988ba159ad44
Author:     Corvin Köhne <corvink@FreeBSD.org>
AuthorDate: 2021-08-11 08:00:34 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-02-28 10:04:37 +0000

    bhyve: add emulation for qemu's fwcfg data port
    
    The data port returns the data of the fwcfg item.
    
    Reviewed by:            markj
    MFC after:              1 week
    Sponsored by:           Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D38333
    
    (cherry picked from commit b11081dca76b8e283495632b86b41539ee013857)
---
 usr.sbin/bhyve/qemu_fwcfg.c | 40 ++++++++++++++++++++++++++++++++++++++++
 usr.sbin/bhyve/qemu_fwcfg.h |  8 ++++++++
 2 files changed, 48 insertions(+)

diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c
index dec3fa83c493..13e21daca7ff 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.c
+++ b/usr.sbin/bhyve/qemu_fwcfg.c
@@ -56,6 +56,8 @@ struct qemu_fwcfg_softc {
 
 	uint32_t data_offset;
 	union qemu_fwcfg_selector selector;
+	struct qemu_fwcfg_item items[QEMU_FWCFG_MAX_ARCHS]
+				    [QEMU_FWCFG_MAX_ENTRIES];
 };
 
 static struct qemu_fwcfg_softc fwcfg_sc;
@@ -87,6 +89,44 @@ qemu_fwcfg_data_port_handler(struct vmctx *const ctx __unused, const int in,
     const int port __unused, const int bytes, uint32_t *const eax,
     void *const arg __unused)
 {
+	if (bytes != sizeof(uint8_t)) {
+		warnx("%s: invalid size (%d) of IO port access", __func__,
+		    bytes);
+		return (-1);
+	}
+
+	if (!in) {
+		warnx("%s: Writes to qemu fwcfg data port aren't allowed",
+		    __func__);
+		return (-1);
+	}
+
+	/* get fwcfg item */
+	struct qemu_fwcfg_item *const item =
+	    &fwcfg_sc.items[fwcfg_sc.selector.architecture]
+			   [fwcfg_sc.selector.index];
+	if (item->data == NULL) {
+		warnx(
+		    "%s: qemu fwcfg item doesn't exist (architecture %s index 0x%x)",
+		    __func__,
+		    fwcfg_sc.selector.architecture ? "specific" : "generic",
+		    fwcfg_sc.selector.index);
+		*eax = 0x00;
+		return (0);
+	} else if (fwcfg_sc.data_offset >= item->size) {
+		warnx(
+		    "%s: qemu fwcfg item read exceeds size (architecture %s index 0x%x size 0x%x offset 0x%x)",
+		    __func__,
+		    fwcfg_sc.selector.architecture ? "specific" : "generic",
+		    fwcfg_sc.selector.index, item->size, fwcfg_sc.data_offset);
+		*eax = 0x00;
+		return (0);
+	}
+
+	/* return item data */
+	*eax = item->data[fwcfg_sc.data_offset];
+	fwcfg_sc.data_offset++;
+
 	return (0);
 }
 
diff --git a/usr.sbin/bhyve/qemu_fwcfg.h b/usr.sbin/bhyve/qemu_fwcfg.h
index 26c4db0ff71e..58ef5ed3c6bf 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.h
+++ b/usr.sbin/bhyve/qemu_fwcfg.h
@@ -9,4 +9,12 @@
 
 #include <vmmapi.h>
 
+#define QEMU_FWCFG_MAX_ARCHS 0x2
+#define QEMU_FWCFG_MAX_ENTRIES 0x4000
+
+struct qemu_fwcfg_item {
+	uint32_t size;
+	uint8_t *data;
+};
+
 int qemu_fwcfg_init(struct vmctx *const ctx);