git: c791a53c8026 - stable/13 - bhyve: add helper to create a bootorder
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Aug 2023 07:53:44 UTC
The branch stable/13 has been updated by corvink:
URL: https://cgit.FreeBSD.org/src/commit/?id=c791a53c8026951051be47cbd608915b6fa41845
commit c791a53c8026951051be47cbd608915b6fa41845
Author: Corvin Köhne <corvink@FreeBSD.org>
AuthorDate: 2021-08-16 07:47:53 +0000
Commit: Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-08-18 07:52:10 +0000
bhyve: add helper to create a bootorder
Qemu's fwcfg allows to define a bootorder. Therefore, the hypervisor has
to create a fwcfg item named bootorder, which has a newline seperated
list of boot entries. Qemu's OVMF will pick up the bootorder and applies
it.
Add the moment, bhyve's OVMF doesn't support a custom bootorder by
qemu's fwcfg. However, in the future bhyve will gain support for qemu's
OVMF. Additonally, we can port relevant parts from qemu's to bhyve's
OVMF implementation.
Reviewed by: jhb, markj
MFC after: 1 week
Sponsored by: Beckhoff Automation GmbH & Co. KG
Differential Revision: https://reviews.freebsd.org/D39284
(cherry picked from commit 6632a0a4e3ab68b0e31b612e8aeca14de3fc8159)
---
usr.sbin/bhyve/pci_emul.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
usr.sbin/bhyve/pci_emul.h | 2 ++
2 files changed, 78 insertions(+)
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index f52bf94b7c3d..2f85e453ff17 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "pci_irq.h"
#include "pci_lpc.h"
#include "pci_passthru.h"
+#include "qemu_fwcfg.h"
#define CONF1_ADDR_PORT 0x0cf8
#define CONF1_DATA_PORT 0x0cfc
@@ -121,6 +122,14 @@ struct pci_bar_allocation {
static TAILQ_HEAD(pci_bar_list, pci_bar_allocation) pci_bars =
TAILQ_HEAD_INITIALIZER(pci_bars);
+struct boot_device {
+ TAILQ_ENTRY(boot_device) boot_device_chain;
+ struct pci_devinst *pdi;
+ int bootindex;
+};
+static TAILQ_HEAD(boot_list, boot_device) boot_devices = TAILQ_HEAD_INITIALIZER(
+ boot_devices);
+
#define PCI_EMUL_IOBASE 0x2000
#define PCI_EMUL_IOLIMIT 0x10000
@@ -949,6 +958,45 @@ pci_emul_alloc_rom(struct pci_devinst *const pdi, const uint64_t size,
return (0);
}
+int
+pci_emul_add_boot_device(struct pci_devinst *pi, int bootindex)
+{
+ struct boot_device *new_device, *device;
+
+ /* don't permit a negative bootindex */
+ if (bootindex < 0) {
+ errx(4, "Invalid bootindex %d for %s", bootindex, pi->pi_name);
+ }
+
+ /* alloc new boot device */
+ new_device = calloc(1, sizeof(struct boot_device));
+ if (new_device == NULL) {
+ return (ENOMEM);
+ }
+ new_device->pdi = pi;
+ new_device->bootindex = bootindex;
+
+ /* search for boot device with higher boot index */
+ TAILQ_FOREACH(device, &boot_devices, boot_device_chain) {
+ if (device->bootindex == bootindex) {
+ errx(4,
+ "Could not set bootindex %d for %s. Bootindex already occupied by %s",
+ bootindex, pi->pi_name, device->pdi->pi_name);
+ } else if (device->bootindex > bootindex) {
+ break;
+ }
+ }
+
+ /* add boot device to queue */
+ if (device == NULL) {
+ TAILQ_INSERT_TAIL(&boot_devices, new_device, boot_device_chain);
+ } else {
+ TAILQ_INSERT_BEFORE(device, new_device, boot_device_chain);
+ }
+
+ return (0);
+}
+
#define CAP_START_OFFSET 0x40
static int
pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen)
@@ -1357,6 +1405,27 @@ pci_ecfg_base(void)
return (PCI_EMUL_ECFG_BASE);
}
+static int
+init_bootorder(void)
+{
+ struct boot_device *device;
+ FILE *fp;
+ char *bootorder;
+ size_t bootorder_len;
+
+ if (TAILQ_EMPTY(&boot_devices))
+ return (0);
+
+ fp = open_memstream(&bootorder, &bootorder_len);
+ TAILQ_FOREACH(device, &boot_devices, boot_device_chain) {
+ fprintf(fp, "/pci@i0cf8/pci@%d,%d\n",
+ device->pdi->pi_slot, device->pdi->pi_func);
+ }
+ fclose(fp);
+
+ return (qemu_fwcfg_add_file("bootorder", bootorder_len, bootorder));
+}
+
#define BUSIO_ROUNDUP 32
#define BUSMEM32_ROUNDUP (1024 * 1024)
#define BUSMEM64_ROUNDUP (512 * 1024 * 1024)
@@ -1386,6 +1455,8 @@ init_pci(struct vmctx *ctx)
pci_emul_membase64 = roundup2(pci_emul_membase64, PCI_EMUL_MEMSIZE64);
pci_emul_memlim64 = pci_emul_membase64 + PCI_EMUL_MEMSIZE64;
+ TAILQ_INIT(&boot_devices);
+
for (bus = 0; bus < MAXBUSES; bus++) {
snprintf(node_name, sizeof(node_name), "pci.%d", bus);
nvl = find_config_node(node_name);
@@ -1493,6 +1564,11 @@ init_pci(struct vmctx *ctx)
}
lpc_pirq_routed();
+ if ((error = init_bootorder()) != 0) {
+ warnx("%s: Unable to init bootorder", __func__);
+ return (error);
+ }
+
/*
* The guest physical memory map looks like the following:
* [0, lowmem) guest system memory
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index ce14f5e34889..2eb2e3a4e280 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -234,6 +234,8 @@ int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx,
enum pcibar_type type, uint64_t size);
int pci_emul_alloc_rom(struct pci_devinst *const pdi, const uint64_t size,
void **const addr);
+int pci_emul_add_boot_device(struct pci_devinst *const pi,
+ const int bootindex);
int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum);
int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type);
void pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes,