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
This commit is contained in:
Corvin Köhne 2021-08-16 09:47:53 +02:00
parent 2e65cfd3ad
commit 6632a0a4e3
No known key found for this signature in database
GPG Key ID: D854DA56315E026A
2 changed files with 78 additions and 0 deletions

View File

@ -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
@ -955,6 +964,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)
@ -1362,6 +1410,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)
@ -1391,6 +1460,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);
@ -1498,6 +1569,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

View File

@ -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,