diff options
author | Corvin Köhne <corvink@FreeBSD.org> | 2021-08-11 08:02:57 +0000 |
---|---|---|
committer | Corvin Köhne <corvink@FreeBSD.org> | 2023-02-28 12:37:12 +0000 |
commit | 34f804e547e7c3b10b12f5450ff2e0a771000daf (patch) | |
tree | 8c11f21d91192e69937c62e5c38caa36e498e6bc | |
parent | 3ef46195ac37111ab247cfabed735d3ee5e7f5b5 (diff) | |
download | src-34f804e547e7c3b10b12f5450ff2e0a771000daf.tar.gz src-34f804e547e7c3b10b12f5450ff2e0a771000daf.zip |
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
-rw-r--r-- | usr.sbin/bhyve/qemu_fwcfg.c | 99 | ||||
-rw-r--r-- | usr.sbin/bhyve/qemu_fwcfg.h | 1 |
2 files changed, 100 insertions, 0 deletions
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 { @@ -156,6 +185,62 @@ qemu_fwcfg_add_item(const uint16_t architecture, const uint16_t index, } 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; |