Skip to content

Commit

Permalink
iommu: add dmabuf helper
Browse files Browse the repository at this point in the history
Add iommu/dmabuf.h which helps allocating and mapping DMA buffers.

Signed-off-by: Klaus Jensen <[email protected]>
  • Loading branch information
birkelund committed Sep 6, 2024
1 parent d4c1f92 commit 6476e80
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 5 deletions.
84 changes: 84 additions & 0 deletions include/vfn/iommu/dmabuf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later or MIT */

/*
* This file is part of libvfn.
*
* Copyright (C) 2023 The libvfn Authors. All Rights Reserved.
*
* This library (libvfn) is dual licensed under the GNU Lesser General
* Public License version 2.1 or later or the MIT license. See the
* COPYING and LICENSE files for more information.
*/

#ifndef LIBVFN_IOMMU_DMABUF_H
#define LIBVFN_IOMMU_DMABUF_H

/**
* DOC: DMA-buffer helpers
*
* This provides a helper for allocating and mapping DMA buffers.
*
* &struct iommu_dmabuf is also registered as an "autovar" and can be
* automatically unmapped and deallocated when going out of scope. For this
* reason, this header is not included in <vfn/iommu.h> and must explicitly be
* included.
*
* Required includes:
* #include <vfn/iommu.h>
* #include <vfn/support/autoptr.h>
* #include <vfn/iommu/dmabuf.h>
*/


/**
* struct iommu_dmabuf - DMA buffer abstraction
* @ctx: &struct iommu_ctx
* @vaddr: data buffer
* @iova: mapped address
* @len: length of @vaddr
*
* Convenience wrapper around a mapped data buffer.
*/
struct iommu_dmabuf {
struct iommu_ctx *ctx;

void *vaddr;
uint64_t iova;
ssize_t len;
};

/**
* iommu_get_dmabuf - Allocate and map a DMA buffer
* @ctx: &struct iommu_ctx
* @buffer: uninitialized &struct iommu_dmabuf
* @len: desired minimum length
* @flags: combination of enum iommu_map_flags
*
* Allocate at least @len bytes and map the buffer within the IOVA address space
* described by @ctx. The actual allocated and mapped length may be larger than
* requestes due to alignment requirements.
*
* Return: On success, returns ``0``; on error, returns ``-1`` and sets
* ``errno``.
*/
int iommu_get_dmabuf(struct iommu_ctx *ctx, struct iommu_dmabuf *buffer, size_t len,
unsigned long flags);

/**
* iommu_put_dmabuf - Unmap and deallocate a DMA buffer
* @buffer: &struct iommu_dmabuf
*
* Unmap the buffer and deallocate it.
*/
void iommu_put_dmabuf(struct iommu_dmabuf *buffer);

static inline void __do_iommu_put_dmabuf(void *p)
{
struct iommu_dmabuf *buffer = (struct iommu_dmabuf *)p;

iommu_put_dmabuf(buffer);
}

DEFINE_AUTOVAR_STRUCT(iommu_dmabuf, __do_iommu_put_dmabuf);

#endif /* LIBVFN_IOMMU_DMABUF_H */
40 changes: 35 additions & 5 deletions include/vfn/support/autoptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
#define LIBVFN_SUPPORT_AUTOPTR_H

/**
* DOC: glib-style auto pointer
* DOC: glib-style automatic cleanup.
*
* The __autoptr() provides a general way of "cleaning up" when going out of
* scope. Inspired by glib, but simplified a lot (at the expence of
* flexibility).
* The __autoptr() and __autovar_s() provides a general way of "cleaning up"
* when going out of scope. Inspired by glib, but simplified a lot (at the
* expence of flexibility).
*/

#define __AUTOPTR_CLEANUP(t) __autoptr_cleanup_##t
Expand All @@ -27,7 +27,7 @@
/**
* DEFINE_AUTOPTR - Defines the appropriate cleanup function for a pointer type
* @t: type name
* @cleanup: function to be called to cleanup type
* @cleanup: function to be called to clean up type
*
* Defines a function ``__autoptr_cleanup_##t`` that will call @cleanup when
* invoked.
Expand All @@ -51,4 +51,34 @@
*/
#define __autoptr(t) __attribute__((cleanup(__AUTOPTR_CLEANUP(t)))) __AUTOPTR_T(t)

#define __AUTOVAR_STRUCT_CLEANUP(t) __autovar_struct_cleanup_##t
#define __AUTOVAR_STRUCT_T(t) __autovar_struct_##t

/**
* DEFINE_AUTOVAR_STRUCT - Defines the appropriate cleanup function for a struct
* type
* @t: type name
* @cleanup: function to be called to clean up type
*
* Defines a function ``__autovar_struct_cleanup_##t`` that will call @cleanup
* when invoked.
*/
#define DEFINE_AUTOVAR_STRUCT(t, cleanup) \
typedef struct t __AUTOVAR_STRUCT_T(t); \
\
static inline void __AUTOVAR_STRUCT_CLEANUP(t) (struct t *p) \
{ \
(cleanup)(p); \
}

/**
* __autovar_s - Helper to declare a struct variable with automatic cleanup
* @t: type name
*
* Declares a struct-type variable that is cleaned up when the variable goes out
* of scope. How to clean up the type must have been previously declared using
* DEFINE_AUTOPTR().
*/
#define __autovar_s(t) __attribute__((cleanup(__AUTOVAR_STRUCT_CLEANUP(t)))) __AUTOVAR_STRUCT_T(t)

#endif /* LIBVFN_SUPPORT_AUTOPTR_H */
51 changes: 51 additions & 0 deletions src/iommu/dmabuf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: LGPL-2.1-or-later or MIT

/*
* This file is part of libvfn.
*
* Copyright (C) 2024 The libvfn Authors. All Rights Reserved.
*
* This library (libvfn) is dual licensed under the GNU Lesser General
* Public License version 2.1 or later or the MIT license. See the
* COPYING and LICENSE files for more information.
*/

#include <string.h>

#include <sys/types.h>

#include <vfn/iommu.h>

#include <vfn/support/autoptr.h>
#include <vfn/iommu/dmabuf.h>

#include <vfn/support.h>

int iommu_get_dmabuf(struct iommu_ctx *ctx, struct iommu_dmabuf *buffer, size_t len,
unsigned long flags)
{
buffer->ctx = ctx;

buffer->len = pgmap(&buffer->vaddr, len);
if (buffer->len < 0)
return -1;

if (iommu_map_vaddr(ctx, buffer->vaddr, buffer->len, &buffer->iova, flags)) {
pgunmap(buffer->vaddr, buffer->len);
return -1;
}

return 0;
}

void iommu_put_dmabuf(struct iommu_dmabuf *buffer)
{
if (!buffer->len)
return;

log_fatal_if(iommu_unmap_vaddr(buffer->ctx, buffer->vaddr, NULL), "iommu_unmap_vaddr");

pgunmap(buffer->vaddr, buffer->len);

memset(buffer, 0x0, sizeof(*buffer));
}
1 change: 1 addition & 0 deletions src/iommu/meson.build
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
iommu_sources = files(
'context.c',
'dma.c',
'dmabuf.c',
'vfio.c',
)

Expand Down

0 comments on commit 6476e80

Please sign in to comment.