The introduce of virtio 1.0 support brings yet another set of ops, badly, it's not handled correctly, that it breaks the multiple process support.
The issue is the function pointer may vary from different processes, and the current code just does one time set (for primary process only). That said, the function pointer the secondary process saw is actually from the primary process space. Accessing it could likely result to a crash. The fix is somehow straightforward (at least, way more simpler than what I have firstly thought): just reset the function pointers for the secondary process on init stage. Fixes: d5bbeefca826 ("virtio: introduce PCI implementation structure") Cc: sta...@dpdk.org Reported-by: Yaron Illouz <yar...@radcom.com> Signed-off-by: Yuanhan Liu <yuanhan....@linux.intel.com> --- drivers/net/virtio/virtio_ethdev.c | 12 ++++++++++++ drivers/net/virtio/virtio_pci.c | 4 ++-- drivers/net/virtio/virtio_pci.h | 4 ++++ drivers/net/virtio/virtio_user_ethdev.c | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index f2a803b..a9f7ae4 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1174,6 +1174,17 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, } static void +set_vtpci_ops(struct rte_eth_dev *eth_dev, struct virtio_hw *hw) +{ + if (eth_dev->pci_dev == NULL) + hw->vtpci_ops = &virtio_user_ops; + else if (hw->modern) + hw->vtpci_ops = &modern_ops; + else + hw->vtpci_ops = &legacy_ops; +} + +static void rx_func_get(struct rte_eth_dev *eth_dev) { struct virtio_hw *hw = eth_dev->data->dev_private; @@ -1313,6 +1324,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, if (!hw) return 1; + set_vtpci_ops(eth_dev, hw); rx_func_get(eth_dev); return 0; } diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c index 9b47165..e9e53a5 100644 --- a/drivers/net/virtio/virtio_pci.c +++ b/drivers/net/virtio/virtio_pci.c @@ -300,7 +300,7 @@ return 0; } -static const struct virtio_pci_ops legacy_ops = { +const struct virtio_pci_ops legacy_ops = { .read_dev_cfg = legacy_read_dev_config, .write_dev_cfg = legacy_write_dev_config, .reset = legacy_reset, @@ -516,7 +516,7 @@ io_write16(1, vq->notify_addr); } -static const struct virtio_pci_ops modern_ops = { +const struct virtio_pci_ops modern_ops = { .read_dev_cfg = modern_read_dev_config, .write_dev_cfg = modern_write_dev_config, .reset = modern_reset, diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h index de271bf..3e1e911 100644 --- a/drivers/net/virtio/virtio_pci.h +++ b/drivers/net/virtio/virtio_pci.h @@ -317,4 +317,8 @@ int vtpci_init(struct rte_pci_device *, struct virtio_hw *, uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); +extern const struct virtio_pci_ops legacy_ops; +extern const struct virtio_pci_ops modern_ops; +extern const struct virtio_pci_ops virtio_user_ops; + #endif /* _VIRTIO_PCI_H_ */ diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 406beea..26eca37 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -212,7 +212,7 @@ strerror(errno)); } -static const struct virtio_pci_ops virtio_user_ops = { +const struct virtio_pci_ops virtio_user_ops = { .read_dev_cfg = virtio_user_read_dev_config, .write_dev_cfg = virtio_user_write_dev_config, .reset = virtio_user_reset, -- 1.9.0