diff options
Diffstat (limited to 'usr/src/cmd/bhyve/pci_virtio_viona.c')
-rw-r--r-- | usr/src/cmd/bhyve/pci_virtio_viona.c | 194 |
1 files changed, 100 insertions, 94 deletions
diff --git a/usr/src/cmd/bhyve/pci_virtio_viona.c b/usr/src/cmd/bhyve/pci_virtio_viona.c index 9cafa7b111..07abf20512 100644 --- a/usr/src/cmd/bhyve/pci_virtio_viona.c +++ b/usr/src/cmd/bhyve/pci_virtio_viona.c @@ -64,6 +64,7 @@ #include <vmmapi.h> #include "bhyverun.h" +#include "config.h" #include "pci_emul.h" #include "virtio.h" @@ -135,10 +136,12 @@ struct pci_viona_softc { static uint64_t pci_viona_iosize(struct pci_devinst *pi) { - if (pci_msix_enabled(pi)) + if (pci_msix_enabled(pi)) { return (VIONA_REGSZ); - else - return (VIONA_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX)); + } else { + return (VIONA_REGSZ - + (VIRTIO_PCI_CONFIG_OFF(1) - VIRTIO_PCI_CONFIG_OFF(0))); + } } static uint16_t @@ -301,82 +304,80 @@ pci_viona_viona_init(struct vmctx *ctx, struct pci_viona_softc *sc) } static int -pci_viona_parse_opts(struct pci_viona_softc *sc, char *opts) +pci_viona_legacy_config(nvlist_t *nvl, const char *opt) { - char *next, *cp, *vnic = NULL; + char *config, *name, *tofree, *value; + + if (opt == NULL) + return (0); + + config = tofree = strdup(opt); + while ((name = strsep(&config, ",")) != NULL) { + value = strchr(name, '='); + if (value != NULL) { + *value++ = '\0'; + set_config_value_node(nvl, name, value); + } else { + set_config_value_node(nvl, "vnic", name); + } + } + free(tofree); + return (0); +} + +static int +pci_viona_parse_opts(struct pci_viona_softc *sc, nvlist_t *nvl) +{ + const char *value; int err = 0; sc->vsc_vq_size = VIONA_RINGSZ; sc->vsc_feature_mask = 0; + sc->vsc_linkname[0] = '\0'; - for (; opts != NULL && *opts != '\0'; opts = next) { - char *val; + value = get_config_value_node(nvl, "feature_mask"); + if (value != NULL) { + long num; - if ((cp = strchr(opts, ',')) != NULL) { - *cp = '\0'; - next = cp + 1; + errno = 0; + num = strtol(value, NULL, 0); + if (errno != 0 || num < 0) { + fprintf(stderr, + "viona: invalid mask '%s'", value); } else { - next = NULL; + sc->vsc_feature_mask = num; } + } - if ((cp = strchr(opts, '=')) == NULL) { - /* vnic chosen with bare name */ - if (vnic != NULL) { - fprintf(stderr, - "viona: unexpected vnic name '%s'", opts); - err = -1; - } else { - vnic = opts; - } - continue; - } + value = get_config_value_node(nvl, "vqsize"); + if (value != NULL) { + long num; - /* <param>=<value> handling */ - val = cp + 1; - *cp = '\0'; - if (strcmp(opts, "feature_mask") == 0) { - long num; - - errno = 0; - num = strtol(val, NULL, 0); - if (errno != 0 || num < 0) { - fprintf(stderr, - "viona: invalid mask '%s'", val); - } else { - sc->vsc_feature_mask = num; - } - } else if (strcmp(opts, "vqsize") == 0) { - long num; - - errno = 0; - num = strtol(val, NULL, 0); - if (errno != 0) { - fprintf(stderr, - "viona: invalid vsqize '%s'", val); - err = -1; - } else if (num <= 2 || num > 32768) { - fprintf(stderr, - "viona: vqsize out of range", num); - err = -1; - } else if ((1 << (ffs(num) - 1)) != num) { - fprintf(stderr, - "viona: vqsize must be power of 2", num); - err = -1; - } else { - sc->vsc_vq_size = num; - } - } else { + errno = 0; + num = strtol(value, NULL, 0); + if (errno != 0) { + fprintf(stderr, + "viona: invalid vsqize '%s'", value); + err = -1; + } else if (num <= 2 || num > 32768) { + fprintf(stderr, + "viona: vqsize out of range", num); + err = -1; + } else if ((1 << (ffs(num) - 1)) != num) { fprintf(stderr, - "viona: unrecognized option '%s'", opts); + "viona: vqsize must be power of 2", num); err = -1; + } else { + sc->vsc_vq_size = num; } } - if (vnic == NULL) { + + value = get_config_value_node(nvl, "vnic"); + if (value == NULL) { fprintf(stderr, "viona: vnic name required"); - sc->vsc_linkname[0] = '\0'; err = -1; } else { - (void) strlcpy(sc->vsc_linkname, vnic, MAXLINKNAMELEN); + (void) strlcpy(sc->vsc_linkname, value, MAXLINKNAMELEN); } DPRINTF(("viona=%p dev=%s vqsize=%x feature_mask=%x\n", sc, @@ -385,7 +386,7 @@ pci_viona_parse_opts(struct pci_viona_softc *sc, char *opts) } static int -pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) +pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) { dladm_handle_t handle; dladm_status_t status; @@ -394,8 +395,10 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) int error, i; struct pci_viona_softc *sc; uint64_t ioport; + const char *vnic; - if (opts == NULL) { + vnic = get_config_value_node(nvl, "vnic"); + if (vnic == NULL) { printf("virtio-viona: vnic required\n"); return (1); } @@ -408,7 +411,7 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) pthread_mutex_init(&sc->vsc_mtx, NULL); - if (pci_viona_parse_opts(sc, opts) != 0) { + if (pci_viona_parse_opts(sc, nvl) != 0) { free(sc); return (1); } @@ -419,18 +422,18 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) return (1); } - if (dladm_name2info(handle, sc->vsc_linkname, &sc->vsc_linkid, - NULL, NULL, NULL) != DLADM_STATUS_OK) { - WPRINTF(("dladm_name2info() for %s failed: %s\n", opts, + if ((status = dladm_name2info(handle, sc->vsc_linkname, &sc->vsc_linkid, + NULL, NULL, NULL)) != DLADM_STATUS_OK) { + WPRINTF(("dladm_name2info() for %s failed: %s\n", vnic, dladm_status2str(status, errmsg))); dladm_close(handle); free(sc); return (1); } - if (dladm_vnic_info(handle, sc->vsc_linkid, &attr, - DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { - WPRINTF(("dladm_vnic_info() for %s failed: %s\n", opts, + if ((status = dladm_vnic_info(handle, sc->vsc_linkid, &attr, + DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { + WPRINTF(("dladm_vnic_info() for %s failed: %s\n", vnic, dladm_status2str(status, errmsg))); dladm_close(handle); free(sc); @@ -454,7 +457,7 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET); pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); - pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET); + pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_ID_NETWORK); pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); /* MSI-X support */ @@ -476,7 +479,7 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) } /* Install ioport hook for virtqueue notification */ - ioport = pi->pi_bar[0].addr + VTCFG_R_QNOTIFY; + ioport = pi->pi_bar[0].addr + VIRTIO_PCI_QUEUE_NOTIFY; error = ioctl(sc->vsc_vnafd, VNA_IOC_SET_NOTIFY_IOP, ioport); if (error != 0) { WPRINTF(("could not install ioport hook at %x\n", ioport)); @@ -501,8 +504,10 @@ viona_adjust_offset(struct pci_devinst *pi, uint64_t offset) * whether MSI-X capability is enabled or not */ if (!pci_msix_enabled(pi)) { - if (offset >= VTCFG_R_MSIX) - return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX)); + if (offset >= VIRTIO_PCI_CONFIG_OFF(0)) { + return (offset + (VIRTIO_PCI_CONFIG_OFF(1) - + VIRTIO_PCI_CONFIG_OFF(0))); + } } return (offset); @@ -640,7 +645,7 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, offset = viona_adjust_offset(pi, offset); switch (offset) { - case VTCFG_R_GUESTCAP: + case VIRTIO_PCI_GUEST_FEATURES: assert(size == 4); value &= ~(sc->vsc_feature_mask); err = ioctl(sc->vsc_vnafd, VNA_IOC_SET_FEATURES, &value); @@ -651,29 +656,29 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, sc->vsc_features = value; } break; - case VTCFG_R_PFN: + case VIRTIO_PCI_QUEUE_PFN: assert(size == 4); pci_viona_ring_init(sc, value); break; - case VTCFG_R_QSEL: + case VIRTIO_PCI_QUEUE_SEL: assert(size == 2); assert(value < VIONA_MAXQ); sc->vsc_curq = value; break; - case VTCFG_R_QNOTIFY: + case VIRTIO_PCI_QUEUE_NOTIFY: assert(size == 2); assert(value < VIONA_MAXQ); pci_viona_qnotify(sc, value); break; - case VTCFG_R_STATUS: + case VIRTIO_PCI_STATUS: assert(size == 1); pci_viona_update_status(sc, value); break; - case VTCFG_R_CFGVEC: + case VIRTIO_MSI_CONFIG_VECTOR: assert(size == 2); sc->vsc_msix_table_idx[VIONA_CTLQ] = value; break; - case VTCFG_R_QVEC: + case VIRTIO_MSI_QUEUE_VECTOR: assert(size == 2); assert(sc->vsc_curq != VIONA_CTLQ); sc->vsc_msix_table_idx[sc->vsc_curq] = value; @@ -699,9 +704,9 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, *(uint32_t *)ptr = value; } break; - case VTCFG_R_HOSTCAP: - case VTCFG_R_QNUM: - case VTCFG_R_ISR: + case VIRTIO_PCI_HOST_FEATURES: + case VIRTIO_PCI_QUEUE_NUM: + case VIRTIO_PCI_ISR: case VIONA_R_CFG6: case VIONA_R_CFG7: DPRINTF(("viona: write to readonly reg %ld\n\r", offset)); @@ -742,7 +747,7 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, offset = viona_adjust_offset(pi, offset); switch (offset) { - case VTCFG_R_HOSTCAP: + case VIRTIO_PCI_HOST_FEATURES: assert(size == 4); err = ioctl(sc->vsc_vnafd, VNA_IOC_GET_FEATURES, &value); if (err != 0) { @@ -751,31 +756,31 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, } value &= ~sc->vsc_feature_mask; break; - case VTCFG_R_GUESTCAP: + case VIRTIO_PCI_GUEST_FEATURES: assert(size == 4); value = sc->vsc_features; /* XXX never read ? */ break; - case VTCFG_R_PFN: + case VIRTIO_PCI_QUEUE_PFN: assert(size == 4); value = sc->vsc_pfn[sc->vsc_curq] >> VRING_PFN; break; - case VTCFG_R_QNUM: + case VIRTIO_PCI_QUEUE_NUM: assert(size == 2); value = pci_viona_qsize(sc, sc->vsc_curq); break; - case VTCFG_R_QSEL: + case VIRTIO_PCI_QUEUE_SEL: assert(size == 2); value = sc->vsc_curq; /* XXX never read ? */ break; - case VTCFG_R_QNOTIFY: + case VIRTIO_PCI_QUEUE_NOTIFY: assert(size == 2); value = sc->vsc_curq; /* XXX never read ? */ break; - case VTCFG_R_STATUS: + case VIRTIO_PCI_STATUS: assert(size == 1); value = sc->vsc_status; break; - case VTCFG_R_ISR: + case VIRTIO_PCI_ISR: assert(size == 1); value = sc->vsc_isr; sc->vsc_isr = 0; /* a read clears this flag */ @@ -783,11 +788,11 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, pci_lintr_deassert(pi); } break; - case VTCFG_R_CFGVEC: + case VIRTIO_MSI_CONFIG_VECTOR: assert(size == 2); value = sc->vsc_msix_table_idx[VIONA_CTLQ]; break; - case VTCFG_R_QVEC: + case VIRTIO_MSI_QUEUE_VECTOR: assert(size == 2); assert(sc->vsc_curq != VIONA_CTLQ); value = sc->vsc_msix_table_idx[sc->vsc_curq]; @@ -830,6 +835,7 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, struct pci_devemu pci_de_viona = { .pe_emu = "virtio-net-viona", .pe_init = pci_viona_init, + .pe_legacy_config = pci_viona_legacy_config, .pe_barwrite = pci_viona_write, .pe_barread = pci_viona_read, .pe_lintrupdate = pci_viona_lintrupdate |