aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorvin Köhne <corvink@FreeBSD.org>2021-08-11 07:59:16 +0000
committerCorvin Köhne <corvink@FreeBSD.org>2023-02-28 10:04:36 +0000
commitbd8366500e15e6aa840e80d21661d5f3bf4d835e (patch)
tree6c7032aa094a3bdcf93bc6b30a60ace316839e46
parent0232125972f5f9f9e88e2555d2f8d0837d117298 (diff)
downloadsrc-bd8366500e15e6aa840e80d21661d5f3bf4d835e.tar.gz
src-bd8366500e15e6aa840e80d21661d5f3bf4d835e.zip
bhyve: add emulation for the qemu fwcfg selector port
The selector port is used to select the desired fwcfg item. Reviewed by: markj MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D38332 (cherry picked from commit 151d8131a817e7a6a629e9bb7fde4d7a158e5211)
-rw-r--r--usr.sbin/bhyve/qemu_fwcfg.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c
index 5d3070abf285..dec3fa83c493 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.c
+++ b/usr.sbin/bhyve/qemu_fwcfg.c
@@ -29,8 +29,33 @@
#define QEMU_FWCFG_DATA_PORT_FLAGS \
IOPORT_F_INOUT /* QEMU v2.4+ ignores writes */
+#define QEMU_FWCFG_ARCHITECTURE_MASK 0x0001
+#define QEMU_FWCFG_INDEX_MASK 0x3FFF
+
+#define QEMU_FWCFG_SELECT_READ 0
+#define QEMU_FWCFG_SELECT_WRITE 1
+
+#define QEMU_FWCFG_ARCHITECTURE_GENERIC 0
+#define QEMU_FWCFG_ARCHITECTURE_SPECIFIC 1
+
+#pragma pack(1)
+
+union qemu_fwcfg_selector {
+ struct {
+ uint16_t index : 14;
+ uint16_t writeable : 1;
+ uint16_t architecture : 1;
+ };
+ uint16_t bits;
+};
+
+#pragma pack()
+
struct qemu_fwcfg_softc {
struct acpi_device *acpi_dev;
+
+ uint32_t data_offset;
+ union qemu_fwcfg_selector selector;
};
static struct qemu_fwcfg_softc fwcfg_sc;
@@ -40,6 +65,20 @@ qemu_fwcfg_selector_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(uint16_t)) {
+ warnx("%s: invalid size (%d) of IO port access", __func__,
+ bytes);
+ return (-1);
+ }
+
+ if (in) {
+ *eax = htole16(fwcfg_sc.selector.bits);
+ return (0);
+ }
+
+ fwcfg_sc.data_offset = 0;
+ fwcfg_sc.selector.bits = le16toh(*eax);
+
return (0);
}