Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_net.c
Show First 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
#define VTNET_MAXSEGS 256 | #define VTNET_MAXSEGS 256 | ||||
#define VTNET_MAX_PKT_LEN (65536 + 64) | #define VTNET_MAX_PKT_LEN (65536 + 64) | ||||
#define VTNET_MIN_MTU ETHERMIN | #define VTNET_MIN_MTU ETHERMIN | ||||
#define VTNET_MAX_MTU 65535 | #define VTNET_MAX_MTU 65535 | ||||
#define VTNET_S_HOSTCAPS \ | #define VTNET_S_HOSTCAPS_LEGACY \ | ||||
( VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | \ | ( VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | \ | ||||
VIRTIO_F_NOTIFY_ON_EMPTY | VIRTIO_RING_F_INDIRECT_DESC) | VIRTIO_F_NOTIFY_ON_EMPTY | VIRTIO_RING_F_INDIRECT_DESC) | ||||
#define VTNET_S_HOSTCAPS_MODERN \ | |||||
( VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | \ | |||||
VIRTIO_RING_F_INDIRECT_DESC) | |||||
/* | /* | ||||
* PCI config-space "registers" | * PCI config-space "registers" | ||||
*/ | */ | ||||
struct virtio_net_config { | struct virtio_net_config { | ||||
uint8_t mac[6]; | uint8_t mac[6]; | ||||
uint16_t status; | uint16_t status; | ||||
uint16_t max_virtqueue_pairs; | uint16_t max_virtqueue_pairs; | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | static struct virtio_consts vtnet_vi_consts = { | ||||
"vtnet", /* our name */ | "vtnet", /* our name */ | ||||
VTNET_MAXQ - 1, /* we currently support 2 virtqueues */ | VTNET_MAXQ - 1, /* we currently support 2 virtqueues */ | ||||
sizeof(struct virtio_net_config), /* config reg size */ | sizeof(struct virtio_net_config), /* config reg size */ | ||||
pci_vtnet_reset, /* reset */ | pci_vtnet_reset, /* reset */ | ||||
NULL, /* device-wide qnotify -- not used */ | NULL, /* device-wide qnotify -- not used */ | ||||
pci_vtnet_cfgread, /* read PCI config */ | pci_vtnet_cfgread, /* read PCI config */ | ||||
pci_vtnet_cfgwrite, /* write PCI config */ | pci_vtnet_cfgwrite, /* write PCI config */ | ||||
pci_vtnet_neg_features, /* apply negotiated features */ | pci_vtnet_neg_features, /* apply negotiated features */ | ||||
VTNET_S_HOSTCAPS, /* our capabilities */ | VTNET_S_HOSTCAPS_LEGACY, /* our capabilities (legacy) */ | ||||
VTNET_S_HOSTCAPS_MODERN, /* our capabilities (modern) */ | |||||
true, /* Enable legacy */ | |||||
true, /* Enable modern */ | |||||
2, /* PCI BAR# for modern */ | |||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
pci_vtnet_pause, /* pause rx/tx threads */ | pci_vtnet_pause, /* pause rx/tx threads */ | ||||
pci_vtnet_resume, /* resume rx/tx threads */ | pci_vtnet_resume, /* resume rx/tx threads */ | ||||
pci_vtnet_snapshot, /* save / restore device state */ | pci_vtnet_snapshot, /* save / restore device state */ | ||||
#endif | #endif | ||||
}; | }; | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | if (value != NULL) { | ||||
} | } | ||||
if (mtu < VTNET_MIN_MTU || mtu > VTNET_MAX_MTU) { | if (mtu < VTNET_MIN_MTU || mtu > VTNET_MAX_MTU) { | ||||
err = EINVAL; | err = EINVAL; | ||||
errno = EINVAL; | errno = EINVAL; | ||||
free(sc); | free(sc); | ||||
return (err); | return (err); | ||||
} | } | ||||
sc->vsc_consts.vc_hv_caps |= VIRTIO_NET_F_MTU; | sc->vsc_consts.vc_hv_caps_legacy |= VIRTIO_NET_F_MTU; | ||||
sc->vsc_consts.vc_hv_caps_modern |= VIRTIO_NET_F_MTU; | |||||
} | } | ||||
sc->vsc_config.mtu = mtu; | sc->vsc_config.mtu = mtu; | ||||
/* Permit interfaces without a configured backend. */ | /* Permit interfaces without a configured backend. */ | ||||
if (get_config_value_node(nvl, "backend") != NULL) { | if (get_config_value_node(nvl, "backend") != NULL) { | ||||
err = netbe_init(&sc->vsc_be, nvl, pci_vtnet_rx_callback, sc); | err = netbe_init(&sc->vsc_be, nvl, pci_vtnet_rx_callback, sc); | ||||
if (err) { | if (err) { | ||||
free(sc); | free(sc); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | } | ||||
sc->vsc_consts.vc_hv_caps |= VIRTIO_NET_F_MRG_RXBUF | | sc->vsc_consts.vc_hv_caps_legacy |= VIRTIO_NET_F_MRG_RXBUF | | ||||
netbe_get_cap(sc->vsc_be); | netbe_get_cap(sc->vsc_be); | ||||
sc->vsc_consts.vc_hv_caps_modern |= VIRTIO_NET_F_MRG_RXBUF | | |||||
netbe_get_cap(sc->vsc_be); | |||||
/* | /* | ||||
* Since we do not actually support multiqueue, | * Since we do not actually support multiqueue, | ||||
* set the maximum virtqueue pairs to 1. | * set the maximum virtqueue pairs to 1. | ||||
*/ | */ | ||||
sc->vsc_config.max_virtqueue_pairs = 1; | sc->vsc_config.max_virtqueue_pairs = 1; | ||||
/* initialize config space */ | /* initialize config space */ | ||||
pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET); | pci_set_cfgdata16(pi, PCIR_DEVICE, sc->vsc_consts.vc_en_legacy ? | ||||
VIRTIO_DEV_NET : vi_get_modern_pci_devid(VIRTIO_ID_NETWORK)); | |||||
pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); | pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); | ||||
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); | pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); | ||||
pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_ID_NETWORK); | pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_ID_NETWORK); | ||||
pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); | pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); | ||||
/* Link is always up. */ | /* Link is always up. */ | ||||
sc->vsc_config.status = 1; | sc->vsc_config.status = 1; | ||||
vi_softc_linkup(&sc->vsc_vs, &sc->vsc_consts, sc, pi, sc->vsc_queues); | vi_softc_linkup(&sc->vsc_vs, &sc->vsc_consts, sc, pi, sc->vsc_queues); | ||||
sc->vsc_vs.vs_mtx = &sc->vsc_mtx; | sc->vsc_vs.vs_mtx = &sc->vsc_mtx; | ||||
/* use BAR 1 to map MSI-X table and PBA, if we're using MSI-X */ | /* use BAR 1 to map MSI-X table and PBA, if we're using MSI-X */ | ||||
if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix())) { | if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix())) { | ||||
free(sc); | free(sc); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* use BAR 0 to map config regs in IO space */ | /* Virtio-legacy: use BAR 0 to map config regs in IO space */ | ||||
vi_set_io_bar(&sc->vsc_vs, 0); | vi_setup_pci_bar(&sc->vsc_vs); | ||||
sc->resetting = 0; | sc->resetting = 0; | ||||
sc->rx_merge = 0; | sc->rx_merge = 0; | ||||
sc->vhdrlen = sizeof(struct virtio_net_rxhdr) - 2; | sc->vhdrlen = sizeof(struct virtio_net_rxhdr) - 2; | ||||
pthread_mutex_init(&sc->rx_mtx, NULL); | pthread_mutex_init(&sc->rx_mtx, NULL); | ||||
/* | /* | ||||
Show All 20 Lines | pci_vtnet_cfgwrite(void *vsc, int offset, int size, uint32_t value) | ||||
if (offset < (int)sizeof(sc->vsc_config.mac)) { | if (offset < (int)sizeof(sc->vsc_config.mac)) { | ||||
assert(offset + size <= (int)sizeof(sc->vsc_config.mac)); | assert(offset + size <= (int)sizeof(sc->vsc_config.mac)); | ||||
/* | /* | ||||
* The driver is allowed to change the MAC address | * The driver is allowed to change the MAC address | ||||
*/ | */ | ||||
ptr = &sc->vsc_config.mac[offset]; | ptr = &sc->vsc_config.mac[offset]; | ||||
memcpy(ptr, &value, size); | memcpy(ptr, &value, size); | ||||
vq_devcfg_changed(&sc->vsc_vs); | |||||
} else { | } else { | ||||
/* silently ignore other writes */ | /* silently ignore other writes */ | ||||
DPRINTF(("vtnet: write to readonly reg %d", offset)); | DPRINTF(("vtnet: write to readonly reg %d", offset)); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | done: | ||||
return (ret); | return (ret); | ||||
} | } | ||||
#endif | #endif | ||||
static struct pci_devemu pci_de_vnet = { | static struct pci_devemu pci_de_vnet = { | ||||
.pe_emu = "virtio-net", | .pe_emu = "virtio-net", | ||||
.pe_init = pci_vtnet_init, | .pe_init = pci_vtnet_init, | ||||
.pe_legacy_config = netbe_legacy_config, | .pe_legacy_config = netbe_legacy_config, | ||||
.pe_cfgwrite = vi_pci_cfgwrite, | |||||
.pe_cfgread = vi_pci_cfgread, | |||||
.pe_barwrite = vi_pci_write, | .pe_barwrite = vi_pci_write, | ||||
.pe_barread = vi_pci_read, | .pe_barread = vi_pci_read, | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
.pe_snapshot = vi_pci_snapshot, | .pe_snapshot = vi_pci_snapshot, | ||||
.pe_pause = vi_pci_pause, | .pe_pause = vi_pci_pause, | ||||
.pe_resume = vi_pci_resume, | .pe_resume = vi_pci_resume, | ||||
#endif | #endif | ||||
}; | }; | ||||
PCI_EMUL_SET(pci_de_vnet); | PCI_EMUL_SET(pci_de_vnet); |