Skip to content

Commit

Permalink
iommu: Add put_device_fd callback for vfio
Browse files Browse the repository at this point in the history
Application might open and close the vfio device file descriptors in an
alive session.  This patch added support for putting (closing) the open
file descriptors for vfio resources to unbind the vfio device
successfully.

Signed-off-by: Minwoo Im <[email protected]>
  • Loading branch information
minwooim authored and birkelund committed Aug 13, 2024
1 parent fd4ef71 commit 58a5b44
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 4 deletions.
11 changes: 11 additions & 0 deletions include/vfn/vfio/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ struct vfio_pci_device {
*/
int vfio_pci_open(struct vfio_pci_device *pci, const char *bdf);

/**
* vfio_pci_close - close vfio device file descriptor
* @pci: &struct vfio_pci_device whose fd is to close
*
* Close vfio group file descriptor
*
* Return: On success, returns ``0``. On error, returns ``-1`` and sets
* ``errno``.
*/
int vfio_pci_close(struct vfio_pci_device *pci);

/**
* vfio_pci_map_bar - map a vfio device region into virtual memory
* @pci: &struct vfio_pci_device
Expand Down
1 change: 1 addition & 0 deletions src/iommu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct iommu_ctx_ops {

/* device ops */
int (*get_device_fd)(struct iommu_ctx *ctx, const char *bdf);
int (*put_device_fd)(struct iommu_ctx *ctx, const char *bdf);
};

struct iova_mapping {
Expand Down
17 changes: 17 additions & 0 deletions src/iommu/iommufd.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "vfn/iommu.h"

#include "ccan/list/list.h"
#include "ccan/compiler/compiler.h"

#include "context.h"
#include "trace.h"
Expand All @@ -48,6 +49,7 @@ struct iommu_ioas {

char *name;
uint32_t id;
int devfd;
};

static struct iommu_ioas iommufd_default_ioas = {
Expand Down Expand Up @@ -147,6 +149,7 @@ static int iommufd_get_device_fd(struct iommu_ctx *ctx, const char *bdf)
goto close_dev;
}

ioas->devfd = devfd;
return devfd;

close_dev:
Expand All @@ -156,6 +159,19 @@ static int iommufd_get_device_fd(struct iommu_ctx *ctx, const char *bdf)
return -1;
}

static int iommufd_put_device_fd(struct iommu_ctx *ctx, const char *bdf UNUSED)
{
struct iommu_ioas *ioas = container_of_var(ctx, ioas, ctx);

if (ioas->devfd) {
close(ioas->devfd);
return 0;
}

errno = ENODEV;
return -1;
}

static int iommu_ioas_do_dma_map(struct iommu_ctx *ctx, void *vaddr, size_t len, uint64_t *iova,
unsigned long flags)
{
Expand Down Expand Up @@ -234,6 +250,7 @@ static int iommu_ioas_do_dma_unmap_all(struct iommu_ctx *ctx)

static const struct iommu_ctx_ops iommufd_ops = {
.get_device_fd = iommufd_get_device_fd,
.put_device_fd = iommufd_put_device_fd,

.dma_map = iommu_ioas_do_dma_map,
.dma_unmap = iommu_ioas_do_dma_unmap,
Expand Down
43 changes: 40 additions & 3 deletions src/iommu/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct vfio_group {
struct vfio_container *container;

char *path;
int nr_devs;
};

struct vfio_container {
Expand Down Expand Up @@ -363,8 +364,8 @@ static int vfio_get_group_fd(struct vfio_container *vfio,
* Returns an existing vfio_group instance, or an empty one with group->path
* filled out, otherwise return NULL in case no more group available.
*/
static struct vfio_group *vfio_get_group(struct vfio_container *vfio,
const char *bdf)
static struct vfio_group *__vfio_get_group(struct vfio_container *vfio,
const char *bdf, bool alloc)
{
__autofree char *path = NULL;
struct vfio_group *group;
Expand All @@ -383,6 +384,9 @@ static struct vfio_group *vfio_get_group(struct vfio_container *vfio,
return group;
}

if (!alloc)
return NULL;

/*
* If existing group is not found, provide an empty one for the
* correspnoding 'bdf' device.
Expand All @@ -391,20 +395,33 @@ static struct vfio_group *vfio_get_group(struct vfio_container *vfio,
group = &vfio->groups[i];
if (!group->path) {
group->path = strdup(path);
group->nr_devs = 0;
return group;
}
}

return NULL;
}

static struct vfio_group *vfio_get_or_create_group(struct vfio_container *vfio,
const char *bdf)
{
return __vfio_get_group(vfio, bdf, true);
}

static struct vfio_group *vfio_get_group(struct vfio_container *vfio,
const char *bdf)
{
return __vfio_get_group(vfio, bdf, false);
}

static int vfio_get_device_fd(struct iommu_ctx *ctx, const char *bdf)
{
struct vfio_container *vfio = container_of_var(ctx, vfio, ctx);
struct vfio_group *group;
int gfd, ret_fd;

group = vfio_get_group(vfio, bdf);
group = vfio_get_or_create_group(vfio, bdf);
if (!group) {
log_debug("could not determine iommu group for device %s\n", bdf);
errno = EMFILE;
Expand All @@ -422,9 +439,28 @@ static int vfio_get_device_fd(struct iommu_ctx *ctx, const char *bdf)
return -1;
}

atomic_inc(&group->nr_devs);
return ret_fd;
}

static int vfio_put_device_fd(struct iommu_ctx *ctx, const char *bdf)
{
struct vfio_container *vfio = container_of_var(ctx, vfio, ctx);
struct vfio_group *group;

group = vfio_get_group(vfio, bdf);
if (!group) {
log_debug("could not find iommu group for device %s\n", bdf);
errno = ENODEV;
return -1;
}

if (atomic_dec_fetch(&group->nr_devs) == 0)
close(group->fd);

return 0;
}

static int vfio_iommu_type1_do_dma_map(struct iommu_ctx *ctx, void *vaddr, size_t len,
uint64_t *iova, unsigned long flags)
{
Expand Down Expand Up @@ -525,6 +561,7 @@ static int vfio_iommu_type1_do_dma_unmap_all(struct iommu_ctx *ctx)

static const struct iommu_ctx_ops vfio_ops = {
.get_device_fd = vfio_get_device_fd,
.put_device_fd = vfio_put_device_fd,

.iova_reserve = vfio_iommu_type1_iova_reserve,
.iova_put_ephemeral = vfio_iommu_type1_iova_put_ephemeral,
Expand Down
2 changes: 1 addition & 1 deletion src/nvme/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,5 +681,5 @@ void nvme_close(struct nvme_ctrl *ctrl)
vfio_pci_unmap_bar(&ctrl->pci, 0, ctrl->regs, 0x1000, 0);
vfio_pci_unmap_bar(&ctrl->pci, 0, ctrl->doorbells, 0x1000, 0x1000);

//vfio_close(ctrl->pci.vfio);
vfio_pci_close(&ctrl->pci);
}
9 changes: 9 additions & 0 deletions src/vfio/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,12 @@ int vfio_pci_open(struct vfio_pci_device *pci, const char *bdf)

return 0;
}

int vfio_pci_close(struct vfio_pci_device *pci)
{
struct iommu_ctx *ctx = pci->dev.ctx;

close(pci->dev.fd);

return ctx->ops.put_device_fd(ctx, pci->bdf);
}

0 comments on commit 58a5b44

Please sign in to comment.