bhyve: add bootindex option for several devices

The bootindex option creates an entry in the "bootorder" fwcfg file.
This file can be picked up by the guest firmware to determine the
bootorder. Nevertheless, it's not guaranteed that the guest firmware
uses the bootorder. At the moment, our OVMF ignores the bootorder. This
will change in the future.

If guest firmware supports the "bootorder" fwcfg file and no device uses
the bootindex option, the boot order is determined by the firmware
itself. If one or more devices specify a bootindex, the first bootable
device with the lowest bootindex will be booted. It's not garanteed that
devices without a bootindex will be recognized as bootable from the
firmware in that case.

Reviewed by:		jhb
MFC after:		1 week
Sponsored by:		Beckhoff Automation GmbH & Co. KG
Differential Revision:	https://reviews.freebsd.org/D39285
This commit is contained in:
Corvin Köhne 2021-08-16 09:50:15 +02:00
parent 6632a0a4e3
commit 480bef9481
No known key found for this signature in database
GPG Key ID: D854DA56315E026A
7 changed files with 69 additions and 1 deletions

View File

@ -494,6 +494,12 @@ if not explicitly specified.
Disable emulation of guest trim requests via
.Dv DIOCGDELETE
requests.
.It Li bootindex= Ns Ar index
Add the device to the bootorder at
.Ar index .
A fwcfg file is used to specify the bootorder.
The guest firmware may ignore or doesn't support this fwcfg file.
In that case, this feature doesn't work as expected.
.El
.Pp
SCSI device backends:
@ -511,6 +517,12 @@ are:
.It Cm iid= Ns Ar IID
Initiator ID to use when sending requests to specified CTL port.
The default value is 0.
.It Li bootindex= Ns Ar index
Add the device to the bootorder at
.Ar index .
A fwcfg file is used to specify the bootorder.
The guest firmware may ignore or doesn't support this fwcfg file.
In that case, this feature doesn't work as expected.
.El
.Pp
9P device backends:
@ -608,6 +620,12 @@ Add
.Ar romfile
as option ROM to the PCI device.
The ROM will be loaded by firmware and should be capable of initializing the device.
.It Li bootindex= Ns Ar index
Add the device to the bootorder at
.Ar index .
A fwcfg file is used to specify the bootorder.
The guest firmware may ignore or doesn't support this fwcfg file.
In that case, this feature doesn't work as expected.
.El
.Pp
Guest memory must be wired using the

View File

@ -122,6 +122,7 @@ struct blockif_ctxt {
TAILQ_HEAD(, blockif_elem) bc_pendq;
TAILQ_HEAD(, blockif_elem) bc_busyq;
struct blockif_elem bc_reqs[BLOCKIF_MAXREQ];
int bc_bootindex;
};
static pthread_once_t blockif_once = PTHREAD_ONCE_INIT;
@ -466,12 +467,22 @@ blockif_legacy_config(nvlist_t *nvl, const char *opts)
return (pci_parse_legacy_config(nvl, cp + 1));
}
int
blockif_add_boot_device(struct pci_devinst *const pi,
struct blockif_ctxt *const bc)
{
if (bc->bc_bootindex < 0)
return (0);
return (pci_emul_add_boot_device(pi, bc->bc_bootindex));
}
struct blockif_ctxt *
blockif_open(nvlist_t *nvl, const char *ident)
{
char tname[MAXCOMLEN + 1];
char name[MAXPATHLEN];
const char *path, *pssval, *ssval;
const char *path, *pssval, *ssval, *bootindex_val;
char *cp;
struct blockif_ctxt *bc;
struct stat sbuf;
@ -480,6 +491,7 @@ blockif_open(nvlist_t *nvl, const char *ident)
int extra, fd, i, sectsz;
int ro, candelete, geom, ssopt, pssopt;
int nodelete;
int bootindex;
#ifndef WITHOUT_CAPSICUM
cap_rights_t rights;
@ -493,6 +505,7 @@ blockif_open(nvlist_t *nvl, const char *ident)
ssopt = 0;
ro = 0;
nodelete = 0;
bootindex = -1;
if (get_config_bool_node_default(nvl, "nocache", false))
extra |= O_DIRECT;
@ -525,6 +538,11 @@ blockif_open(nvlist_t *nvl, const char *ident)
}
}
bootindex_val = get_config_value_node(nvl, "bootindex");
if (bootindex_val != NULL) {
bootindex = atoi(bootindex_val);
}
path = get_config_value_node(nvl, "path");
if (path == NULL) {
EPRINTLN("Missing \"path\" for block device.");
@ -644,6 +662,7 @@ blockif_open(nvlist_t *nvl, const char *ident)
TAILQ_INIT(&bc->bc_freeq);
TAILQ_INIT(&bc->bc_pendq);
TAILQ_INIT(&bc->bc_busyq);
bc->bc_bootindex = bootindex;
for (i = 0; i < BLOCKIF_MAXREQ; i++) {
bc->bc_reqs[i].be_status = BST_FREE;
TAILQ_INSERT_HEAD(&bc->bc_freeq, &bc->bc_reqs[i], be_link);

View File

@ -62,11 +62,13 @@ struct blockif_req {
struct iovec br_iov[BLOCKIF_IOV_MAX];
};
struct pci_devinst;
struct blockif_ctxt;
typedef void blockif_resize_cb(struct blockif_ctxt *, void *, size_t);
int blockif_legacy_config(nvlist_t *nvl, const char *opts);
int blockif_add_boot_device(struct pci_devinst *const pi, struct blockif_ctxt *const bc);
struct blockif_ctxt *blockif_open(nvlist_t *nvl, const char *ident);
int blockif_register_resize_callback(struct blockif_ctxt *bc,
blockif_resize_cb *cb, void *cb_arg);

View File

@ -2477,6 +2477,13 @@ pci_ahci_init(struct pci_devinst *pi, nvlist_t *nvl)
ret = 1;
goto open_fail;
}
ret = blockif_add_boot_device(pi, bctxt);
if (ret) {
sc->ports = p;
goto open_fail;
}
sc->port[p].bctx = bctxt;
sc->port[p].pr_sc = sc;
sc->port[p].port = p;

View File

@ -3159,6 +3159,14 @@ pci_nvme_parse_config(struct pci_nvme_softc *sc, nvlist_t *nvl)
sc->dataset_management = NVME_DATASET_MANAGEMENT_DISABLE;
}
value = get_config_value_node(nvl, "bootindex");
if (value != NULL) {
if (pci_emul_add_boot_device(sc->nsc_pi, atoi(value))) {
EPRINTLN("Invalid bootindex %d", atoi(value));
return (-1);
}
}
value = get_config_value_node(nvl, "ram");
if (value != NULL) {
uint64_t sz = strtoull(value, NULL, 10);

View File

@ -471,6 +471,11 @@ pci_vtblk_init(struct pci_devinst *pi, nvlist_t *nvl)
return (1);
}
if (blockif_add_boot_device(pi, bctxt)) {
perror("Invalid boot device");
return (1);
}
size = blockif_size(bctxt);
sectsz = blockif_sectsz(bctxt);
blockif_psectsz(bctxt, &sts, &sto);

View File

@ -709,6 +709,15 @@ pci_vtscsi_init(struct pci_devinst *pi, nvlist_t *nvl)
if (value != NULL)
sc->vss_iid = strtoul(value, NULL, 10);
value = get_config_value_node(nvl, "bootindex");
if (value != NULL) {
if (pci_emul_add_boot_device(pi, atoi(value))) {
EPRINTLN("Invalid bootindex %d", atoi(value));
free(sc);
return (-1);
}
}
devname = get_config_value_node(nvl, "dev");
if (devname == NULL)
devname = "/dev/cam/ctl";