Skip to content

Commit

Permalink
net/virtio: fix descriptor addresses in 32-bit build
Browse files Browse the repository at this point in the history
[ upstream commit 8c41645be010ec7fa0df4f6c3790b167945154b4 ]

With Virtio-user, the Virtio descriptor buffer address is the
virtual address of the mbuf's buffer. On 32-bit builds, it is
expected to be 32 bits.

With Virtio-PCI, the Virtio descriptor buffer address is the
physical address of the mbuf's buffer. On 32-bit builds running
on 64-bit kernel, it is expected to be up to 64 bits.

This patch introduces a new mask field in virtqueue's struct to
filter our the upper 4 bytes of the address only when necessary.
An optimization is introduced for 64-bit builds to remove the
masking, as the address is always 64 bits wide.

Fixes: ba55c94 ("net/virtio: revert forcing IOVA as VA mode for virtio-user")

Reported-by: Sampath Peechu <[email protected]>
Signed-off-by: Maxime Coquelin <[email protected]>
Reviewed-by: David Marchand <[email protected]>
Signed-off-by: Maxime Coquelin <[email protected]>
  • Loading branch information
mcoquelin authored and kevintraynor committed Nov 23, 2023
1 parent 93f0406 commit 9b63dd4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 6 deletions.
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,7 @@ Salem Sol <[email protected]>
Sameh Gobriel <[email protected]>
Sam Grove <[email protected]>
Samik Gupta <[email protected]>
Sampath Peechu <[email protected]>
Samuel Gauthier <[email protected]>
Sangjin Han <[email protected]>
Sankar Chokkalingam <[email protected]>
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/virtio/virtio_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,13 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t queue_idx)
hw->cvq = cvq;
}

if (hw->use_va)
if (hw->use_va) {
vq->mbuf_addr_offset = offsetof(struct rte_mbuf, buf_addr);
else
vq->mbuf_addr_mask = UINTPTR_MAX;
} else {
vq->mbuf_addr_offset = offsetof(struct rte_mbuf, buf_iova);
vq->mbuf_addr_mask = UINT64_MAX;
}

if (queue_type == VTNET_TQ) {
struct virtio_tx_region *txr;
Expand Down
18 changes: 14 additions & 4 deletions drivers/net/virtio/virtqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,26 @@ virtqueue_store_flags_packed(struct vring_packed_desc *dp,

#define VIRTQUEUE_MAX_NAME_SZ 32

#ifdef RTE_ARCH_32
#define VIRTIO_MBUF_ADDR_MASK(vq) ((vq)->mbuf_addr_mask)
#else
#define VIRTIO_MBUF_ADDR_MASK(vq) UINT64_MAX
#endif

/**
* Return the IOVA (or virtual address in case of virtio-user) of mbuf
* data buffer.
*
* The address is firstly casted to the word size (sizeof(uintptr_t))
* before casting it to uint64_t. This is to make it work with different
* combination of word size (64 bit and 32 bit) and virtio device
* (virtio-pci and virtio-user).
* before casting it to uint64_t. It is then masked with the expected
* address length (64 bits for virtio-pci, word size for virtio-user).
*
* This is to make it work with different combination of word size (64
* bit and 32 bit) and virtio device (virtio-pci and virtio-user).
*/
#define VIRTIO_MBUF_ADDR(mb, vq) \
((uint64_t)(*(uintptr_t *)((uintptr_t)(mb) + (vq)->mbuf_addr_offset)))
((*(uint64_t *)((uintptr_t)(mb) + (vq)->mbuf_addr_offset)) & \
VIRTIO_MBUF_ADDR_MASK(vq))

/**
* Return the physical address (or virtual address in case of
Expand Down Expand Up @@ -297,6 +306,7 @@ struct virtqueue {
void *vq_ring_virt_mem; /**< linear address of vring*/
unsigned int vq_ring_size;
uint16_t mbuf_addr_offset;
uint64_t mbuf_addr_mask;

union {
struct virtnet_rx rxq;
Expand Down

0 comments on commit 9b63dd4

Please sign in to comment.