aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKa Ho Ng <khng@FreeBSD.org>2021-03-20 07:40:55 +0000
committerKa Ho Ng <khng@FreeBSD.org>2021-03-20 07:45:34 +0000
commitcf5d1112408ddef3fdff8212599727c49ba90fa4 (patch)
tree1db88a24fdf64890e7f8a1c8ffd01f831a7d39b6
parentfaf9a4e9142a02c289ee543a6091bd4b925c6a63 (diff)
virtio_pci_legacy: Allow memory space for configuration
For guests running under some kind of VMMs, configuration structure is available in memory space but not I/O space. Reported by: Yuan Rui <number201724@me.com> MFC after: 2 weeks Reviewed by: rpokala, bryanv, jhb Approved by: philip (mentor) Differential Revision: https://reviews.freebsd.org/D28818
-rw-r--r--sys/dev/virtio/pci/virtio_pci_legacy.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/dev/virtio/pci/virtio_pci_legacy.c b/sys/dev/virtio/pci/virtio_pci_legacy.c
index d74983099110..a17dd22aa953 100644
--- a/sys/dev/virtio/pci/virtio_pci_legacy.c
+++ b/sys/dev/virtio/pci/virtio_pci_legacy.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
struct vtpci_legacy_softc {
device_t vtpci_dev;
struct vtpci_common vtpci_common;
+ int vtpci_res_type;
struct resource *vtpci_res;
struct resource *vtpci_msix_table_res;
struct resource *vtpci_msix_pba_res;
@@ -231,7 +232,7 @@ vtpci_legacy_attach(device_t dev)
error = vtpci_legacy_alloc_resources(sc);
if (error) {
- device_printf(dev, "cannot map I/O space\n");
+ device_printf(dev, "cannot map I/O space nor memory space\n");
return (error);
}
@@ -601,14 +602,25 @@ vtpci_legacy_teardown_msix(struct vtpci_legacy_softc *sc)
static int
vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *sc)
{
+ const int res_types[] = { SYS_RES_IOPORT, SYS_RES_MEMORY };
device_t dev;
- int rid;
+ int rid, i;
dev = sc->vtpci_dev;
- rid = PCIR_BAR(0);
- if ((sc->vtpci_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
- &rid, RF_ACTIVE)) == NULL)
+ /*
+ * Most hypervisors export the common configuration structure in IO
+ * space, but some use memory space; try both.
+ */
+ for (i = 0; nitems(res_types); i++) {
+ rid = PCIR_BAR(0);
+ sc->vtpci_res_type = res_types[i];
+ sc->vtpci_res = bus_alloc_resource_any(dev, res_types[i], &rid,
+ RF_ACTIVE);
+ if (sc->vtpci_res != NULL)
+ break;
+ }
+ if (sc->vtpci_res == NULL)
return (ENXIO);
return (0);
@@ -622,7 +634,7 @@ vtpci_legacy_free_resources(struct vtpci_legacy_softc *sc)
dev = sc->vtpci_dev;
if (sc->vtpci_res != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0),
+ bus_release_resource(dev, sc->vtpci_res_type, PCIR_BAR(0),
sc->vtpci_res);
sc->vtpci_res = NULL;
}