diff options
| author | Patrick Mooney <pmooney@pfmooney.com> | 2018-01-03 21:11:35 +0000 |
|---|---|---|
| committer | Patrick Mooney <pmooney@pfmooney.com> | 2018-02-28 18:42:18 +0000 |
| commit | 887132348b2882cd572106fe2dede45955e3a623 (patch) | |
| tree | a49b5f4ba88d51aa9ae2cddc7d3646e3303fa2eb /usr/src/cmd | |
| parent | 9c1f0b4865ff20abeb270b5e73b7372aa4f49fea (diff) | |
| download | illumos-joyent-887132348b2882cd572106fe2dede45955e3a623.tar.gz | |
OS-6681 modernize viona driver
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Mike Gerdts <mike.gerdts@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/cmd')
| -rw-r--r-- | usr/src/cmd/bhyve/Makefile.com | 1 | ||||
| -rw-r--r-- | usr/src/cmd/bhyve/pci_emul.c | 5 | ||||
| -rw-r--r-- | usr/src/cmd/bhyve/pci_emul.h | 7 | ||||
| -rw-r--r-- | usr/src/cmd/bhyve/pci_virtio_viona.c | 472 | ||||
| -rw-r--r-- | usr/src/cmd/devfsadm/i386/misc_link_i386.c | 6 |
5 files changed, 312 insertions, 179 deletions
diff --git a/usr/src/cmd/bhyve/Makefile.com b/usr/src/cmd/bhyve/Makefile.com index b80bf910de..b9ad3fde70 100644 --- a/usr/src/cmd/bhyve/Makefile.com +++ b/usr/src/cmd/bhyve/Makefile.com @@ -42,6 +42,7 @@ SRCS = acpi.c \ pci_virtio_block.c \ pci_virtio_net.c \ pci_virtio_rnd.c \ + pci_virtio_viona.c \ pci_xhci.c \ pm.c \ post.c \ diff --git a/usr/src/cmd/bhyve/pci_emul.c b/usr/src/cmd/bhyve/pci_emul.c index 101773b4e5..d48af9521b 100644 --- a/usr/src/cmd/bhyve/pci_emul.c +++ b/usr/src/cmd/bhyve/pci_emul.c @@ -1580,6 +1580,11 @@ pci_lintr_update(struct pci_devinst *pi) pci_irq_assert(pi); } pthread_mutex_unlock(&pi->pi_lintr.lock); +#ifndef __FreeBSD__ + if (pi->pi_d->pe_lintrupdate != NULL) { + pi->pi_d->pe_lintrupdate(pi); + } +#endif /* __FreeBSD__ */ } int diff --git a/usr/src/cmd/bhyve/pci_emul.h b/usr/src/cmd/bhyve/pci_emul.h index 0fffb19dee..a0aaa425be 100644 --- a/usr/src/cmd/bhyve/pci_emul.h +++ b/usr/src/cmd/bhyve/pci_emul.h @@ -25,6 +25,9 @@ * * $FreeBSD$ */ +/* + * Copyright 2018 Joyent, Inc. + */ #ifndef _PCI_EMUL_H_ #define _PCI_EMUL_H_ @@ -69,6 +72,10 @@ struct pci_devemu { uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size); + +#ifndef __FreeBSD__ + void (*pe_lintrupdate)(struct pci_devinst *pi); +#endif /* __FreeBSD__ */ }; #define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x); diff --git a/usr/src/cmd/bhyve/pci_virtio_viona.c b/usr/src/cmd/bhyve/pci_virtio_viona.c index e5a5cb584f..1c4b739711 100644 --- a/usr/src/cmd/bhyve/pci_virtio_viona.c +++ b/usr/src/cmd/bhyve/pci_virtio_viona.c @@ -34,7 +34,7 @@ * http://www.illumos.org/license/CDDL. * * Copyright 2015 Pluribus Networks Inc. - * Copyright 2017 Joyent, Inc. + * Copyright 2018 Joyent, Inc. */ #include <sys/cdefs.h> @@ -85,18 +85,6 @@ #define VIONA_REGSZ VIONA_R_MAX+1 /* - * Host capabilities - */ -#define VIRTIO_NET_F_MAC (1 << 5) /* host supplies MAC */ -#define VIRTIO_NET_F_MRG_RXBUF (1 << 15) /* host can merge RX buffers */ -#define VIRTIO_NET_F_STATUS (1 << 16) /* config status field available */ - -#define VIONA_S_HOSTCAPS \ - (VIRTIO_NET_F_MAC | \ - VIRTIO_NET_F_MRG_RXBUF | \ - VIRTIO_NET_F_STATUS) - -/* * Queue definitions. */ #define VIONA_RXQ 0 @@ -108,7 +96,7 @@ /* * Debug printf */ -static int pci_viona_debug; +static volatile int pci_viona_debug; #define DPRINTF(params) if (pci_viona_debug) printf params #define WPRINTF(params) printf params @@ -124,26 +112,20 @@ struct pci_viona_softc { int vsc_isr; datalink_id_t vsc_linkid; - char vsc_linkname[MAXLINKNAMELEN]; int vsc_vnafd; + /* Configurable parameters */ + char vsc_linkname[MAXLINKNAMELEN]; + uint32_t vsc_feature_mask; + uint16_t vsc_vq_size; + uint32_t vsc_features; uint8_t vsc_macaddr[6]; uint64_t vsc_pfn[VIONA_MAXQ]; uint16_t vsc_msix_table_idx[VIONA_MAXQ]; - /* - * Flag to see if host is already sending data out. - * If it is, no need to wait for lock and send interrupt to host - * for new data. - */ - boolean_t vsc_tx_kick_lock_held; - - pthread_t tx_tid; - pthread_mutex_t tx_mtx; - pthread_cond_t tx_cond; + boolean_t vsc_msix_active; }; -#define viona_ctx(sc) ((sc)->vsc_pi->pi_vmctx) /* * Return the size of IO BAR that maps virtio header and device specific @@ -160,15 +142,14 @@ pci_viona_iosize(struct pci_devinst *pi) } static uint16_t -pci_viona_qsize(int qnum) +pci_viona_qsize(struct pci_viona_softc *sc, int qnum) { /* XXX no ctl queue currently */ if (qnum == VIONA_CTLQ) { return (0); } - /* XXX fixed currently. Maybe different for tx/rx/ctl */ - return (VIONA_RINGSZ); + return (sc->vsc_vq_size); } static void @@ -180,21 +161,13 @@ pci_viona_ring_reset(struct pci_viona_softc *sc, int ring) switch (ring) { case VIONA_RXQ: - error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_RESET); - if (error != 0) { - WPRINTF(("ioctl viona rx ring reset failed %d\n", - error)); - } else { - sc->vsc_pfn[VIONA_RXQ] = 0; - } - break; case VIONA_TXQ: - error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_RESET); + error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_RESET, ring); if (error != 0) { - WPRINTF(("ioctl viona tx ring reset failed %d\n", - error)); + WPRINTF(("ioctl viona ring %u reset failed %d\n", + ring, errno)); } else { - sc->vsc_pfn[VIONA_TXQ] = 0; + sc->vsc_pfn[ring] = 0; } break; case VIONA_CTLQ: @@ -220,11 +193,11 @@ static void * pci_viona_poll_thread(void *param) { struct pci_viona_softc *sc = param; - pollfd_t pollset; - int error; + pollfd_t pollset; + const int fd = sc->vsc_vnafd; - pollset.fd = sc->vsc_vnafd; - pollset.events = POLLIN | POLLOUT; + pollset.fd = fd; + pollset.events = POLLRDBAND; for (;;) { if (poll(&pollset, 1, -1) < 0) { @@ -236,23 +209,35 @@ pci_viona_poll_thread(void *param) break; } } - if (pollset.revents & POLLIN) { - pci_generate_msix(sc->vsc_pi, - sc->vsc_msix_table_idx[VIONA_RXQ]); - error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_INTR_CLR); - if (error != 0) { - WPRINTF(("ioctl viona rx intr clear failed" - " %d\n", error)); + if (pollset.revents & POLLRDBAND) { + vioc_intr_poll_t vip; + uint_t i; + int res; + boolean_t assert_lintr = B_FALSE; + const boolean_t do_msix = pci_msix_enabled(sc->vsc_pi); + + res = ioctl(fd, VNA_IOC_INTR_POLL, &vip); + for (i = 0; res > 0 && i < VIONA_VQ_MAX; i++) { + if (vip.vip_status[i] == 0) { + continue; + } + if (do_msix) { + pci_generate_msix(sc->vsc_pi, + sc->vsc_msix_table_idx[i]); + } else { + assert_lintr = B_TRUE; + } + res = ioctl(fd, VNA_IOC_RING_INTR_CLR, i); + if (res != 0) { + WPRINTF(("ioctl viona vq %d intr " + "clear failed %d\n", i, errno)); + } } - } - - if (pollset.revents & POLLOUT) { - pci_generate_msix(sc->vsc_pi, - sc->vsc_msix_table_idx[VIONA_TXQ]); - error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_INTR_CLR); - if (error != 0) { - WPRINTF(("ioctl viona tx intr clear failed" - " %d\n", error)); + if (assert_lintr) { + pthread_mutex_lock(&sc->vsc_mtx); + sc->vsc_isr |= VTCFG_ISR_QUEUES; + pci_lintr_assert(sc->vsc_pi); + pthread_mutex_unlock(&sc->vsc_mtx); } } } @@ -261,57 +246,6 @@ pci_viona_poll_thread(void *param) } static void -pci_viona_ping_rxq(struct pci_viona_softc *sc) -{ - int error; - - error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_KICK); - if (error != 0) { - WPRINTF(("ioctl viona rx ring kick failed %d\n", error)); - } -} - -static void * -pci_viona_tx_thread(void *param) -{ - struct pci_viona_softc *sc = (struct pci_viona_softc *)param; - int error; - - pthread_mutex_lock(&sc->tx_mtx); - for (;;) { - error = pthread_cond_wait(&sc->tx_cond, &sc->tx_mtx); - assert(error == 0); - sc->vsc_tx_kick_lock_held = B_TRUE; - error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_KICK); - if (error != 0) { - WPRINTF(("ioctl viona tx ring kick failed %d\n", - error)); - } - sc->vsc_tx_kick_lock_held = B_FALSE; - } - pthread_mutex_unlock(&sc->tx_mtx); - - return (NULL); -} - -static void -pci_viona_ping_txq(struct pci_viona_softc *sc) -{ - /* Signal the tx thread for processing */ - if (sc->vsc_tx_kick_lock_held) - return; - pthread_mutex_lock(&sc->tx_mtx); - pthread_cond_signal(&sc->tx_cond); - pthread_mutex_unlock(&sc->tx_mtx); -} - -static void -pci_viona_ping_ctlq(struct pci_viona_softc *sc) -{ - DPRINTF(("viona: control qnotify!\n\r")); -} - -static void pci_viona_ring_init(struct pci_viona_softc *sc, uint64_t pfn) { int qnum = sc->vsc_curq; @@ -320,29 +254,19 @@ pci_viona_ring_init(struct pci_viona_softc *sc, uint64_t pfn) assert(qnum < VIONA_MAXQ); + if (qnum == VIONA_CTLQ) { + return; + } + sc->vsc_pfn[qnum] = (pfn << VRING_PFN); - vna_ri.ri_qsize = pci_viona_qsize(qnum); + vna_ri.ri_index = qnum; + vna_ri.ri_qsize = pci_viona_qsize(sc, qnum); vna_ri.ri_qaddr = (pfn << VRING_PFN); + error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_INIT, &vna_ri); - switch (qnum) { - case VIONA_RXQ: - error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_INIT, &vna_ri); - if (error != 0) { - WPRINTF(("ioctl viona rx ring init failed %d\n", - error)); - } - break; - case VIONA_TXQ: - error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_INIT, &vna_ri); - if (error != 0) { - WPRINTF(("ioctl viona tx ring init failed %d\n", - error)); - } - break; - case VIONA_CTLQ: - default: - break; + if (error != 0) { + WPRINTF(("ioctl viona ring %u init failed %d\n", qnum, errno)); } } @@ -350,30 +274,20 @@ static int pci_viona_viona_init(struct vmctx *ctx, struct pci_viona_softc *sc) { vioc_create_t vna_create; -#if notyet - char devname[MAXNAMELEN]; - int ctlfd; -#endif int error; - sc->vsc_vnafd = open("/devices/pseudo/viona@0:ctl", O_RDWR | O_EXCL); + sc->vsc_vnafd = open("/dev/viona", O_RDWR | O_EXCL); if (sc->vsc_vnafd == -1) { - WPRINTF(("open viona ctl failed\n")); + WPRINTF(("open viona ctl failed: %d\n", errno)); return (-1); } vna_create.c_linkid = sc->vsc_linkid; - strlcpy(vna_create.c_vmname, vmname, - sizeof (vna_create.c_vmname)); -#if notyet - vm_get_memory_seg(ctx, 1 * (1024 * 1024UL), &vna_create.c_lomem_size, - NULL); - vm_get_memory_seg(ctx, 4 * (1024 * 1024 * 1024UL), - &vna_create.c_himem_size, NULL); -#endif + vna_create.c_vmfd = vm_get_device_fd(ctx); error = ioctl(sc->vsc_vnafd, VNA_IOC_CREATE, &vna_create); if (error != 0) { - WPRINTF(("ioctl viona create failed %d\n", error)); + (void) close(sc->vsc_vnafd); + WPRINTF(("ioctl viona create failed %d\n", errno)); return (-1); } @@ -381,15 +295,99 @@ 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) +{ + char *next, *cp, *vnic = NULL; + int err = 0; + + sc->vsc_vq_size = VIONA_RINGSZ; + sc->vsc_feature_mask = 0; + + for (; opts != NULL && *opts != '\0'; opts = next) { + char *val; + + if ((cp = strchr(opts, ',')) != NULL) { + *cp = '\0'; + next = cp + 1; + } else { + next = NULL; + } + + 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; + } + + /* <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 { + fprintf(stderr, + "viona: unrecognized option '%s'", opts); + err = -1; + } + } + if (vnic == NULL) { + fprintf(stderr, "viona: vnic name required"); + sc->vsc_linkname[0] = '\0'; + err = -1; + } else { + (void) strlcpy(sc->vsc_linkname, vnic, MAXLINKNAMELEN); + } + + DPRINTF(("viona=%p dev=%s vqsize=%x feature_mask=%x\n", sc, + sc->vsc_linkname, sc->vsc_vq_size, sc->vsc_feature_mask)); + return (err); +} + +static int pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) { dladm_handle_t handle; dladm_status_t status; dladm_vnic_attr_t attr; char errmsg[DLADM_STRSIZE]; - int error; + int error, i; struct pci_viona_softc *sc; - int i; + uint64_t ioport; if (opts == NULL) { printf("virtio-viona: vnic required\n"); @@ -404,7 +402,10 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) pthread_mutex_init(&sc->vsc_mtx, NULL); - strlcpy(sc->vsc_linkname, opts, MAXLINKNAMELEN); + if (pci_viona_parse_opts(sc, opts) != 0) { + free(sc); + return (1); + } if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) { WPRINTF(("could not open /dev/dld")); @@ -430,7 +431,6 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) return (1); } - sc->vsc_tx_kick_lock_held = B_FALSE; memcpy(sc->vsc_macaddr, attr.va_mac_addr, ETHERADDRL); dladm_close(handle); @@ -449,42 +449,44 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 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_SUBVEND_0, VIRTIO_VENDOR); /* MSI-X support */ for (i = 0; i < VIONA_MAXQ; i++) sc->vsc_msix_table_idx[i] = VIRTIO_MSI_NO_VECTOR; - /* - * BAR 1 used to map MSI-X table and PBA - */ + /* BAR 1 used to map MSI-X table and PBA */ if (pci_emul_add_msixcap(pi, VIONA_MAXQ, 1)) { free(sc); return (1); } - pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VIONA_REGSZ); + /* BAR 0 for legacy-style virtio register access. */ + error = pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VIONA_REGSZ); + if (error != NULL) { + WPRINTF(("could not allocate virtio BAR\n")); + free(sc); + return (1); + } + + /* Install ioport hook for virtqueue notification */ + ioport = pi->pi_bar[0].addr + VTCFG_R_QNOTIFY; + error = ioctl(sc->vsc_vnafd, VNA_IOC_SET_NOTIFY_IOP, ioport); + if (error != 0) { + WPRINTF(("could not install ioport hook at %x\n", ioport)); + free(sc); + return (1); + } /* - * Initialize tx semaphore & spawn TX processing thread - * As of now, only one thread for TX desc processing is - * spawned. + * Need a legacy interrupt for virtio compliance, even though MSI-X + * operation is _strongly_ suggested for adequate performance. */ - pthread_mutex_init(&sc->tx_mtx, NULL); - pthread_cond_init(&sc->tx_cond, NULL); - pthread_create(&sc->tx_tid, NULL, pci_viona_tx_thread, (void *)sc); + pci_lintr_request(pi); return (0); } -/* - * Function pointer array to handle queue notifications - */ -static void (*pci_viona_qnotify[VIONA_MAXQ])(struct pci_viona_softc *) = { - pci_viona_ping_rxq, - pci_viona_ping_txq, - pci_viona_ping_ctlq -}; - static uint64_t viona_adjust_offset(struct pci_devinst *pi, uint64_t offset) { @@ -501,6 +503,109 @@ viona_adjust_offset(struct pci_devinst *pi, uint64_t offset) } static void +pci_viona_ring_set_msix(struct pci_devinst *pi, uint_t ring) +{ + struct pci_viona_softc *sc = pi->pi_arg; + struct msix_table_entry mte; + uint16_t tab_index; + vioc_ring_msi_t vrm; + int res; + + assert(ring <= VIONA_VQ_TX); + + vrm.rm_index = ring; + vrm.rm_addr = 0; + vrm.rm_msg = 0; + tab_index = sc->vsc_msix_table_idx[ring]; + + if (tab_index != VIRTIO_MSI_NO_VECTOR && sc->vsc_msix_active) { + mte = pi->pi_msix.table[tab_index]; + if ((mte.vector_control & PCIM_MSIX_VCTRL_MASK) == 0) { + vrm.rm_addr = mte.addr; + vrm.rm_msg = mte.msg_data; + } + } + + res = ioctl(sc->vsc_vnafd, VNA_IOC_RING_SET_MSI, &vrm); + if (res != 0) { + WPRINTF(("ioctl viona set_msi %d failed %d\n", ring, errno)); + } +} + +static void +pci_viona_lintrupdate(struct pci_devinst *pi) +{ + struct pci_viona_softc *sc = pi->pi_arg; + boolean_t msix_on = B_FALSE; + + pthread_mutex_lock(&sc->vsc_mtx); + msix_on = pci_msix_enabled(pi) && (pi->pi_msix.function_mask == 0); + if ((sc->vsc_msix_active && !msix_on) || + (msix_on && !sc->vsc_msix_active)) { + uint_t i; + + sc->vsc_msix_active = msix_on; + /* Update in-kernel ring configs */ + for (i = 0; i <= VIONA_VQ_TX; i++) { + pci_viona_ring_set_msix(pi, i); + } + } + pthread_mutex_unlock(&sc->vsc_mtx); +} + +static void +pci_viona_msix_update(struct pci_devinst *pi, uint64_t offset) +{ + struct pci_viona_softc *sc = pi->pi_arg; + uint_t tab_index, i; + + pthread_mutex_lock(&sc->vsc_mtx); + if (!sc->vsc_msix_active) { + pthread_mutex_unlock(&sc->vsc_mtx); + return; + } + + /* + * Rather than update every possible MSI-X vector, cheat and use the + * offset to calculate the entry within the table. Since this should + * only be called when a write to the table succeeds, the index should + * be valid. + */ + tab_index = offset / MSIX_TABLE_ENTRY_SIZE; + + for (i = 0; i <= VIONA_VQ_TX; i++) { + if (sc->vsc_msix_table_idx[i] != tab_index) { + continue; + } + pci_viona_ring_set_msix(pi, i); + } + + pthread_mutex_unlock(&sc->vsc_mtx); +} + +static void +pci_viona_qnotify(struct pci_viona_softc *sc, int ring) +{ + int error; + + switch (ring) { + case VIONA_TXQ: + case VIONA_RXQ: + error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_KICK, ring); + if (error != 0) { + WPRINTF(("ioctl viona ring %d kick failed %d\n", + ring, errno)); + } + break; + case VIONA_CTLQ: + DPRINTF(("viona: control qnotify!\n")); + break; + default: + break; + } +} + +static void pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value) { @@ -510,7 +615,9 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, if (baridx == pci_msix_table_bar(pi) || baridx == pci_msix_pba_bar(pi)) { - pci_emul_msix_twrite(pi, offset, size, value); + if (pci_emul_msix_twrite(pi, offset, size, value) == 0) { + pci_viona_msix_update(pi, offset); + } return; } @@ -529,10 +636,14 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, switch (offset) { case VTCFG_R_GUESTCAP: assert(size == 4); + value &= ~(sc->vsc_feature_mask); err = ioctl(sc->vsc_vnafd, VNA_IOC_SET_FEATURES, &value); - if (err != 0) + if (err != 0) { WPRINTF(("ioctl feature negotiation returned" - " err = %d\n", err)); + " err = %d\n", errno)); + } else { + sc->vsc_features = value; + } break; case VTCFG_R_PFN: assert(size == 4); @@ -546,7 +657,7 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, case VTCFG_R_QNOTIFY: assert(size == 2); assert(value < VIONA_MAXQ); - (*pci_viona_qnotify[value])(sc); + pci_viona_qnotify(sc, value); break; case VTCFG_R_STATUS: assert(size == 1); @@ -597,7 +708,7 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, pthread_mutex_unlock(&sc->vsc_mtx); } -uint64_t +static uint64_t pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size) { @@ -627,9 +738,11 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, case VTCFG_R_HOSTCAP: assert(size == 4); err = ioctl(sc->vsc_vnafd, VNA_IOC_GET_FEATURES, &value); - if (err != 0) + if (err != 0) { WPRINTF(("ioctl get host features returned" - " err = %d\n", err)); + " err = %d\n", errno)); + } + value &= ~sc->vsc_feature_mask; break; case VTCFG_R_GUESTCAP: assert(size == 4); @@ -641,7 +754,7 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, break; case VTCFG_R_QNUM: assert(size == 2); - value = pci_viona_qsize(sc->vsc_curq); + value = pci_viona_qsize(sc, sc->vsc_curq); break; case VTCFG_R_QSEL: assert(size == 2); @@ -705,9 +818,10 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, } struct pci_devemu pci_de_viona = { - .pe_emu = "virtio-net-viona", + .pe_emu = "virtio-net-viona", .pe_init = pci_viona_init, .pe_barwrite = pci_viona_write, - .pe_barread = pci_viona_read + .pe_barread = pci_viona_read, + .pe_lintrupdate = pci_viona_lintrupdate }; PCI_EMUL_SET(pci_de_viona); diff --git a/usr/src/cmd/devfsadm/i386/misc_link_i386.c b/usr/src/cmd/devfsadm/i386/misc_link_i386.c index f1a6ef1172..99085a3d4f 100644 --- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c +++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c @@ -84,6 +84,9 @@ static devfsadm_create_t misc_cbt[] = { { "pseudo", "ddi_pseudo", "ucode", TYPE_EXACT | DRV_EXACT, ILEVEL_0, ln_minor_name, }, + { "pseudo", "ddi_pseudo", "viona", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, ln_minor_name, + } }; DEVFSADM_CREATE_INIT_V0(misc_cbt); @@ -109,6 +112,9 @@ static devfsadm_remove_t misc_remove_cbt[] = { }, { "serial", "^tty[a-z]$", RM_ALWAYS | RM_PRE, ILEVEL_1, devfsadm_rm_all + }, + { "pseudo", "^viona$", RM_ALWAYS | RM_PRE | RM_HOT, + ILEVEL_0, devfsadm_rm_all } }; |
