Skip to content

Commit

Permalink
vdpa/sfc: add support for mcdi IOVA remap
Browse files Browse the repository at this point in the history
vDPA driver allocates a MCDI buffer and maps it for DMA in the IO address
space of the virtual function, and the virtio-net driver independently
allocates virtqueues and uses their corresponding guest IOVA(s). There is
no guarantee that the values for these two addresses will be unique and
vDPA might need to relocate mcdi IOVA.

To resolves the problem of overlap between IOVA(s) allocated by vDPA and
qemu, three changes have been made to the vDPA driver.

1) Cache all known IOVA(s) in a linked list and add functions
   to check overlap and resolve IOVA opverlaps.
2) Check for overlap
3) If overlap is found, find a new IOVA and invoke efx_mcdi_dma_remap

Signed-off-by: Abhimanyu Saini <[email protected]>
  • Loading branch information
Abhimanyu Saini committed Jul 17, 2022
1 parent 0acecd1 commit c957571
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 18 deletions.
14 changes: 13 additions & 1 deletion drivers/vdpa/sfc/sfc_vdpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
#define SFC_VDPA_DEFAULT_MCDI_IOVA 0x200000000000
#define SFC_SW_VRING_IOVA 0x300000000000

/*
* Ensure a gap of at least 0x1000 between the new and existing
* IOVA allocations. The gap is not strictly necessary and has
* been added just to space out the different IOVA allocations
*/
#define SFC_VDPA_IOVA_REMAP_OFFSET 0x1000

/* Broadcast & Unicast MAC filters are supported */
#define SFC_MAX_SUPPORTED_FILTERS 3

Expand Down Expand Up @@ -62,6 +69,7 @@ struct sfc_vdpa_adapter {
efsys_bar_t mem_bar;

struct sfc_efx_mcdi mcdi;
uint64_t mcdi_iova;
size_t mcdi_buff_size;

uint32_t max_queue_count;
Expand Down Expand Up @@ -102,11 +110,15 @@ int
sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
size_t len, efsys_mem_t *esmp);

int
sfc_vdpa_dma_remap(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp);

void
sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp);

int
sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *vdpa_data, bool do_map);
sfc_vdpa_dma_map_vhost_mem_table(struct sfc_vdpa_ops_data *vdpa_data,
bool do_map);

int
sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data *ops_data);
Expand Down
61 changes: 47 additions & 14 deletions drivers/vdpa/sfc/sfc_vdpa_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,

sfc_vdpa_log_init(sva, "name=%s, len=%zu", mz_name, len);

mcdi_iova = SFC_VDPA_DEFAULT_MCDI_IOVA;
mz = rte_memzone_reserve_aligned(mz_name, mcdi_buff_size,
numa_node,
RTE_MEMZONE_IOVA_CONTIG,
Expand All @@ -52,19 +53,6 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
return -ENOMEM;
}

/* IOVA address for MCDI would be re-calculated if mapping
* using default IOVA would fail.
* TODO: Earlier there was no way to get valid IOVA range.
* Recently a patch has been submitted to get the IOVA range
* using ioctl. VFIO_IOMMU_GET_INFO. This patch is available
* in the kernel version >= 5.4. Support to get the default
* IOVA address for MCDI buffer using available IOVA range
* would be added later. Meanwhile default IOVA for MCDI buffer
* is kept at high mem at 2TB. In case of overlap new available
* addresses would be searched and same would be used.
*/
mcdi_iova = SFC_VDPA_DEFAULT_MCDI_IOVA;

for (;;) {
ret = rte_vfio_container_dma_map(sva->vfio_container_fd,
(uint64_t)mz->addr, mcdi_iova,
Expand All @@ -84,6 +72,7 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,

esmp->esm_addr = mcdi_iova;
esmp->esm_base = mz->addr;
sva->mcdi_iova = mcdi_iova;
sva->mcdi_buff_size = mcdi_buff_size;

sfc_vdpa_info(sva,
Expand All @@ -93,6 +82,49 @@ sfc_vdpa_dma_alloc(struct sfc_vdpa_adapter *sva, const char *name,
return 0;
}

int
sfc_vdpa_dma_remap(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
{
int ret;

ret = rte_vfio_container_dma_unmap(sva->vfio_container_fd,
(uint64_t)esmp->esm_base,
esmp->esm_addr,
sva->mcdi_buff_size);
if (ret < 0) {
sfc_vdpa_err(sva,
"DMA unmap failed for virt=%p iova=0x%lx, len=%zu",
esmp->esm_base, esmp->esm_addr, sva->mcdi_buff_size
);
goto error;
}

ret = rte_vfio_container_dma_map(sva->vfio_container_fd,
(uint64_t)esmp->esm_base,
sva->mcdi_iova,
sva->mcdi_buff_size);

if (ret < 0) {
sfc_vdpa_err(sva,
"DMA map failed for virt=%p iova=0x%lx, len=%zu",
esmp->esm_base, esmp->esm_addr, sva->mcdi_buff_size
);
goto error;
}

esmp->esm_addr = sva->mcdi_iova;
sfc_vdpa_info(sva,
"DMA remapping for MCDI done, new IOVA: 0x%lx",
esmp->esm_addr);

return 0;

error:
sfc_vdpa_err(sva, "DMA remapping failed for MCDI : %s",
rte_strerror(rte_errno));
return ret;
}

void
sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
{
Expand All @@ -118,7 +150,8 @@ sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp)
}

int
sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *ops_data, bool do_map)
sfc_vdpa_dma_map_vhost_mem_table(struct sfc_vdpa_ops_data *ops_data,
bool do_map)
{
uint32_t i, j;
int rc;
Expand Down
10 changes: 10 additions & 0 deletions drivers/vdpa/sfc/sfc_vdpa_mcdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ sfc_vdpa_mcdi_dma_alloc(void *cookie, const char *name, size_t len,
return sfc_vdpa_dma_alloc(sva, name, len, esmp);
}

static sfc_efx_mcdi_dma_remap_cb sfc_vdpa_mcdi_dma_remap;
static int
sfc_vdpa_mcdi_dma_remap(void *cookie, efsys_mem_t *esmp)
{
struct sfc_vdpa_adapter *sva = cookie;

return sfc_vdpa_dma_remap(sva, esmp);
}

static sfc_efx_mcdi_dma_free_cb sfc_vdpa_mcdi_dma_free;
static void
sfc_vdpa_mcdi_dma_free(void *cookie, efsys_mem_t *esmp)
Expand All @@ -43,6 +52,7 @@ sfc_vdpa_mcdi_mgmt_evq_poll(void *cookie)

static const struct sfc_efx_mcdi_ops sfc_vdpa_mcdi_ops = {
.dma_alloc = sfc_vdpa_mcdi_dma_alloc,
.dma_remap = sfc_vdpa_mcdi_dma_remap,
.dma_free = sfc_vdpa_mcdi_dma_free,
.sched_restart = sfc_vdpa_mcdi_sched_restart,
.mgmt_evq_poll = sfc_vdpa_mcdi_mgmt_evq_poll,
Expand Down
Loading

0 comments on commit c957571

Please sign in to comment.