aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/CMakeLists.txt2
-rw-r--r--include/libvfio-user.h2
-rw-r--r--include/pci_defs.h (renamed from include/pci.h)8
-rw-r--r--lib/libvfio-user.c183
-rw-r--r--lib/pci.c143
-rw-r--r--lib/pci.h56
-rw-r--r--lib/private.h23
7 files changed, 217 insertions, 200 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 07c6836..c209d6c 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -36,5 +36,5 @@ install(FILES "pci_caps/msi.h" DESTINATION ${VFIO_USER_HEADERS_DIR}/pci_caps)
install(FILES "pci_caps/msix.h" DESTINATION ${VFIO_USER_HEADERS_DIR}/pci_caps)
install(FILES "pci_caps/pm.h" DESTINATION ${VFIO_USER_HEADERS_DIR}/pci_caps)
install(FILES "pci_caps/px.h" DESTINATION ${VFIO_USER_HEADERS_DIR}/pci_caps)
-install(FILES "pci.h" DESTINATION ${VFIO_USER_HEADERS_DIR})
+install(FILES "pci_defs.h" DESTINATION ${VFIO_USER_HEADERS_DIR})
install(FILES "vfio-user.h" DESTINATION ${VFIO_USER_HEADERS_DIR})
diff --git a/include/libvfio-user.h b/include/libvfio-user.h
index f92e0cd..75878c1 100644
--- a/include/libvfio-user.h
+++ b/include/libvfio-user.h
@@ -43,7 +43,7 @@
#include <unistd.h>
#include <syslog.h>
-#include "pci.h"
+#include "pci_defs.h"
#include "pci_caps/pm.h"
#include "pci_caps/px.h"
#include "pci_caps/msi.h"
diff --git a/include/pci.h b/include/pci_defs.h
index 112becf..5a77b65 100644
--- a/include/pci.h
+++ b/include/pci_defs.h
@@ -30,8 +30,8 @@
*
*/
-#ifndef LIBVFIO_USER_PCI_H
-#define LIBVFIO_USER_PCI_H
+#ifndef LIBVFIO_USER_PCI_DEFS_H
+#define LIBVFIO_USER_PCI_DEFS_H
#include <stdint.h>
#include <stdbool.h>
@@ -42,6 +42,8 @@ extern "C" {
#endif
/*
+ * PCI standard header definitions.
+ *
* TODO lots of the sizes of each member are defined in pci_regs.h, use those
* instead?
*/
@@ -194,6 +196,6 @@ _Static_assert(sizeof(vfu_pci_config_space_t) == 0x100,
}
#endif
-#endif /* LIBVFIO_USER_PCI_H */
+#endif /* LIBVFIO_USER_PCI_DEFS_H */
/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 599b17f..6d75e15 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -51,11 +51,12 @@
#include "cap.h"
#include "dma.h"
+#include "irq.h"
#include "libvfio-user.h"
+#include "migration.h"
+#include "pci.h"
#include "private.h"
#include "tran_sock.h"
-#include "migration.h"
-#include "irq.h"
void
vfu_log(vfu_ctx_t *vfu_ctx, int level, const char *fmt, ...)
@@ -77,13 +78,6 @@ vfu_log(vfu_ctx_t *vfu_ctx, int level, const char *fmt, ...)
errno = _errno;
}
-static inline int
-ERROR(int err)
-{
- errno = err;
- return -1;
-}
-
static size_t
get_vfio_caps_size(bool is_migr_reg, struct vfu_sparse_mmap_areas *m)
{
@@ -171,21 +165,6 @@ dev_get_caps(vfu_ctx_t *vfu_ctx, vfu_reg_info_t *vfu_reg, bool is_migr_reg,
return 0;
}
-#define VFU_REGION_SHIFT 40
-#define VFU_REGION_MASK ((1ULL << VFU_REGION_SHIFT) - 1)
-
-uint64_t
-region_to_offset(uint32_t region)
-{
- return (uint64_t)region << VFU_REGION_SHIFT;
-}
-
-uint32_t
-offset_to_region(uint64_t offset)
-{
- return (offset >> VFU_REGION_SHIFT) & VFU_REGION_MASK;
-}
-
#ifdef VFU_VERBOSE_LOGGING
void
dump_buffer(const char *prefix, const char *buf, uint32_t count)
@@ -293,47 +272,6 @@ vfu_get_region(loff_t pos, size_t count, loff_t *off)
return r;
}
-static uint32_t
-region_size(vfu_ctx_t *vfu_ctx, int region)
-{
- assert(region >= VFU_PCI_DEV_BAR0_REGION_IDX && region <= VFU_PCI_DEV_VGA_REGION_IDX);
- return vfu_ctx->reg_info[region].size;
-}
-
-static uint32_t
-pci_config_space_size(vfu_ctx_t *vfu_ctx)
-{
- return region_size(vfu_ctx, VFU_PCI_DEV_CFG_REGION_IDX);
-}
-
-/*
- * Accesses the non-standard part (offset >= 0x40) of the PCI configuration
- * space.
- */
-static ssize_t
-handle_pci_config_space_access(vfu_ctx_t *vfu_ctx, char *buf, size_t count,
- loff_t pos, bool is_write)
-{
- int ret;
-
- count = MIN(pci_config_space_size(vfu_ctx), count);
- if (is_write) {
- ret = cap_maybe_access(vfu_ctx, vfu_ctx->pci.caps, buf, count, pos);
- if (ret < 0) {
- vfu_log(vfu_ctx, LOG_ERR, "bad access to capabilities %#lx-%#lx\n",
- pos, pos + count);
- return ret;
- }
- } else {
- /*
- * It is legitimate to read the non-standard part of the PCI config
- * space even if there are no capabilities.
- */
- memcpy(buf, vfu_ctx->pci.config_space->raw + pos, count);
- }
- return count;
-}
-
static ssize_t
do_access(vfu_ctx_t *vfu_ctx, char *buf, uint8_t count, uint64_t pos, bool is_write)
{
@@ -356,8 +294,7 @@ do_access(vfu_ctx_t *vfu_ctx, char *buf, uint8_t count, uint64_t pos, bool is_wr
}
if (idx == VFU_PCI_DEV_CFG_REGION_IDX) {
- return handle_pci_config_space_access(vfu_ctx, buf, count, offset,
- is_write);
+ return pci_config_space_access(vfu_ctx, buf, count, offset, is_write);
}
if (is_migr_reg(vfu_ctx, idx)) {
@@ -465,18 +402,21 @@ vfu_access(vfu_ctx_t *vfu_ctx, bool is_write, char *rwbuf, uint32_t count,
#endif
_count = count;
- ret = vfu_pci_hdr_access(vfu_ctx, &_count, pos, is_write, rwbuf);
- if (ret != 0) {
- /* FIXME shouldn't we fail here? */
- vfu_log(vfu_ctx, LOG_ERR, "failed to access PCI header: %s",
- strerror(-ret));
+
+ if (pci_is_hdr_access(*pos)) {
+ ret = pci_hdr_access(vfu_ctx, &_count, pos, is_write, rwbuf);
+ if (ret != 0) {
+ /* FIXME shouldn't we fail here? */
+ vfu_log(vfu_ctx, LOG_ERR, "failed to access PCI header: %s",
+ strerror(-ret));
#ifdef VFU_VERBOSE_LOGGING
- dump_buffer("buffer write", rwbuf, _count);
+ dump_buffer("buffer write", rwbuf, _count);
#endif
+ }
}
/*
- * count is how much has been processed by vfu_pci_hdr_access,
+ * count is how much has been processed by pci_hdr_access,
* _count is how much there's left to be processed by vfu_access
*/
processed = count - _count;
@@ -1151,7 +1091,7 @@ vfu_realize_ctx(vfu_ctx_t *vfu_ctx)
cfg_reg->size = PCI_CFG_SPACE_SIZE;
}
- // This maybe allocated by vfu_setup_pci_config_hdr().
+ // This may have been allocated by vfu_setup_pci_config_hdr().
if (vfu_ctx->pci.config_space == NULL) {
vfu_ctx->pci.config_space = calloc(1, cfg_reg->size);
if (vfu_ctx->pci.config_space == NULL) {
@@ -1285,12 +1225,6 @@ vfu_attach_ctx(vfu_ctx_t *vfu_ctx)
return vfu_ctx->trans->attach(vfu_ctx);
}
-bool
-is_valid_pci_type(vfu_pci_type_t t)
-{
- return t >= VFU_PCI_TYPE_CONVENTIONAL && t <= VFU_PCI_TYPE_EXPRESS;
-}
-
vfu_ctx_t *
vfu_create_ctx(vfu_trans_t trans, const char *path, int flags, void *pvt,
vfu_dev_type_t dev_type)
@@ -1380,83 +1314,6 @@ vfu_setup_log(vfu_ctx_t *vfu_ctx, vfu_log_fn_t *log, int log_level)
return 0;
}
-int
-vfu_pci_setup_config_hdr(vfu_ctx_t *vfu_ctx, vfu_pci_hdr_id_t id,
- vfu_pci_hdr_ss_t ss, vfu_pci_hdr_cc_t cc,
- vfu_pci_type_t pci_type,
- int revision __attribute__((unused)))
-{
- vfu_pci_config_space_t *config_space;
- size_t size;
-
- assert(vfu_ctx != NULL);
-
- /*
- * TODO there no real reason why we shouldn't allow this, we should just
- * clean up and redo it.
- */
- if (vfu_ctx->pci.config_space != NULL) {
- vfu_log(vfu_ctx, LOG_ERR, "PCI configuration space header already setup");
- return ERROR(EEXIST);
- }
-
- vfu_ctx->pci.type = pci_type;
- switch (vfu_ctx->pci.type) {
- case VFU_PCI_TYPE_CONVENTIONAL:
- case VFU_PCI_TYPE_PCI_X_1:
- size = PCI_CFG_SPACE_SIZE;
- break;
- case VFU_PCI_TYPE_PCI_X_2:
- case VFU_PCI_TYPE_EXPRESS:
- size = PCI_CFG_SPACE_EXP_SIZE;
- break;
- default:
- vfu_log(vfu_ctx, LOG_ERR, "invalid PCI type %d", pci_type);
- return ERROR(EINVAL);
- }
-
- // Allocate a buffer for the config space.
- config_space = calloc(1, size);
- if (config_space == NULL) {
- return ERROR(ENOMEM);
- }
-
- config_space->hdr.id = id;
- config_space->hdr.ss = ss;
- config_space->hdr.cc = cc;
- vfu_ctx->pci.config_space = config_space;
- vfu_ctx->reg_info[VFU_PCI_DEV_CFG_REGION_IDX].size = size;
-
- return 0;
-}
-
-int
-vfu_pci_setup_caps(vfu_ctx_t *vfu_ctx, vfu_cap_t **caps, int nr_caps)
-{
- int ret;
-
- assert(vfu_ctx != NULL);
-
- if (vfu_ctx->pci.caps != NULL) {
- vfu_log(vfu_ctx, LOG_ERR, "capabilities are already setup");
- return ERROR(EEXIST);
- }
-
- if (caps == NULL || nr_caps == 0) {
- vfu_log(vfu_ctx, LOG_ERR, "Invalid args passed");
- return ERROR(EINVAL);
- }
-
- vfu_ctx->pci.caps = caps_create(vfu_ctx, caps, nr_caps, &ret);
- if (vfu_ctx->pci.caps == NULL) {
- vfu_log(vfu_ctx, LOG_ERR, "failed to create PCI capabilities: %s",
- strerror(ret));
- return ERROR(ret);
- }
-
- return 0;
-}
-
static int
copy_sparse_mmap_areas(vfu_reg_info_t *reg_info,
struct iovec *mmap_areas, uint32_t nr_mmap_areas)
@@ -1633,16 +1490,6 @@ vfu_setup_device_migration(vfu_ctx_t *vfu_ctx, vfu_migration_t *migration)
return 0;
}
-/*
- * Returns a pointer to the PCI configuration space.
- */
-inline vfu_pci_config_space_t *
-vfu_pci_get_config_space(vfu_ctx_t *vfu_ctx)
-{
- assert(vfu_ctx != NULL);
- return vfu_ctx->pci.config_space;
-}
-
inline vfu_reg_info_t *
vfu_get_region_info(vfu_ctx_t *vfu_ctx)
{
diff --git a/lib/pci.c b/lib/pci.c
index 105e31a..f28e7b0 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -30,22 +30,20 @@
*
*/
-#include <stdio.h>
#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
#include <string.h>
#include <sys/param.h>
-#include <errno.h>
-
-#include <linux/pci_regs.h>
-#include <linux/vfio.h>
+#include "cap.h"
#include "common.h"
#include "libvfio-user.h"
#include "pci.h"
#include "private.h"
static inline void
-vfu_pci_hdr_write_bar(vfu_ctx_t *vfu_ctx, uint16_t bar_index, const char *buf)
+pci_hdr_write_bar(vfu_ctx_t *vfu_ctx, uint16_t bar_index, const char *buf)
{
uint32_t cfg_addr;
unsigned long mask;
@@ -219,7 +217,7 @@ handle_erom_write(vfu_ctx_t *ctx, vfu_pci_config_space_t *pci,
}
static inline int
-vfu_pci_hdr_write(vfu_ctx_t *vfu_ctx, uint16_t offset,
+pci_hdr_write(vfu_ctx_t *vfu_ctx, uint16_t offset,
const char *buf, size_t count)
{
vfu_pci_config_space_t *pci;
@@ -255,7 +253,7 @@ vfu_pci_hdr_write(vfu_ctx_t *vfu_ctx, uint16_t offset,
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
- vfu_pci_hdr_write_bar(vfu_ctx, BAR_INDEX(offset), buf);
+ pci_hdr_write_bar(vfu_ctx, BAR_INDEX(offset), buf);
break;
case PCI_ROM_ADDRESS:
ret = handle_erom_write(vfu_ctx, pci, buf, count);
@@ -280,10 +278,9 @@ vfu_pci_hdr_write(vfu_ctx_t *vfu_ctx, uint16_t offset,
* @write: whether this is a PCI header write
* @count: output parameter that receives the number of bytes read/written
*/
-static inline int
-vfu_do_pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
- uint64_t *pos, bool is_write,
- char *buf)
+int
+pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
+ uint64_t *pos, bool is_write, char *buf)
{
uint32_t _count;
loff_t _pos;
@@ -298,7 +295,7 @@ vfu_do_pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
_count = MIN(*count, PCI_STD_HEADER_SIZEOF - _pos);
if (is_write) {
- err = vfu_pci_hdr_write(vfu_ctx, _pos, buf, _count);
+ err = pci_hdr_write(vfu_ctx, _pos, buf, _count);
} else {
memcpy(buf, vfu_pci_get_config_space(vfu_ctx)->hdr.raw + _pos, _count);
}
@@ -307,26 +304,122 @@ vfu_do_pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
return err;
}
-static inline bool
-vfu_is_pci_hdr_access(uint64_t pos)
+static uint32_t
+pci_config_space_size(vfu_ctx_t *vfu_ctx)
+{
+ return vfu_ctx->reg_info[VFU_PCI_DEV_CFG_REGION_IDX].size;
+}
+
+/*
+ * Accesses the non-standard part (offset >= 0x40) of the PCI configuration
+ * space.
+ */
+ssize_t
+pci_config_space_access(vfu_ctx_t *vfu_ctx, char *buf, size_t count,
+ loff_t pos, bool is_write)
{
- const uint64_t off = region_to_offset(VFU_PCI_DEV_CFG_REGION_IDX);
- return pos >= off && pos - off < PCI_STD_HEADER_SIZEOF;
+ int ret;
+
+ count = MIN(pci_config_space_size(vfu_ctx), count);
+ if (is_write) {
+ ret = cap_maybe_access(vfu_ctx, vfu_ctx->pci.caps, buf, count, pos);
+ if (ret < 0) {
+ vfu_log(vfu_ctx, LOG_ERR, "bad access to capabilities %#lx-%#lx\n",
+ pos, pos + count);
+ return ret;
+ }
+ } else {
+ /*
+ * It is legitimate to read the non-standard part of the PCI config
+ * space even if there are no capabilities.
+ */
+ memcpy(buf, vfu_ctx->pci.config_space->raw + pos, count);
+ }
+ return count;
}
-/* FIXME this function is misleading, remove it */
int
-vfu_pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
- uint64_t *pos, bool is_write, char *buf)
+vfu_pci_setup_config_hdr(vfu_ctx_t *vfu_ctx, vfu_pci_hdr_id_t id,
+ vfu_pci_hdr_ss_t ss, vfu_pci_hdr_cc_t cc,
+ vfu_pci_type_t pci_type,
+ int revision __attribute__((unused)))
{
+ vfu_pci_config_space_t *config_space;
+ size_t size;
+
assert(vfu_ctx != NULL);
- assert(count != NULL);
- assert(pos != NULL);
- if (!vfu_is_pci_hdr_access(*pos)) {
- return 0;
+ /*
+ * TODO there no real reason why we shouldn't allow this, we should just
+ * clean up and redo it.
+ */
+ if (vfu_ctx->pci.config_space != NULL) {
+ vfu_log(vfu_ctx, LOG_ERR, "PCI configuration space header already setup");
+ return ERROR(EEXIST);
+ }
+
+ vfu_ctx->pci.type = pci_type;
+ switch (vfu_ctx->pci.type) {
+ case VFU_PCI_TYPE_CONVENTIONAL:
+ case VFU_PCI_TYPE_PCI_X_1:
+ size = PCI_CFG_SPACE_SIZE;
+ break;
+ case VFU_PCI_TYPE_PCI_X_2:
+ case VFU_PCI_TYPE_EXPRESS:
+ size = PCI_CFG_SPACE_EXP_SIZE;
+ break;
+ default:
+ vfu_log(vfu_ctx, LOG_ERR, "invalid PCI type %d", pci_type);
+ return ERROR(EINVAL);
+ }
+
+ // Allocate a buffer for the config space.
+ config_space = calloc(1, size);
+ if (config_space == NULL) {
+ return ERROR(ENOMEM);
+ }
+
+ config_space->hdr.id = id;
+ config_space->hdr.ss = ss;
+ config_space->hdr.cc = cc;
+ vfu_ctx->pci.config_space = config_space;
+ vfu_ctx->reg_info[VFU_PCI_DEV_CFG_REGION_IDX].size = size;
+
+ return 0;
+}
+
+int
+vfu_pci_setup_caps(vfu_ctx_t *vfu_ctx, vfu_cap_t **caps, int nr_caps)
+{
+ int ret;
+
+ assert(vfu_ctx != NULL);
+
+ if (vfu_ctx->pci.caps != NULL) {
+ vfu_log(vfu_ctx, LOG_ERR, "capabilities are already setup");
+ return ERROR(EEXIST);
+ }
+
+ if (caps == NULL || nr_caps == 0) {
+ vfu_log(vfu_ctx, LOG_ERR, "Invalid args passed");
+ return ERROR(EINVAL);
+ }
+
+ vfu_ctx->pci.caps = caps_create(vfu_ctx, caps, nr_caps, &ret);
+ if (vfu_ctx->pci.caps == NULL) {
+ vfu_log(vfu_ctx, LOG_ERR, "failed to create PCI capabilities: %s",
+ strerror(ret));
+ return ERROR(ret);
}
- return vfu_do_pci_hdr_access(vfu_ctx, count, pos, is_write, buf);
+
+ return 0;
+}
+
+inline vfu_pci_config_space_t *
+vfu_pci_get_config_space(vfu_ctx_t *vfu_ctx)
+{
+ assert(vfu_ctx != NULL);
+ return vfu_ctx->pci.config_space;
}
/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/lib/pci.h b/lib/pci.h
new file mode 100644
index 0000000..8678902
--- /dev/null
+++ b/lib/pci.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 Nutanix Inc. All rights reserved.
+ *
+ * Authors: Thanos Makatos <thanos@nutanix.com>
+ * Swapnil Ingle <swapnil.ingle@nutanix.com>
+ * Felipe Franciosi <felipe@nutanix.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Nutanix nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ */
+
+#ifndef LIB_VFIO_USER_PCI_H
+#define LIB_VFIO_USER_PCI_H
+
+#include "libvfio-user.h"
+#include "private.h"
+
+static inline bool
+pci_is_hdr_access(uint64_t pos)
+{
+ const uint64_t off = region_to_offset(VFU_PCI_DEV_CFG_REGION_IDX);
+ return pos >= off && pos - off < PCI_STD_HEADER_SIZEOF;
+}
+
+int
+pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
+ uint64_t *pos, bool is_write, char *buf);
+
+ssize_t
+pci_config_space_access(vfu_ctx_t *vfu_ctx, char *buf, size_t count,
+ loff_t pos, bool is_write);
+
+#endif /* LIB_VFIO_USER_PCI_H */
+
+/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/lib/private.h b/lib/private.h
index 968271d..871ba29 100644
--- a/lib/private.h
+++ b/lib/private.h
@@ -35,6 +35,16 @@
#include "dma.h"
+#define VFU_REGION_SHIFT 40
+#define VFU_REGION_MASK ((1ULL << VFU_REGION_SHIFT) - 1)
+
+static inline int
+ERROR(int err)
+{
+ errno = err;
+ return -1;
+}
+
#ifdef VFU_VERBOSE_LOGGING
void
dump_buffer(const char *prefix, const char *buf, uint32_t count);
@@ -136,8 +146,17 @@ vfu_pci_hdr_access(vfu_ctx_t *vfu_ctx, uint32_t *count,
vfu_reg_info_t *
vfu_get_region_info(vfu_ctx_t *vfu_ctx);
-uint64_t
-region_to_offset(uint32_t region);
+static inline uint64_t
+region_to_offset(uint32_t region)
+{
+ return (uint64_t)region << VFU_REGION_SHIFT;
+}
+
+static inline uint32_t
+offset_to_region(uint64_t offset)
+{
+ return (offset >> VFU_REGION_SHIFT) & VFU_REGION_MASK;
+}
int
handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,