git: 34f804e547e7 - main - bhyve: add common fwcfg items

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Tue, 28 Feb 2023 12:38:37 UTC
The branch main has been updated by corvink:

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

commit 34f804e547e7c3b10b12f5450ff2e0a771000daf
Author:     Corvin Köhne <corvink@FreeBSD.org>
AuthorDate: 2021-08-11 08:02:57 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-02-28 12:37:12 +0000

    bhyve: add common fwcfg items
    
    Qemu defines some common fwcfg items. We don't need to support all of
    them. Only a subset needs to be present for fwcfg to work properly.
    
    - signature
      The signature is used by the guest to check if qemu's fwcfg is
      available or not.
    - id
      The id is used by the guest to check which features are supported by
      the fwcfg implementation of the hypervisor.
    - file_dir
      The file dir reports all fwcfg items which don't have a fixed index.
      These are mostly user defined fwcfg items.
    
    Reviewed by:            <If someone else reviewed your modification.>
    MFC after:              1 week
    Sponsored by:           Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D38335
---
 usr.sbin/bhyve/qemu_fwcfg.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
 usr.sbin/bhyve/qemu_fwcfg.h |  1 +
 2 files changed, 100 insertions(+)

diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c
index 8cb71b819956..e1a67fd0d8ef 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.c
+++ b/usr.sbin/bhyve/qemu_fwcfg.c
@@ -6,6 +6,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/endian.h>
 
 #include <machine/vmm.h>
 
@@ -38,6 +39,12 @@
 #define QEMU_FWCFG_ARCHITECTURE_GENERIC 0
 #define QEMU_FWCFG_ARCHITECTURE_SPECIFIC 1
 
+#define QEMU_FWCFG_INDEX_SIGNATURE 0x00
+#define QEMU_FWCFG_INDEX_ID 0x01
+#define QEMU_FWCFG_INDEX_FILE_DIR 0x19
+
+#define QEMU_FWCFG_MIN_FILES 10
+
 #pragma pack(1)
 
 union qemu_fwcfg_selector {
@@ -49,6 +56,28 @@ union qemu_fwcfg_selector {
 	uint16_t bits;
 };
 
+struct qemu_fwcfg_signature {
+	uint8_t signature[4];
+};
+
+struct qemu_fwcfg_id {
+	uint32_t interface : 1; /* always set */
+	uint32_t DMA : 1;
+	uint32_t reserved : 30;
+};
+
+struct qemu_fwcfg_file {
+	uint32_t be_size;
+	uint16_t be_selector;
+	uint16_t reserved;
+	uint8_t name[QEMU_FWCFG_MAX_NAME];
+};
+
+struct qemu_fwcfg_directory {
+	uint32_t be_count;
+	struct qemu_fwcfg_file files[0];
+};
+
 #pragma pack()
 
 struct qemu_fwcfg_softc {
@@ -155,6 +184,62 @@ qemu_fwcfg_add_item(const uint16_t architecture, const uint16_t index,
 	return (0);
 }
 
+static int
+qemu_fwcfg_add_item_file_dir(void)
+{
+	const size_t size = sizeof(struct qemu_fwcfg_directory) +
+	    QEMU_FWCFG_MIN_FILES * sizeof(struct qemu_fwcfg_file);
+	struct qemu_fwcfg_directory *const fwcfg_directory = calloc(1, size);
+	if (fwcfg_directory == NULL) {
+		return (ENOMEM);
+	}
+
+	fwcfg_sc.directory = fwcfg_directory;
+
+	return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
+	    QEMU_FWCFG_INDEX_FILE_DIR, sizeof(struct qemu_fwcfg_directory),
+	    (uint8_t *)fwcfg_sc.directory));
+}
+
+static int
+qemu_fwcfg_add_item_id(void)
+{
+	struct qemu_fwcfg_id *const fwcfg_id = calloc(1,
+	    sizeof(struct qemu_fwcfg_id));
+	if (fwcfg_id == NULL) {
+		return (ENOMEM);
+	}
+
+	fwcfg_id->interface = 1;
+	fwcfg_id->DMA = 0;
+
+	uint32_t *const le_fwcfg_id_ptr = (uint32_t *)fwcfg_id;
+	*le_fwcfg_id_ptr = htole32(*le_fwcfg_id_ptr);
+
+	return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
+	    QEMU_FWCFG_INDEX_ID, sizeof(struct qemu_fwcfg_id),
+	    (uint8_t *)fwcfg_id));
+}
+
+static int
+qemu_fwcfg_add_item_signature(void)
+{
+	struct qemu_fwcfg_signature *const fwcfg_signature = calloc(1,
+	    sizeof(struct qemu_fwcfg_signature));
+	if (fwcfg_signature == NULL) {
+		return (ENOMEM);
+	}
+
+	fwcfg_signature->signature[0] = 'Q';
+	fwcfg_signature->signature[1] = 'E';
+	fwcfg_signature->signature[2] = 'M';
+	fwcfg_signature->signature[3] = 'U';
+
+	return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
+	    QEMU_FWCFG_INDEX_SIGNATURE, sizeof(struct qemu_fwcfg_signature),
+	    (uint8_t *)fwcfg_signature));
+}
+
 static int
 qemu_fwcfg_register_port(const char *const name, const int port, const int size,
     const int flags, const inout_func_t handler)
@@ -209,6 +294,20 @@ qemu_fwcfg_init(struct vmctx *const ctx)
 		goto done;
 	}
 
+	/* add common fwcfg items */
+	if ((error = qemu_fwcfg_add_item_signature()) != 0) {
+		warnx("%s: Unable to add signature item", __func__);
+		goto done;
+	}
+	if ((error = qemu_fwcfg_add_item_id()) != 0) {
+		warnx("%s: Unable to add id item", __func__);
+		goto done;
+	}
+	if ((error = qemu_fwcfg_add_item_file_dir()) != 0) {
+		warnx("%s: Unable to add file_dir item", __func__);
+		goto done;
+	}
+
 done:
 	if (error) {
 		acpi_device_destroy(fwcfg_sc.acpi_dev);
diff --git a/usr.sbin/bhyve/qemu_fwcfg.h b/usr.sbin/bhyve/qemu_fwcfg.h
index 58ef5ed3c6bf..b5454fa9977d 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.h
+++ b/usr.sbin/bhyve/qemu_fwcfg.h
@@ -11,6 +11,7 @@
 
 #define QEMU_FWCFG_MAX_ARCHS 0x2
 #define QEMU_FWCFG_MAX_ENTRIES 0x4000
+#define QEMU_FWCFG_MAX_NAME 56
 
 struct qemu_fwcfg_item {
 	uint32_t size;