The branch main has been updated by corvink:

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

commit d85147f3d6811c04e250bfb4597783d8844de315
Author:     Corvin Köhne <corv...@freebsd.org>
AuthorDate: 2021-08-18 07:31:59 +0000
Commit:     Corvin Köhne <corv...@freebsd.org>
CommitDate: 2023-03-17 08:35:36 +0000

    bhyve: add cmdline option to enable qemu's fwcfg
    
    Let the user decide if he wants to use bhyve's fwctl or qemu's fwcfg. He
    can set the interface by adding a fwcfg option to bootrom:
    
    -l bootrom,<path/to/rom>,fwcfg=bhyve
    -l bootrom,<path/to/rom>,fwcfg=qemu
    
    Reviewed by:            markj
    MFC after:              1 week
    Sponsored by:           Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D38337
---
 usr.sbin/bhyve/Makefile       |  1 +
 usr.sbin/bhyve/bhyve.8        | 29 ++++++++++++++++--
 usr.sbin/bhyve/bhyve_config.5 |  8 +++++
 usr.sbin/bhyve/bhyverun.c     | 16 +++++++++-
 usr.sbin/bhyve/pci_lpc.c      | 18 ++++++++++-
 usr.sbin/bhyve/pci_lpc.h      |  1 +
 usr.sbin/bhyve/qemu_fwcfg.c   | 71 +++++++++++++++++++++++++------------------
 7 files changed, 111 insertions(+), 33 deletions(-)

diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index 1c679a3c1578..a5a1dafebcd9 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -63,6 +63,7 @@ SRCS= \
        post.c                  \
        ps2kbd.c                \
        ps2mouse.c              \
+       qemu_fwcfg.c            \
        rfb.c                   \
        rtc.c                   \
        smbiostbl.c             \
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index 84e031f1340c..72018912e2c5 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -200,7 +200,9 @@ and
 .Cm com4 ,
 the boot ROM device
 .Cm bootrom ,
-and the debug/test device
+the
+.Cm fwcfg
+type and the debug/test device
 .Cm pc-testdev .
 .Pp
 The possible values for the
@@ -345,7 +347,7 @@ PCI 16550 serial device.
 .It Cm lpc
 LPC PCI-ISA bridge with COM1, COM2, COM3, and COM4 16550 serial ports,
 a boot ROM, and,
-optionally, the debug/test device.
+optionally, a fwcfg type and the debug/test device.
 The LPC bridge emulation can only be configured on bus 0.
 .It Cm fbuf
 Raw framebuffer device attached to VNC server.
@@ -520,6 +522,29 @@ address space, and any modifications the guest makes will 
be saved
 to that file.
 .El
 .Pp
+Fwcfg types:
+.Bl -tag -width 10n
+.It Ar fwcfg
+The fwcfg interface is used to pass information such as the CPU count or ACPI 
tables to the guest firmware.
+Supported values are
+.Ql bhyve
+and
+.Ql qemu .
+Due to backward compatibility reasons,
+.Ql bhyve
+is the default option.
+When
+.Ql bhyve
+is used, bhyve's fwctl interface is used.
+It currently reports only the CPU count to the guest firmware.
+The
+.Ql qemu
+option uses QEMU's fwcfg interface.
+This interface is widely used and allows user-defined information to be passed 
to the guest.
+It is used for passing the CPU count, ACPI tables, a boot order and many other 
things to the guest.
+Some operating systems such as Fedora CoreOS can be configured by qemu's fwcfg 
interface as well.
+.El
+.Pp
 Pass-through device backends:
 .Sm off
 .Bl -bullet
diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5
index 94a8a4d5cb1d..32658c11f9e2 100644
--- a/usr.sbin/bhyve/bhyve_config.5
+++ b/usr.sbin/bhyve/bhyve_config.5
@@ -259,6 +259,7 @@ VGA framebuffer device attached to VNC server.
 .It Li lpc
 LPC PCI-ISA bridge with COM1-COM4 16550 serial ports,
 a boot ROM,
+an optional fwcfg type,
 and an optional debug/test device.
 This device must be configured on bus 0.
 .It Li hda
@@ -529,6 +530,13 @@ Settings for the COM2 serial port device.
 Settings for the COM3 serial port device.
 .It Va com4 Ta node Ta Ta
 Settings for the COM4 serial port device.
+.It Va fwcfg Ta string Ta bhyve Ta
+The fwcfg type to be used.
+Supported values are
+.Dq bhyve
+for fwctl and
+.Dq qemu
+for fwcfg.
 .It Va pc-testdev Ta bool Ta false Ta
 Enable the PC debug/test device.
 .El
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index af4d15666ae3..665fec73e48c 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -101,6 +101,7 @@ __FBSDID("$FreeBSD$");
 #include "pci_emul.h"
 #include "pci_irq.h"
 #include "pci_lpc.h"
+#include "qemu_fwcfg.h"
 #include "smbiostbl.h"
 #ifdef BHYVE_SNAPSHOT
 #include "snapshot.h"
@@ -1231,6 +1232,7 @@ set_defaults(void)
        set_config_bool("acpi_tables", false);
        set_config_value("memory.size", "256M");
        set_config_bool("x86.strictmsr", true);
+       set_config_value("lpc.fwcfg", "bhyve");
 }
 
 int
@@ -1460,6 +1462,17 @@ main(int argc, char *argv[])
        rtc_init(ctx);
        sci_init(ctx);
 
+       if (qemu_fwcfg_init(ctx) != 0) {
+               fprintf(stderr, "qemu fwcfg initialization error");
+               exit(4);
+       }
+
+       if (qemu_fwcfg_add_file("opt/bhyve/hw.ncpu", sizeof(guest_ncpus),
+           &guest_ncpus) != 0) {
+               fprintf(stderr, "Could not add qemu fwcfg opt/bhyve/hw.ncpu");
+               exit(4);
+       }
+
        /*
         * Exit if a device emulation finds an error in its initilization
         */
@@ -1554,8 +1567,9 @@ main(int argc, char *argv[])
                assert(error == 0);
        }
 
-       if (lpc_bootrom())
+       if (lpc_bootrom() && strcmp(lpc_fwcfg(), "bhyve") == 0) {
                fwctl_init();
+       }
 
        /*
         * Change the proc title to include the VM name.
diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c
index 548726e27d0d..ad47230c005e 100644
--- a/usr.sbin/bhyve/pci_lpc.c
+++ b/usr.sbin/bhyve/pci_lpc.c
@@ -110,10 +110,20 @@ lpc_device_parse(const char *opts)
                        set_config_value("lpc.bootrom", romfile);
 
                        varfile = strsep(&str, ",");
-                       if (varfile != NULL) {
+                       if (varfile == NULL) {
+                               error = 0;
+                               goto done;
+                       }
+                       if (strchr(varfile, '=') == NULL) {
                                set_config_value("lpc.bootvars", varfile);
+                       } else {
+                               /* varfile doesn't exist, it's another config
+                                * option */
+                               pci_parse_legacy_config(find_config_node("lpc"),
+                                   varfile);
                        }
 
+                       pci_parse_legacy_config(find_config_node("lpc"), str);
                        error = 0;
                        goto done;
                }
@@ -160,6 +170,12 @@ lpc_bootrom(void)
        return (get_config_value("lpc.bootrom"));
 }
 
+const char *
+lpc_fwcfg(void)
+{
+       return (get_config_value("lpc.fwcfg"));
+}
+
 static void
 lpc_uart_intr_assert(void *arg)
 {
diff --git a/usr.sbin/bhyve/pci_lpc.h b/usr.sbin/bhyve/pci_lpc.h
index 611b025d4386..ff3ea98b4f9c 100644
--- a/usr.sbin/bhyve/pci_lpc.h
+++ b/usr.sbin/bhyve/pci_lpc.h
@@ -72,5 +72,6 @@ void    lpc_print_supported_devices(void);
 char   *lpc_pirq_name(int pin);
 void   lpc_pirq_routed(void);
 const char *lpc_bootrom(void);
+const char *lpc_fwcfg(void);
 
 #endif
diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c
index 5ee35d6764e6..1b0b5e3e9931 100644
--- a/usr.sbin/bhyve/qemu_fwcfg.c
+++ b/usr.sbin/bhyve/qemu_fwcfg.c
@@ -17,6 +17,7 @@
 
 #include "acpi_device.h"
 #include "inout.h"
+#include "pci_lpc.h"
 #include "qemu_fwcfg.h"
 
 #define QEMU_FWCFG_ACPI_DEVICE_NAME "FWCF"
@@ -351,37 +352,49 @@ qemu_fwcfg_init(struct vmctx *const ctx)
 {
        int error;
 
-       error = acpi_device_create(&fwcfg_sc.acpi_dev, ctx,
-           QEMU_FWCFG_ACPI_DEVICE_NAME, QEMU_FWCFG_ACPI_HARDWARE_ID);
-       if (error) {
-               warnx("%s: failed to create ACPI device for QEMU FwCfg",
-                   __func__);
-               goto done;
-       }
+       /*
+        * Bhyve supports fwctl (bhyve) and fwcfg (qemu) as firmware interfaces.
+        * Both are using the same ports. So, it's not possible to provide both
+        * interfaces at the same time to the guest. Therefore, only create acpi
+        * tables and register io ports for fwcfg, if it's used.
+        */
+       if (strcmp(lpc_fwcfg(), "qemu") == 0) {
+               error = acpi_device_create(&fwcfg_sc.acpi_dev, ctx,
+                   QEMU_FWCFG_ACPI_DEVICE_NAME, QEMU_FWCFG_ACPI_HARDWARE_ID);
+               if (error) {
+                       warnx("%s: failed to create ACPI device for QEMU FwCfg",
+                           __func__);
+                       goto done;
+               }
 
-       error = acpi_device_add_res_fixed_ioport(fwcfg_sc.acpi_dev,
-           QEMU_FWCFG_SELECTOR_PORT_NUMBER, 2);
-       if (error) {
-               warnx("%s: failed to add fixed IO port for QEMU FwCfg",
-                   __func__);
-               goto done;
-       }
+               error = acpi_device_add_res_fixed_ioport(fwcfg_sc.acpi_dev,
+                   QEMU_FWCFG_SELECTOR_PORT_NUMBER, 2);
+               if (error) {
+                       warnx("%s: failed to add fixed IO port for QEMU FwCfg",
+                           __func__);
+                       goto done;
+               }
 
-       /* add handlers for fwcfg ports */
-       if ((error = qemu_fwcfg_register_port("qemu_fwcfg_selector",
-           QEMU_FWCFG_SELECTOR_PORT_NUMBER, QEMU_FWCFG_SELECTOR_PORT_SIZE,
-           QEMU_FWCFG_SELECTOR_PORT_FLAGS,
-           qemu_fwcfg_selector_port_handler)) != 0) {
-               warnx("%s: Unable to register qemu fwcfg selector port 0x%x",
-                   __func__, QEMU_FWCFG_SELECTOR_PORT_NUMBER);
-               goto done;
-       }
-       if ((error = qemu_fwcfg_register_port("qemu_fwcfg_data",
-           QEMU_FWCFG_DATA_PORT_NUMBER, QEMU_FWCFG_DATA_PORT_SIZE,
-           QEMU_FWCFG_DATA_PORT_FLAGS, qemu_fwcfg_data_port_handler)) != 0) {
-               warnx("%s: Unable to register qemu fwcfg data port 0x%x",
-                   __func__, QEMU_FWCFG_DATA_PORT_NUMBER);
-               goto done;
+               /* add handlers for fwcfg ports */
+               if ((error = qemu_fwcfg_register_port("qemu_fwcfg_selector",
+                   QEMU_FWCFG_SELECTOR_PORT_NUMBER,
+                   QEMU_FWCFG_SELECTOR_PORT_SIZE,
+                   QEMU_FWCFG_SELECTOR_PORT_FLAGS,
+                   qemu_fwcfg_selector_port_handler)) != 0) {
+                       warnx(
+                           "%s: Unable to register qemu fwcfg selector port 
0x%x",
+                           __func__, QEMU_FWCFG_SELECTOR_PORT_NUMBER);
+                       goto done;
+               }
+               if ((error = qemu_fwcfg_register_port("qemu_fwcfg_data",
+                   QEMU_FWCFG_DATA_PORT_NUMBER, QEMU_FWCFG_DATA_PORT_SIZE,
+                   QEMU_FWCFG_DATA_PORT_FLAGS,
+                   qemu_fwcfg_data_port_handler)) != 0) {
+                       warnx(
+                           "%s: Unable to register qemu fwcfg data port 0x%x",
+                           __func__, QEMU_FWCFG_DATA_PORT_NUMBER);
+                       goto done;
+               }
        }
 
        /* add common fwcfg items */

Reply via email to