From d33f124c5b0335c0525187e820c6b42be0bae743 Mon Sep 17 00:00:00 2001 From: John Levon Date: Tue, 24 Nov 2020 15:22:18 +0000 Subject: clean up headers Introduce include/ dir for public headers, and clean up include guards etc. --- CMakeLists.txt | 10 +- include/CMakeLists.txt | 40 +++ include/muser.h | 611 +++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 212 ++++++++++++++++ include/pci_caps/common.h | 54 ++++ include/pci_caps/msi.h | 77 ++++++ include/pci_caps/msix.h | 78 ++++++ include/pci_caps/pm.h | 80 ++++++ include/pci_caps/px.h | 158 ++++++++++++ include/vfio_user.h | 181 ++++++++++++++ lib/CMakeLists.txt | 30 +-- lib/cap.h | 6 +- lib/caps/common.h | 46 ---- lib/caps/msi.h | 69 ----- lib/caps/msix.h | 70 ------ lib/caps/pm.h | 72 ------ lib/caps/px.h | 150 ----------- lib/common.h | 6 +- lib/dma.h | 6 +- lib/irq.h | 6 + lib/migration.h | 35 +-- lib/muser.h | 603 -------------------------------------------- lib/muser_priv.h | 12 +- lib/pci.h | 204 --------------- lib/tran_sock.h | 74 +++--- lib/vfio_user.h | 173 ------------- samples/client.c | 6 +- samples/gpio-pci-idio-16.c | 6 +- samples/null.c | 6 +- samples/server.c | 8 +- 30 files changed, 1604 insertions(+), 1485 deletions(-) create mode 100644 include/CMakeLists.txt create mode 100644 include/muser.h create mode 100644 include/pci.h create mode 100644 include/pci_caps/common.h create mode 100644 include/pci_caps/msi.h create mode 100644 include/pci_caps/msix.h create mode 100644 include/pci_caps/pm.h create mode 100644 include/pci_caps/px.h create mode 100644 include/vfio_user.h delete mode 100644 lib/caps/common.h delete mode 100644 lib/caps/msi.h delete mode 100644 lib/caps/msix.h delete mode 100644 lib/caps/pm.h delete mode 100644 lib/caps/px.h delete mode 100644 lib/muser.h delete mode 100644 lib/pci.h delete mode 100644 lib/vfio_user.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb23a7..04f15e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,10 @@ include(GNUInstallDirs) find_package(PkgConfig REQUIRED) pkg_check_modules(JSON REQUIRED json-c) +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/lib) +include_directories(${JSON_INCLUDE_DIRS}) + set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb") # # NB: this intentionally does not define NDEBUG: we want our assert()s even in a @@ -42,12 +46,10 @@ set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb") # set(CMAKE_C_FLAGS_RELEASE "-O3") -# -# "include_directories" does *not* work here. -# -include_directories(${JSON_INCLUDE_DIRS}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wextra") +# public headers +add_subdirectory(include) # shared libraries add_subdirectory(lib) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..3639be8 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# Copyright (c) 2019 Nutanix Inc. All rights reserved. +# +# Authors: Thanos Makatos +# Swapnil Ingle +# Felipe Franciosi +# +# 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 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. +# + +set(MUSER_HEADERS_DIR ${CMAKE_INSTALL_INCLUDEDIR}/muser) + +install(FILES "muser.h" DESTINATION ${MUSER_HEADERS_DIR}) +install(FILES "pci_caps/common.h" DESTINATION ${MUSER_HEADERS_DIR}/pci_caps) +install(FILES "pci_caps/msi.h" DESTINATION ${MUSER_HEADERS_DIR}/pci_caps) +install(FILES "pci_caps/msix.h" DESTINATION ${MUSER_HEADERS_DIR}/pci_caps) +install(FILES "pci_caps/pm.h" DESTINATION ${MUSER_HEADERS_DIR}/pci_caps) +install(FILES "pci_caps/px.h" DESTINATION ${MUSER_HEADERS_DIR}/pci_caps) +install(FILES "pci.h" DESTINATION ${MUSER_HEADERS_DIR}) +install(FILES "vfio_user.h" DESTINATION ${MUSER_HEADERS_DIR}) diff --git a/include/muser.h b/include/muser.h new file mode 100644 index 0000000..7c18490 --- /dev/null +++ b/include/muser.h @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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_MUSER_H +#define LIB_MUSER_H + +#include +#include +#include + +#include "pci.h" +#include "pci_caps/pm.h" +#include "pci_caps/px.h" +#include "pci_caps/msi.h" +#include "pci_caps/msix.h" +#include "vfio_user.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIB_MUSER_VFIO_USER_VERS_MJ 0 +#define LIB_MUSER_VFIO_USER_VERS_MN 1 + +typedef uint64_t dma_addr_t; + +typedef struct { + dma_addr_t dma_addr; + int region; + int length; + uint64_t offset; +} dma_sg_t; + +typedef struct lm_ctx lm_ctx_t; + +// Region flags. +#define LM_REG_FLAG_READ (1 << 0) +#define LM_REG_FLAG_WRITE (1 << 1) +#define LM_REG_FLAG_MMAP (1 << 2) // TODO: how this relates to IO bar? +#define LM_REG_FLAG_RW (LM_REG_FLAG_READ | LM_REG_FLAG_WRITE) +#define LM_REG_FLAG_MEM (1 << 3) // if unset, bar is IO + +struct lm_mmap_area { + uint64_t start; + uint64_t size; +}; + +struct lm_sparse_mmap_areas { + int nr_mmap_areas; + struct lm_mmap_area areas[]; +}; + +/** + * Prototype for region access callback. When a region is accessed, libmuser + * calls the previously registered callback with the following arguments: + * + * @pvt: private data originally set in dev_info + * @buf: buffer containing the data to be written or data to be read into + * @count: number of bytes being read or written + * @offset: byte offset within the region + * @is_write: whether or not this is a write + * + * @returns the number of bytes read or written, or a negative integer on error + */ +typedef ssize_t (lm_region_access_t) (void *pvt, char *buf, size_t count, + loff_t offset, bool is_write); + +/** + * Prototype for memory access callback. The program MUST first map device + * memory in its own virtual address space using lm_mmap, do any additional + * work required, and finally return that memory. When a region is memory + * mapped, libmuser calls previously register callback with the following + * arguments: + * + * @pvt: private data originally set in dev_info + * @off: offset of memory area being memory mapped + * @len: length of memory area being memory mapped + * + * @returns the memory address returned by lm_mmap, or MAP_FAILED on failure + */ +typedef unsigned long (lm_map_region_t) (void *pvt, unsigned long off, + unsigned long len); + +/** + * Creates a mapping of a device region into the caller's virtual memory. It + * must be called by lm_map_region_t. + * + * @lm_ctx: the libmuser context to create mapping from + * @offset: offset of the region being mapped + * @length: size of the region being mapped + * + * @returns a pointer to the requested memory or MAP_FAILED on error. Sets errno. + */ +void *lm_mmap(lm_ctx_t * lm_ctx, off_t offset, size_t length); + +typedef struct { + + /* + * Region flags, see LM_REG_FLAG_XXX above. + */ + uint32_t flags; + + /* + * Size of the region. + */ + uint32_t size; + + /* + * Callback function that is called when the region is read or written. + * Note that the memory of the region is owned by the user, except for the + * standard header (first 64 bytes) of the PCI configuration space. + */ + lm_region_access_t *fn; + + /* + * Callback function that is called when the region is memory mapped. + * Required if LM_REG_FLAG_MEM is set, otherwise ignored. + */ + lm_map_region_t *map; + struct lm_sparse_mmap_areas *mmap_areas; /* sparse mmap areas */ +} lm_reg_info_t; + +enum { + LM_DEV_INTX_IRQ_IDX, + LM_DEV_MSI_IRQ_IDX, + LM_DEV_MSIX_IRQ_IDX, + LM_DEV_ERR_IRQ_INDEX, + LM_DEV_REQ_IRQ_INDEX, + LM_DEV_NUM_IRQS +}; + +/* FIXME these are PCI regions */ +enum { + LM_DEV_BAR0_REG_IDX, + LM_DEV_BAR1_REG_IDX, + LM_DEV_BAR2_REG_IDX, + LM_DEV_BAR3_REG_IDX, + LM_DEV_BAR4_REG_IDX, + LM_DEV_BAR5_REG_IDX, + LM_DEV_ROM_REG_IDX, + LM_DEV_CFG_REG_IDX, + LM_DEV_VGA_REG_IDX, + LM_DEV_NUM_REGS, /* TODO rename to LM_DEV_NUM_PCI_REGS */ +}; + +typedef struct { + uint32_t irq_count[LM_DEV_NUM_IRQS]; + + /* + * Per-region information. Only supported regions need to be defined, + * unsupported regions should be left to 0. + */ + lm_reg_info_t reg_info[LM_DEV_NUM_REGS]; + + /* + * Device and vendor ID. + */ + lm_pci_hdr_id_t id; + + /* + * Subsystem vendor and device ID. + */ + lm_pci_hdr_ss_t ss; + + /* + * Class code. + */ + lm_pci_hdr_cc_t cc; +} lm_pci_info_t; + +/* + * Returns a pointer to the standard part of the PCI configuration space. + */ +lm_pci_config_space_t *lm_get_pci_config_space(lm_ctx_t *lm_ctx); + +#define LM_DMA_REGIONS 0x10 + +typedef enum { + LM_ERR, + LM_INF, + LM_DBG +} lm_log_lvl_t; + +/** + * Callback function signature for log function + * + * @lm_log_fn_t: typedef for log function. + */ +typedef void (lm_log_fn_t) (void *pvt, lm_log_lvl_t lvl, const char *msg); + +/** + * Callback function that gets called when a capability is accessed. The + * callback is not called when the ID and next fields are accessed, these are + * handled by the library. + * + * @pvt: private pointer + * @id: capability ID being accessed + * @buf: pointer to data being read or written + * @count: number of bytes being read or written + * @offset: offset within the capability + * @is_write: whether the capability is read or written + * + * @returns the number of bytes read or written + */ +typedef ssize_t (lm_cap_access_t) (void *pvt, uint8_t id, + char *buf, size_t count, + loff_t offset, bool is_write); + +/* FIXME does it have to be packed as well? */ +typedef union { + struct msicap msi; + struct msixcap msix; + struct pmcap pm; + struct pxcap px; +} lm_cap_t; + +typedef enum { + LM_TRANS_SOCK, + LM_TRANS_MAX +} lm_trans_t; + +#define LM_MAX_CAPS (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF + +/* + * FIXME the names of migration callback functions are probably far too long, + * but for now it helps with the implementation. + */ +typedef int (lm_migration_callback_t)(void *pvt); + +typedef enum { + LM_MIGR_STATE_STOP, + LM_MIGR_STATE_RUNNING, + LM_MIGR_STATE_STOP_AND_COPY, + LM_MIGR_STATE_PRE_COPY, + LM_MIGR_STATE_RESUME +} lm_migr_state_t; + +typedef struct { + + /* migration state transition callback */ + /* TODO rename to lm_migration_state_transition_callback */ + /* FIXME maybe we should create a single callback and pass the state? */ + int (*transition)(void *pvt, lm_migr_state_t state); + + /* Callbacks for saving device state */ + + /* + * Function that is called to retrieve pending migration data. If migration + * data were previously made available (function prepare_data has been + * called) then calling this function signifies that they have been read + * (e.g. migration data can be discarded). If the function returns 0 then + * migration has finished and this function won't be called again. + */ + __u64 (*get_pending_bytes)(void *pvt); + + /* + * Function that is called to instruct the device to prepare migration data. + * The function must return only after migration data are available at the + * specified offset. + */ + int (*prepare_data)(void *pvt, __u64 *offset, __u64 *size); + + /* + * Function that is called to read migration data. offset and size can + * be any subrange on the offset and size previously returned by + * prepare_data. The function must return the amount of data read. This + * function can be called even if the migration data can be memory mapped. + * + * Does this mean that reading data_offset/data_size updates the values? + */ + size_t (*read_data)(void *pvt, void *buf, __u64 count, __u64 offset); + + /* Callbacks for restoring device state */ + + /* + * Function that is called when client has written some previously stored + * device state. + */ + int (*data_written)(void *pvt, __u64 count, __u64 offset); + + /* Fuction that is called for writing previously stored device state. */ + size_t (*write_data)(void *pvt, void *buf, __u64 count, __u64 offset); + +} lm_migration_callbacks_t; + +typedef struct { + size_t size; + lm_migration_callbacks_t callbacks; + struct lm_sparse_mmap_areas *mmap_areas; +} lm_migration_t; + +/** + * Device information structure, used to create the lm_ctx. + * To be filled and passed to lm_ctx_create() + */ +typedef struct { + char *uuid; + + /* + * Private data passed to various lm_XXX functions. + */ + void *pvt; + + /* + * Whether an extended PCI configuration space should be created. + */ + bool extended; + + /* + * Function to call for logging. Optional. + */ + lm_log_fn_t *log; + + /* + * Log level. Messages above this level are not logged. Optional + */ + lm_log_lvl_t log_lvl; + + /* + * PCI configuration. + */ + lm_pci_info_t pci_info; + + /* + * Function that is called when the guest resets the device. Optional. + */ + int (*reset) (void *pvt); + + /* + * Function that is called when the guest maps a DMA region. Optional. + */ + void (*map_dma) (void *pvt, uint64_t iova, uint64_t len); + + /* + * Function that is called when the guest unmaps a DMA region. The device + * must release all references to that region before the callback returns. + * This is required if you want to be able to access guest memory. + */ + int (*unmap_dma) (void *pvt, uint64_t iova); + + lm_trans_t trans; + + /* + * Attaching to the transport is non-blocking. The library will not attempt + * to attach during context creation time. The caller must then manually + * call lm_ctx_try_attach(), which is non-blocking, as many times as + * necessary. + */ +#define LM_FLAG_ATTACH_NB (1 << 0) + uint64_t flags; + + /* + * PCI capabilities. + */ + int nr_caps; + lm_cap_t **caps; + + lm_migration_t migration; + +} lm_dev_info_t; + +/** + * Creates libmuser context. + * + * @dev_info: device information used to create the context. + * + * @returns the lm_ctx to be used or NULL on error. Sets errno. + */ +lm_ctx_t * +lm_ctx_create(const lm_dev_info_t *dev_info); + +/** + * Destroys libmuser context. + * + * @lm_ctx: the libmuser context to destroy + */ +void +lm_ctx_destroy(lm_ctx_t *lm_ctx); + +/** + * Once the lm_ctx is configured lm_ctx_drive() drives it. This function waits + * for commands coming from muser.ko and then processes it. + * + * @lm_ctx: the libmuser context to drive + * + * @returns 0 on success, -errno on failure. + */ +int +lm_ctx_drive(lm_ctx_t *lm_ctx); + +/** + * Creates and runs an lm_ctx. + * + * @dev_info: device information used to create the context + * + * @returns 0 on success, -1 on failure. Sets errno. + */ +int +lm_ctx_run(lm_dev_info_t *dev_info); + +/** + * Polls, without blocking, an lm_ctx. This is an alternative to using + * a thread and making a blocking call to lm_ctx_drive(). Instead, the + * application can periodically poll the context directly from one of + * its own threads. + * + * This is only allowed when LM_FLAG_ATTACH_NB is specified during creation. + * + * @lm_ctx: The libmuser context to poll + * + * @returns 0 on success, -errno on failure. + */ +int +lm_ctx_poll(lm_ctx_t *lm_ctx); + +/** + * Triggers an interrupt. + * + * libmuser takes care of using the correct IRQ type (IRQ index: INTx or MSI/X), + * the caller only needs to specify the sub-index. + * + * @lm_ctx: the libmuser context to trigger interrupt + * @subindex: vector subindex to trigger interrupt on + * + * @returns 0 on success, or -1 on failure. Sets errno. + */ +int +lm_irq_trigger(lm_ctx_t *lm_ctx, uint32_t subindex); + +/** + * Sends message to client to trigger an interrupt. + * + * libmuser takes care of using the IRQ type (INTx, MSI/X), the caller only + * needs to specify the sub-index. + * This api can be used to trigger interrupt by sending message to client. + * + * @lm_ctx: the libmuser context to trigger interrupt + * @subindex: vector subindex to trigger interrupt on + * + * @returns 0 on success, or -1 on failure. Sets errno. + */ + +int +lm_irq_message(lm_ctx_t *lm_ctx, uint32_t subindex); + +/* Helper functions */ + +/** + * Converts a guest physical address to a dma_sg_t element which can + * be later passed on to lm_map_sg to memory map the GPA. It is the caller's + * responsibility to unmap it by calling lm_unmap_sg. + * + */ + +/** + * Takes a guest physical address and returns a list of scatter/gather entries + * than can be individually mapped in the program's virtual memory. A single + * linear guest physical address span may need to be split into multiple + * scatter/gather regions due to limitations of how memory can be mapped. + * Field unmap_dma must have been provided at context creation time in order + * to use this function. + * + * @lm_ctx: the libmuser context + * @dma_addr: the guest physical address + * @len: size of memory to be mapped + * @sg: array that receives the scatter/gather entries to be mapped + * @max_sg: maximum number of elements in above array + * @prot: protection as define in + * + * @returns the number of scatter/gather entries created on success, and on + * failure: + * -1: if the GPA address span is invalid, or + * (-x - 1): if @max_sg is too small, where x is the number of scatter/gather + * entries necessary to complete this request. + */ +int +lm_addr_to_sg(lm_ctx_t *lm_ctx, dma_addr_t dma_addr, uint32_t len, + dma_sg_t *sg, int max_sg, int prot); + +/** + * Maps a list scatter/gather entries from the guest's physical address space + * to the program's virtual memory. It is the caller's responsibility to remove + * the mappings by calling lm_unmap_sg. + * Field unmap_dma must have been provided at context creation time in order + * to use this function. + * + * @lm_ctx: the libmuser context + * @sg: array of scatter/gather entries returned by lm_addr_to_sg + * @iov: array of iovec structures (defined in ) to receive each + * mapping + * @cnt: number of scatter/gather entries to map + * + * @returns 0 on success, -1 on failure + */ +int +lm_map_sg(lm_ctx_t *lm_ctx, const dma_sg_t *sg, + struct iovec *iov, int cnt); + +/** + * Unmaps a list scatter/gather entries (previously mapped by lm_map_sg) from + * the program's virtual memory. + * Field unmap_dma must have been provided at context creation time in order + * to use this function. + * + * @lm_ctx: the libmuser context + * @sg: array of scatter/gather entries to unmap + * @iov: array of iovec structures for each scatter/gather entry + * @cnt: number of scatter/gather entries to unmap + */ +void +lm_unmap_sg(lm_ctx_t *lm_ctx, const dma_sg_t *sg, + struct iovec *iov, int cnt); + +/** + * Returns the PCI region given the position and size of an address span in the + * PCI configuration space. + * + * @pos: offset of the address span + * @count: size of the address span + * @off: output parameter that receives the relative offset within the region. + * + * Returns the PCI region (LM_DEV_XXX_REG_IDX), or -errno on error. + */ +int +lm_get_region(loff_t pos, size_t count, loff_t *off); + +/** + * Read from the dma region exposed by the client. + * + * @lm_ctx: the libmuser context + * @sg: a DMA segment obtained from dma_addr_to_sg + * @data: data buffer to read into + */ +int +lm_dma_read(lm_ctx_t *lm_ctx, dma_sg_t *sg, void *data); + +/** + * Write to the dma region exposed by the client. + * + * @lm_ctx: the libmuser context + * @sg: a DMA segment obtained from dma_addr_to_sg + * @data: data buffer to write + */ +int +lm_dma_write(lm_ctx_t *lm_ctx, dma_sg_t *sg, void *data); + +/* + * Advanced stuff. + */ + +/** + * Returns the non-standard part of the PCI configuration space. + */ +uint8_t * +lm_get_pci_non_std_config_space(lm_ctx_t *lm_ctx); + +/* + * Attempts to attach to the transport. LM_FLAG_ATTACH_NB must be set when + * creating the context. Returns 0 on success and -1 on error. If errno is set + * to EAGAIN or EWOULDBLOCK then the transport is not ready to attach to and the + * operation must be retried. + */ +int +lm_ctx_try_attach(lm_ctx_t *lm_ctx); + +/* + * FIXME need to make sure that there can be at most one capability with a given + * ID, otherwise this function will return the first one with this ID. + */ +uint8_t * +lm_ctx_get_cap(lm_ctx_t *lm_ctx, uint8_t id); + +void +lm_log(lm_ctx_t *lm_ctx, lm_log_lvl_t lvl, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* LIB_MUSER_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci.h b/include/pci.h new file mode 100644 index 0000000..27ecf44 --- /dev/null +++ b/include/pci.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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 LIBMUSER_PCI_H +#define LIBMUSER_PCI_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These are already defined in include/uapi/linux/pci_regs.h, however that + * file doesn't seem to installed. + */ +#define PCI_CFG_SPACE_SIZE 256 +#define PCI_CFG_SPACE_EXP_SIZE 4096 + +/* + * TODO lots of the sizes of each member are defined in pci_regs.h, use those + * instead? + */ + +typedef union { + uint32_t raw; + struct { + uint16_t vid; + uint16_t sid; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_ss_t; +_Static_assert(sizeof(lm_pci_hdr_ss_t) == 0x4, "bad SS size"); + +typedef union { + uint8_t raw; +} __attribute__ ((packed)) lm_pci_hdr_bist_t; +_Static_assert(sizeof(lm_pci_hdr_bist_t) == 0x1, "bad BIST size"); + +typedef union { + uint32_t raw; + union { + struct { + unsigned int region_type:1; + unsigned int locatable:2; + unsigned int prefetchable:1; + unsigned int base_address:28; + } __attribute__ ((packed)) mem; + struct { + unsigned int region_type:1; + unsigned int reserved:1; + unsigned int base_address:30; + } __attribute__ ((packed)) io; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_bar_t; +_Static_assert(sizeof(lm_bar_t) == 0x4, "bad BAR size"); + +typedef union { + uint8_t raw; +} __attribute__ ((packed)) lm_pci_hdr_htype_t; +_Static_assert(sizeof(lm_pci_hdr_htype_t) == 0x1, "bad HTYPE size"); + +typedef union { + uint8_t raw[3]; + struct { + uint8_t pi; + uint8_t scc; + uint8_t bcc; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_cc_t; +_Static_assert(sizeof(lm_pci_hdr_cc_t) == 0x3, "bad CC size"); + +/* device status */ +typedef union { + uint16_t raw; + struct { + unsigned int res1:3; + unsigned int is:1; + unsigned int cl:1; + unsigned int c66:1; + unsigned int res2:1; + unsigned int fbc:1; + unsigned int dpd:1; + unsigned int devt:2; + unsigned int sta:1; + unsigned int rta:1; + unsigned int rma:1; + unsigned int sse:1; + unsigned int dpe:1; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_sts_t; +_Static_assert(sizeof(lm_pci_hdr_sts_t) == 0x2, "bad STS size"); + +typedef union { + uint16_t raw; + struct { + uint8_t iose:1; + uint8_t mse:1; + uint8_t bme:1; + uint8_t sce:1; + uint8_t mwie:1; + uint8_t vga:1; + uint8_t pee:1; + uint8_t zero:1; + uint8_t see:1; + uint8_t fbe:1; + uint8_t id:1; + uint8_t res1:5; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_cmd_t; +_Static_assert(sizeof(lm_pci_hdr_cmd_t) == 0x2, "bad CMD size"); + +typedef union { + uint32_t raw; + struct { + uint16_t vid; + uint16_t did; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_id_t; +_Static_assert(sizeof(lm_pci_hdr_id_t) == 0x4, "bad ID size"); + +typedef union { + uint16_t raw; + struct { + uint8_t iline; + uint8_t ipin; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_intr_t; +_Static_assert(sizeof(lm_pci_hdr_intr_t) == 0x2, "bad INTR size"); + +typedef union { + uint8_t raw[PCI_STD_HEADER_SIZEOF]; + struct { + lm_pci_hdr_id_t id; + lm_pci_hdr_cmd_t cmd; + lm_pci_hdr_sts_t sts; + uint8_t rid; + lm_pci_hdr_cc_t cc; + uint8_t cls; + uint8_t mlt; + lm_pci_hdr_htype_t htype; + lm_pci_hdr_bist_t bist; +#define PCI_BARS_NR 6 + lm_bar_t bars[PCI_BARS_NR]; + uint32_t ccptr; + lm_pci_hdr_ss_t ss; + uint32_t erom; + uint8_t cap; + uint8_t res1[7]; + lm_pci_hdr_intr_t intr; + uint8_t mgnt; + uint8_t mlat; + } __attribute__ ((packed)); +} __attribute__ ((packed)) lm_pci_hdr_t; +_Static_assert(sizeof(lm_pci_hdr_t) == 0x40, "bad PCI header size"); + +typedef struct { + uint8_t raw[PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF]; +} __attribute__ ((packed)) lm_pci_non_std_config_space_t; +_Static_assert(sizeof(lm_pci_non_std_config_space_t) == 0xc0, + "bad non-standard PCI configuration space size"); + +typedef struct { + union { + uint8_t raw[PCI_CFG_SPACE_SIZE]; + struct { + lm_pci_hdr_t hdr; + lm_pci_non_std_config_space_t non_std; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + uint8_t extended[]; +} __attribute__ ((packed)) lm_pci_config_space_t; +_Static_assert(sizeof(lm_pci_config_space_t) == 0x100, + "bad PCI configuration space size"); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBMUSER_PCI_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci_caps/common.h b/include/pci_caps/common.h new file mode 100644 index 0000000..aefa209 --- /dev/null +++ b/include/pci_caps/common.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * + * 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 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_MUSER_PCI_CAPS_COMMON_H +#define LIB_MUSER_PCI_CAPS_COMMON_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct cap_hdr { + uint8_t id; + uint8_t next; +} __attribute__((packed)); +_Static_assert(sizeof(struct cap_hdr) == 0x2, "bad PCI capability header size"); +_Static_assert(offsetof(struct cap_hdr, id) == PCI_CAP_LIST_ID, "bad offset"); +_Static_assert(offsetof(struct cap_hdr, next) == PCI_CAP_LIST_NEXT, "bad offset"); + +#ifdef __cplusplus +} +#endif + +#endif /* LIB_MUSER_PCI_CAPS_COMMON_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci_caps/msi.h b/include/pci_caps/msi.h new file mode 100644 index 0000000..1f1a77f --- /dev/null +++ b/include/pci_caps/msi.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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_MUSER_PCI_CAPS_MSI_H +#define LIB_MUSER_PCI_CAPS_MSI_H + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct mc { + unsigned int msie:1; + unsigned int mmc:3; + unsigned int mme:3; + unsigned int c64:1; + unsigned int pvm:1; + unsigned int res1:7; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct mc) == 0x2, "bad MC size"); + +struct ma { + unsigned int res1:2; + unsigned int addr:30; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct ma) == 0x4, "bad MA size"); + +struct msicap { + struct cap_hdr hdr; + struct mc mc; + struct ma ma; + uint32_t mua; + uint16_t md; + uint16_t padding; + uint32_t mmask; + uint32_t mpend; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct msicap) == 0x18, "bad MSICAP size"); +_Static_assert(offsetof(struct msicap, hdr) == 0, "bad offset"); + +#ifdef __cplusplus +} +#endif + +#endif /* LM_CAP_MSI_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci_caps/msix.h b/include/pci_caps/msix.h new file mode 100644 index 0000000..95447bf --- /dev/null +++ b/include/pci_caps/msix.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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_MUSER_PCI_CAPS_MSIX_H +#define LIB_MUSER_PCI_CAPS_MSIX_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mxc { + unsigned int ts:11; + unsigned int reserved:3; + unsigned int fm:1; + unsigned int mxe:1; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct mxc) == PCI_MSIX_FLAGS, "bad MXC size"); + +struct mtab { + unsigned int tbir:3; + unsigned int to:29; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct mtab) == PCI_MSIX_TABLE, "bad MTAB size"); + +struct mpba { + unsigned int pbir:3; + unsigned int pbao:29; +} __attribute__ ((packed)); +_Static_assert(sizeof(struct mtab) == PCI_MSIX_PBA - PCI_MSIX_TABLE, + "bad MPBA size"); + +struct msixcap { + struct cap_hdr hdr; + struct mxc mxc; + struct mtab mtab; + struct mpba mpba; +} __attribute__ ((packed)) __attribute__ ((aligned(4))); +_Static_assert(sizeof(struct msixcap) == PCI_CAP_MSIX_SIZEOF, "bad MSI-X size"); +_Static_assert(offsetof(struct msixcap, hdr) == 0, "bad offset"); + +#ifdef __cplusplus +} +#endif + +#endif /* LM_CAP_MSIX_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci_caps/pm.h b/include/pci_caps/pm.h new file mode 100644 index 0000000..391deac --- /dev/null +++ b/include/pci_caps/pm.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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_MUSER_PCI_CAPS_PM_H +#define LIB_MUSER_PCI_CAPS_PM_H + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pc { + unsigned int vs:3; + unsigned int pmec:1; + unsigned int res:1; + unsigned int dsi:1; + unsigned int auxc:3; + unsigned int d1s:1; + unsigned int d2s:1; + unsigned int psup:5; +} __attribute__((packed)); +_Static_assert(sizeof(struct pc) == 0x2, "bad PC size"); + +struct pmcs { + unsigned int ps:2; + unsigned int res1:1; + unsigned int nsfrst:1; + unsigned int res2:4; + unsigned int pmee:1; + unsigned int dse:4; + unsigned int dsc:2; + unsigned int pmes:1; +} __attribute__((packed)); +_Static_assert(sizeof(struct pc) == 0x2, "bad PMCS size"); + +struct pmcap { + struct cap_hdr hdr; + struct pc pc; + struct pmcs pmcs; +} __attribute__((packed)) __attribute__ ((aligned(8))); /* FIXME why does it need to be aligned? */ +_Static_assert(sizeof(struct pmcap) == PCI_PM_SIZEOF, "bad PC size"); +_Static_assert(offsetof(struct pmcap, hdr) == 0, "bad offset"); + +#ifdef __cplusplus +} +#endif + +#endif /* LM_CAP_PM_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/pci_caps/px.h b/include/pci_caps/px.h new file mode 100644 index 0000000..ac53e15 --- /dev/null +++ b/include/pci_caps/px.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: Thanos Makatos + * Swapnil Ingle + * Felipe Franciosi + * + * 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 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_MUSER_PCI_CAPS_PX_H +#define LIB_MUSER_PCI_CAPS_PX_H + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pxcaps { + unsigned int ver:4; + unsigned int dpt:4; + unsigned int si:1; + unsigned int imn:5; + unsigned int res1:2; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxcaps) == 0x2, "bad PXCAPS size"); + +struct pxdcap { + unsigned int mps:3; + unsigned int pfs:2; + unsigned int etfs:1; + unsigned int l0sl:3; + unsigned int l1l:3; + unsigned int per:1; + unsigned int res1:2; + unsigned int csplv:8; + unsigned int cspls:2; + unsigned int flrc:1; + unsigned int res2:3; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxdcap) == 0x4, "bad PXDCAP size"); + +union pxdc { + uint16_t raw; + struct { + unsigned int cere:1; + unsigned int nfere:1; + unsigned int fere:1; + unsigned int urre:1; + unsigned int ero:1; + unsigned int mps:3; + unsigned int ete:1; + unsigned int pfe:1; + unsigned int appme:1; + unsigned int ens:1; + unsigned int mrrs:3; + unsigned int iflr:1; + } __attribute__((packed)); +} __attribute__((packed)); +_Static_assert(sizeof(union pxdc) == 0x2, "bad PXDC size"); + +/* TODO not defining for now since all values are 0 for reset */ +struct pxds { + unsigned int stuff:16; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxds) == 0x2, "bad PXDS size"); + +struct pxlcap { + unsigned int stuff:32; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxlcap) == 0x4, "bad PXLCAP size"); + +struct pxlc { + unsigned int stuff:16; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxlc) == 0x2, "bad PXLC size"); + +struct pxls { + unsigned int stuff:16; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxls) == 0x2, "bad PXLS size"); + +struct pxdcap2 { + unsigned int ctrs:4; + unsigned int ctds:1; + unsigned int arifs:1; + unsigned int aors:1; + unsigned int aocs32:1; + unsigned int aocs64:1; + unsigned int ccs128:1; + unsigned int nprpr:1; + unsigned int ltrs:1; + unsigned int tphcs:2; + unsigned int obffs:2; + unsigned int effs:1; + unsigned int eetps:1; + unsigned int meetp:2; + unsigned int res1:8; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxdcap2) == 0x4, "bad PXDCAP2 size"); + +struct pxdc2 { + unsigned int stuff:16; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxdc2) == 0x2, "bad PXDC2 size"); + +/* + * TODO the definition of this struct varies, check PCI Express 2.1 + * specification. Maybe we should only define the idividual registers but not + * the whole struct. + */ +struct pxcap { + struct cap_hdr hdr; + struct pxcaps pxcaps; + struct pxdcap pxdcap; + union pxdc pxdc; + struct pxds pxds; + struct pxlcap pxlcap; + struct pxlc pxlc; + struct pxls pxls; + uint8_t pad[0x10]; + struct pxdcap2 pxdcap2; + struct pxdc2 pxdc2; +} __attribute__((packed)); +_Static_assert(sizeof(struct pxcap) == 0x2a, + "bad PCI Express Capability size"); +_Static_assert(offsetof(struct pxcap, hdr) == 0, "bad offset"); + +#ifdef __cplusplus +} +#endif + +#endif /* LIB_MUSER_PCI_CAPS_PX_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vfio_user.h b/include/vfio_user.h new file mode 100644 index 0000000..aeec089 --- /dev/null +++ b/include/vfio_user.h @@ -0,0 +1,181 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * 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 Intel Corporation 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 THE COPYRIGHT + * OWNER OR CONTRIBUTORS 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 VFIO_USER_H +#define VFIO_USER_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum vfio_user_command { + VFIO_USER_VERSION = 1, + VFIO_USER_DMA_MAP = 2, + VFIO_USER_DMA_UNMAP = 3, + VFIO_USER_DEVICE_GET_INFO = 4, + VFIO_USER_DEVICE_GET_REGION_INFO = 5, + VFIO_USER_DEVICE_GET_IRQ_INFO = 6, + VFIO_USER_DEVICE_SET_IRQS = 7, + VFIO_USER_REGION_READ = 8, + VFIO_USER_REGION_WRITE = 9, + VFIO_USER_DMA_READ = 10, + VFIO_USER_DMA_WRITE = 11, + VFIO_USER_VM_INTERRUPT = 12, + VFIO_USER_DEVICE_RESET = 13, + VFIO_USER_DIRTY_PAGES = 14, + VFIO_USER_MAX, +}; + +enum vfio_user_message_type { + VFIO_USER_MESSAGE_COMMAND = 0, + VFIO_USER_MESSAGE_REPLY = 1, +}; + +#define VFIO_USER_FLAGS_NO_REPLY (0x1) + +struct vfio_user_header { + uint16_t msg_id; + uint16_t cmd; + uint32_t msg_size; + struct { + uint32_t type : 4; +#define VFIO_USER_F_TYPE_COMMAND 0 +#define VFIO_USER_F_TYPE_REPLY 1 + uint32_t no_reply : 1; + uint32_t error : 1; + uint32_t resvd : 26; + } flags; + uint32_t error_no; +} __attribute__((packed)); + +struct vfio_user_version { + uint16_t major; + uint16_t minor; + uint8_t data[]; +} __attribute__((packed)); + +struct vfio_user_dma_region { + uint64_t addr; + uint64_t size; + uint64_t offset; + uint32_t prot; + uint32_t flags; +#define VFIO_USER_F_DMA_REGION_MAPPABLE (1 << 0) +} __attribute__((packed)); + +struct vfio_user_region_access { + uint64_t offset; + uint32_t region; + uint32_t count; + uint8_t data[]; +} __attribute__((packed)); + +struct vfio_user_dma_region_access { + uint64_t addr; + uint32_t count; + uint8_t data[]; +} __attribute__((packed)); + +struct vfio_user_irq_info { + uint32_t subindex; +} __attribute__((packed)); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) + +/* copied from */ + +#define VFIO_REGION_TYPE_MIGRATION (3) +#define VFIO_REGION_SUBTYPE_MIGRATION (1) + +struct vfio_device_migration_info { + __u32 device_state; /* VFIO device state */ +#define VFIO_DEVICE_STATE_STOP (0) +#define VFIO_DEVICE_STATE_RUNNING (1 << 0) +#define VFIO_DEVICE_STATE_SAVING (1 << 1) +#define VFIO_DEVICE_STATE_RESUMING (1 << 2) +#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | \ + VFIO_DEVICE_STATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING) + +#define VFIO_DEVICE_STATE_VALID(state) \ + (state & VFIO_DEVICE_STATE_RESUMING ? \ + (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1) + +#define VFIO_DEVICE_STATE_IS_ERROR(state) \ + ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING)) + +#define VFIO_DEVICE_STATE_SET_ERROR(state) \ + ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING) + + __u32 reserved; + __u64 pending_bytes; + __u64 data_offset; + __u64 data_size; +}; + +struct vfio_bitmap { + __u64 pgsize; /* page size for bitmap in bytes */ + __u64 size; /* in bytes */ + __u64 *data; /* one bit per page */ +}; + +struct vfio_iommu_type1_dirty_bitmap { + __u32 argsz; + __u32 flags; +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) + __u8 data[]; +}; + +struct vfio_iommu_type1_dirty_bitmap_get { + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of iova range */ + struct vfio_bitmap bitmap; +}; + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) */ + +#ifdef __cplusplus +} +#endif + +#endif /* VFIO_USER_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 683bf2e..246e0ad 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -39,14 +39,11 @@ add_library(muser SHARED $ $ common.h - muser.h + irq.h muser_priv.h - tran_sock.h - vfio_user.h - irq.h) + tran_sock.h) set_target_properties(muser PROPERTIES LINKER_LANGUAGE C) -set_target_properties(muser PROPERTIES PUBLIC_HEADER "muser.h;pci.h;vfio_user.h") target_link_libraries(muser json-c pthread) @@ -61,23 +58,16 @@ function(add_library_ut lib) set_target_properties(${lib_ut} PROPERTIES LINK_FLAGS ${UT_LFLAGS}) endfunction(add_library_ut) -add_library_ut(cap cap.c cap.h) -add_library_ut(dma dma.c dma.h) -add_library_ut(muser_ctx muser_ctx.c muser.h) -add_library_ut(muser_pci muser_pci.c pci.h) -add_library_ut(tran_sock tran_sock.c tran_sock.h) -add_library_ut(migration migration.c migration.h) -add_library_ut(irq irq.c irq.h) - -set(MUSER_HEADERS_DIR ${CMAKE_INSTALL_INCLUDEDIR}/muser) +add_library_ut(cap cap.c) +add_library_ut(dma dma.c) +add_library_ut(muser_ctx muser_ctx.c) +add_library_ut(muser_pci muser_pci.c) +add_library_ut(tran_sock tran_sock.c) +add_library_ut(migration migration.c) +add_library_ut(irq irq.c) install(TARGETS muser - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${MUSER_HEADERS_DIR}) - -install(DIRECTORY "caps" - DESTINATION ${MUSER_HEADERS_DIR} - FILES_MATCHING PATTERN "*.h") + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) if (DEFINED ENV{PYTHON_BINDINGS}) add_custom_target(python_bindings_build ALL diff --git a/lib/cap.h b/lib/cap.h index 1f72247..527b6c0 100644 --- a/lib/cap.h +++ b/lib/cap.h @@ -30,8 +30,8 @@ * */ -#ifndef __CAP_H__ -#define __CAP_H__ +#ifndef LIB_MUSER_CAP_H +#define LIB_MUSER_CAP_H #include "muser.h" @@ -60,6 +60,6 @@ cap_maybe_access(lm_ctx_t *lm_ctx, struct caps *caps, char *buf, size_t count, uint8_t * cap_find_by_id(lm_ctx_t *lm_ctx, uint8_t id); -#endif /* __CAP_H__ */ +#endif /* LIB_MUSER_CAP_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/caps/common.h b/lib/caps/common.h deleted file mode 100644 index 2181a3b..0000000 --- a/lib/caps/common.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * - * 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 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 LM_PCI_CAP_COMMON_H -#define LM_PCI_CAP_COMMON_H - -#include - -struct cap_hdr { - uint8_t id; - uint8_t next; -} __attribute__((packed)); -_Static_assert(sizeof(struct cap_hdr) == 0x2, "bad PCI capability header size"); -_Static_assert(offsetof(struct cap_hdr, id) == PCI_CAP_LIST_ID, "bad offset"); -_Static_assert(offsetof(struct cap_hdr, next) == PCI_CAP_LIST_NEXT, "bad offset"); - -#endif /* LM_PCI_CAP_COMMON_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/caps/msi.h b/lib/caps/msi.h deleted file mode 100644 index 5933006..0000000 --- a/lib/caps/msi.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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 LM_PCI_CAP_MSI_H -#define LM_PCI_CAP_MSI_H - -#include "common.h" - -struct mc { - unsigned int msie:1; - unsigned int mmc:3; - unsigned int mme:3; - unsigned int c64:1; - unsigned int pvm:1; - unsigned int res1:7; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct mc) == 0x2, "bad MC size"); - -struct ma { - unsigned int res1:2; - unsigned int addr:30; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct ma) == 0x4, "bad MA size"); - -struct msicap { - struct cap_hdr hdr; - struct mc mc; - struct ma ma; - uint32_t mua; - uint16_t md; - uint16_t padding; - uint32_t mmask; - uint32_t mpend; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct msicap) == 0x18, "bad MSICAP size"); -_Static_assert(offsetof(struct msicap, hdr) == 0, "bad offset"); - -#endif /* LM_CAP_MSI_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/caps/msix.h b/lib/caps/msix.h deleted file mode 100644 index b0bc1a5..0000000 --- a/lib/caps/msix.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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 LM_PCI_CAP_MSIX_H -#define LM_PCI_CAP_MSIX_H - -#include - -struct mxc { - unsigned int ts:11; - unsigned int reserved:3; - unsigned int fm:1; - unsigned int mxe:1; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct mxc) == PCI_MSIX_FLAGS, "bad MXC size"); - -struct mtab { - unsigned int tbir:3; - unsigned int to:29; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct mtab) == PCI_MSIX_TABLE, "bad MTAB size"); - -struct mpba { - unsigned int pbir:3; - unsigned int pbao:29; -} __attribute__ ((packed)); -_Static_assert(sizeof(struct mtab) == PCI_MSIX_PBA - PCI_MSIX_TABLE, - "bad MPBA size"); - -struct msixcap { - struct cap_hdr hdr; - struct mxc mxc; - struct mtab mtab; - struct mpba mpba; -} __attribute__ ((packed)) __attribute__ ((aligned(4))); -_Static_assert(sizeof(struct msixcap) == PCI_CAP_MSIX_SIZEOF, "bad MSI-X size"); -_Static_assert(offsetof(struct msixcap, hdr) == 0, "bad offset"); - -#endif /* LM_CAP_MSIX_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/caps/pm.h b/lib/caps/pm.h deleted file mode 100644 index e976d95..0000000 --- a/lib/caps/pm.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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 LM_PCI_CAP_PM_H -#define LM_PCI_CAP_PM_H - -#include "common.h" - -struct pc { - unsigned int vs:3; - unsigned int pmec:1; - unsigned int res:1; - unsigned int dsi:1; - unsigned int auxc:3; - unsigned int d1s:1; - unsigned int d2s:1; - unsigned int psup:5; -} __attribute__((packed)); -_Static_assert(sizeof(struct pc) == 0x2, "bad PC size"); - -struct pmcs { - unsigned int ps:2; - unsigned int res1:1; - unsigned int nsfrst:1; - unsigned int res2:4; - unsigned int pmee:1; - unsigned int dse:4; - unsigned int dsc:2; - unsigned int pmes:1; -} __attribute__((packed)); -_Static_assert(sizeof(struct pc) == 0x2, "bad PMCS size"); - -struct pmcap { - struct cap_hdr hdr; - struct pc pc; - struct pmcs pmcs; -} __attribute__((packed)) __attribute__ ((aligned(8))); /* FIXME why does it need to be aligned? */ -_Static_assert(sizeof(struct pmcap) == PCI_PM_SIZEOF, "bad PC size"); -_Static_assert(offsetof(struct pmcap, hdr) == 0, "bad offset"); - -#endif /* LM_CAP_PM_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/caps/px.h b/lib/caps/px.h deleted file mode 100644 index 28a04d5..0000000 --- a/lib/caps/px.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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 LM_PCI_CAP_PX_H -#define LM_PCI_CAP_PX_H - -#include "common.h" - -struct pxcaps { - unsigned int ver:4; - unsigned int dpt:4; - unsigned int si:1; - unsigned int imn:5; - unsigned int res1:2; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxcaps) == 0x2, "bad PXCAPS size"); - -struct pxdcap { - unsigned int mps:3; - unsigned int pfs:2; - unsigned int etfs:1; - unsigned int l0sl:3; - unsigned int l1l:3; - unsigned int per:1; - unsigned int res1:2; - unsigned int csplv:8; - unsigned int cspls:2; - unsigned int flrc:1; - unsigned int res2:3; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxdcap) == 0x4, "bad PXDCAP size"); - -union pxdc { - uint16_t raw; - struct { - unsigned int cere:1; - unsigned int nfere:1; - unsigned int fere:1; - unsigned int urre:1; - unsigned int ero:1; - unsigned int mps:3; - unsigned int ete:1; - unsigned int pfe:1; - unsigned int appme:1; - unsigned int ens:1; - unsigned int mrrs:3; - unsigned int iflr:1; - } __attribute__((packed)); -} __attribute__((packed)); -_Static_assert(sizeof(union pxdc) == 0x2, "bad PXDC size"); - -/* TODO not defining for now since all values are 0 for reset */ -struct pxds { - unsigned int stuff:16; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxds) == 0x2, "bad PXDS size"); - -struct pxlcap { - unsigned int stuff:32; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxlcap) == 0x4, "bad PXLCAP size"); - -struct pxlc { - unsigned int stuff:16; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxlc) == 0x2, "bad PXLC size"); - -struct pxls { - unsigned int stuff:16; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxls) == 0x2, "bad PXLS size"); - -struct pxdcap2 { - unsigned int ctrs:4; - unsigned int ctds:1; - unsigned int arifs:1; - unsigned int aors:1; - unsigned int aocs32:1; - unsigned int aocs64:1; - unsigned int ccs128:1; - unsigned int nprpr:1; - unsigned int ltrs:1; - unsigned int tphcs:2; - unsigned int obffs:2; - unsigned int effs:1; - unsigned int eetps:1; - unsigned int meetp:2; - unsigned int res1:8; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxdcap2) == 0x4, "bad PXDCAP2 size"); - -struct pxdc2 { - unsigned int stuff:16; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxdc2) == 0x2, "bad PXDC2 size"); - -/* - * TODO the definition of this struct varies, check PCI Express 2.1 - * specification. Maybe we should only define the idividual registers but not - * the whole struct. - */ -struct pxcap { - struct cap_hdr hdr; - struct pxcaps pxcaps; - struct pxdcap pxdcap; - union pxdc pxdc; - struct pxds pxds; - struct pxlcap pxlcap; - struct pxlc pxlc; - struct pxls pxls; - uint8_t pad[0x10]; - struct pxdcap2 pxdcap2; - struct pxdc2 pxdc2; -} __attribute__((packed)); -_Static_assert(sizeof(struct pxcap) == 0x2a, - "bad PCI Express Capability size"); -_Static_assert(offsetof(struct pxcap, hdr) == 0, "bad offset"); - -#endif /* LM_PCI_CAP_PX_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/common.h b/lib/common.h index 41bf343..e30bc2e 100644 --- a/lib/common.h +++ b/lib/common.h @@ -34,8 +34,8 @@ * Private utilities used by the library and sample/test code. */ -#ifndef __COMMON_H__ -#define __COMMON_H__ +#ifndef LIB_MUSER_COMMON_H +#define LIB_MUSER_COMMON_H #include @@ -55,6 +55,6 @@ #define ROUND_DOWN(x, a) ((x) & ~((a)-1)) #define ROUND_UP(x,a) ROUND_DOWN((x)+(a)-1, a) -#endif /* __COMMON_H__ */ +#endif /* LIB_MUSER_COMMON_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/dma.h b/lib/dma.h index 987d8ba..3e2aaf2 100644 --- a/lib/dma.h +++ b/lib/dma.h @@ -28,8 +28,8 @@ * */ -#ifndef DMA_DMA_H -#define DMA_DMA_H +#ifndef LIB_MUSER_DMA_H +#define LIB_MUSER_DMA_H /* * FIXME check whether DMA regions must be page aligned. If so then the @@ -324,6 +324,6 @@ bool dma_controller_region_valid(dma_controller_t *dma, dma_addr_t dma_addr, size_t size); -#endif /* DMA_DMA_H */ +#endif /* LIB_MUSER_DMA_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/irq.h b/lib/irq.h index ac98c28..d29e224 100644 --- a/lib/irq.h +++ b/lib/irq.h @@ -30,6 +30,9 @@ * */ +#ifndef LIB_MUSER_IRQ_H +#define LIB_MUSER_IRQ_H + #include "muser_priv.h" int @@ -40,3 +43,6 @@ int handle_device_set_irqs(lm_ctx_t *lm_ctx, uint32_t size, int *fds, int nr_fds, struct vfio_irq_set *irq_set); +#endif /* LIB_MUSER_IRQ_H */ + +/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/migration.h b/lib/migration.h index 535f97b..a16d5fa 100644 --- a/lib/migration.h +++ b/lib/migration.h @@ -31,9 +31,8 @@ // FIXME: license header (and SPDX ?) everywhere -/* FIXME: regularize across private headers */ -#ifndef MUSER_MIGRATION_H -#define MUSER_MIGRATION_H +#ifndef LIB_MUSER_MIGRATION_H +#define LIB_MUSER_MIGRATION_H /* * These are not public routines, but for convenience, they are used by the @@ -44,22 +43,30 @@ #include "muser.h" -struct migration *init_migration(const lm_migration_t * const lm_migr); +struct migration * +init_migration(const lm_migration_t * const lm_migr); -ssize_t handle_migration_region_access(lm_ctx_t *lm_ctx, void *pvt, - struct migration *migr, - char *buf, size_t count, - loff_t pos, bool is_write); +ssize_t +handle_migration_region_access(lm_ctx_t *lm_ctx, void *pvt, + struct migration *migr, + char *buf, size_t count, + loff_t pos, bool is_write); -bool migration_available(lm_ctx_t *lm_ctx); +bool +migration_available(lm_ctx_t *lm_ctx); -bool device_is_stopped_and_copying(struct migration *migr); +bool +device_is_stopped_and_copying(struct migration *migr); -bool device_is_stopped(struct migration *migr); +bool +device_is_stopped(struct migration *migr); -size_t migration_get_pgsize(struct migration *migr); +size_t +migration_get_pgsize(struct migration *migr); -int migration_set_pgsize(struct migration *migr, size_t pgsize); +int +migration_set_pgsize(struct migration *migr, size_t pgsize); + +#endif /* LIB_MUSER_MIGRATION_H */ -#endif /* MUSER_MIGRATION_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/muser.h b/lib/muser.h deleted file mode 100644 index a71337d..0000000 --- a/lib/muser.h +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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_MUSER_H -#define LIB_MUSER_H - -#include -#include -#include - -#include "vfio_user.h" -#include "pci.h" -#include "caps/pm.h" -#include "caps/px.h" -#include "caps/msi.h" -#include "caps/msix.h" - -#define LIB_MUSER_VFIO_USER_VERS_MJ 0 -#define LIB_MUSER_VFIO_USER_VERS_MN 1 - -typedef uint64_t dma_addr_t; - -typedef struct { - dma_addr_t dma_addr; - int region; - int length; - uint64_t offset; -} dma_sg_t; - -typedef struct lm_ctx lm_ctx_t; - -// Region flags. -#define LM_REG_FLAG_READ (1 << 0) -#define LM_REG_FLAG_WRITE (1 << 1) -#define LM_REG_FLAG_MMAP (1 << 2) // TODO: how this relates to IO bar? -#define LM_REG_FLAG_RW (LM_REG_FLAG_READ | LM_REG_FLAG_WRITE) -#define LM_REG_FLAG_MEM (1 << 3) // if unset, bar is IO - -struct lm_mmap_area { - uint64_t start; - uint64_t size; -}; - -struct lm_sparse_mmap_areas { - int nr_mmap_areas; - struct lm_mmap_area areas[]; -}; - -/** - * Prototype for region access callback. When a region is accessed, libmuser - * calls the previously registered callback with the following arguments: - * - * @pvt: private data originally set in dev_info - * @buf: buffer containing the data to be written or data to be read into - * @count: number of bytes being read or written - * @offset: byte offset within the region - * @is_write: whether or not this is a write - * - * @returns the number of bytes read or written, or a negative integer on error - */ -typedef ssize_t (lm_region_access_t) (void *pvt, char *buf, size_t count, - loff_t offset, bool is_write); - -/** - * Prototype for memory access callback. The program MUST first map device - * memory in its own virtual address space using lm_mmap, do any additional - * work required, and finally return that memory. When a region is memory - * mapped, libmuser calls previously register callback with the following - * arguments: - * - * @pvt: private data originally set in dev_info - * @off: offset of memory area being memory mapped - * @len: length of memory area being memory mapped - * - * @returns the memory address returned by lm_mmap, or MAP_FAILED on failure - */ -typedef unsigned long (lm_map_region_t) (void *pvt, unsigned long off, - unsigned long len); - -/** - * Creates a mapping of a device region into the caller's virtual memory. It - * must be called by lm_map_region_t. - * - * @lm_ctx: the libmuser context to create mapping from - * @offset: offset of the region being mapped - * @length: size of the region being mapped - * - * @returns a pointer to the requested memory or MAP_FAILED on error. Sets errno. - */ -void *lm_mmap(lm_ctx_t * lm_ctx, off_t offset, size_t length); - -typedef struct { - - /* - * Region flags, see LM_REG_FLAG_XXX above. - */ - uint32_t flags; - - /* - * Size of the region. - */ - uint32_t size; - - /* - * Callback function that is called when the region is read or written. - * Note that the memory of the region is owned by the user, except for the - * standard header (first 64 bytes) of the PCI configuration space. - */ - lm_region_access_t *fn; - - /* - * Callback function that is called when the region is memory mapped. - * Required if LM_REG_FLAG_MEM is set, otherwise ignored. - */ - lm_map_region_t *map; - struct lm_sparse_mmap_areas *mmap_areas; /* sparse mmap areas */ -} lm_reg_info_t; - -enum { - LM_DEV_INTX_IRQ_IDX, - LM_DEV_MSI_IRQ_IDX, - LM_DEV_MSIX_IRQ_IDX, - LM_DEV_ERR_IRQ_INDEX, - LM_DEV_REQ_IRQ_INDEX, - LM_DEV_NUM_IRQS -}; - -/* FIXME these are PCI regions */ -enum { - LM_DEV_BAR0_REG_IDX, - LM_DEV_BAR1_REG_IDX, - LM_DEV_BAR2_REG_IDX, - LM_DEV_BAR3_REG_IDX, - LM_DEV_BAR4_REG_IDX, - LM_DEV_BAR5_REG_IDX, - LM_DEV_ROM_REG_IDX, - LM_DEV_CFG_REG_IDX, - LM_DEV_VGA_REG_IDX, - LM_DEV_NUM_REGS, /* TODO rename to LM_DEV_NUM_PCI_REGS */ -}; - -typedef struct { - uint32_t irq_count[LM_DEV_NUM_IRQS]; - - /* - * Per-region information. Only supported regions need to be defined, - * unsupported regions should be left to 0. - */ - lm_reg_info_t reg_info[LM_DEV_NUM_REGS]; - - /* - * Device and vendor ID. - */ - lm_pci_hdr_id_t id; - - /* - * Subsystem vendor and device ID. - */ - lm_pci_hdr_ss_t ss; - - /* - * Class code. - */ - lm_pci_hdr_cc_t cc; -} lm_pci_info_t; - -/* - * Returns a pointer to the standard part of the PCI configuration space. - */ -lm_pci_config_space_t *lm_get_pci_config_space(lm_ctx_t *lm_ctx); - -#define LM_DMA_REGIONS 0x10 - -typedef enum { - LM_ERR, - LM_INF, - LM_DBG -} lm_log_lvl_t; - -/** - * Callback function signature for log function - * - * @lm_log_fn_t: typedef for log function. - */ -typedef void (lm_log_fn_t) (void *pvt, lm_log_lvl_t lvl, const char *msg); - -/** - * Callback function that gets called when a capability is accessed. The - * callback is not called when the ID and next fields are accessed, these are - * handled by the library. - * - * @pvt: private pointer - * @id: capability ID being accessed - * @buf: pointer to data being read or written - * @count: number of bytes being read or written - * @offset: offset within the capability - * @is_write: whether the capability is read or written - * - * @returns the number of bytes read or written - */ -typedef ssize_t (lm_cap_access_t) (void *pvt, uint8_t id, - char *buf, size_t count, - loff_t offset, bool is_write); - -/* FIXME does it have to be packed as well? */ -typedef union { - struct msicap msi; - struct msixcap msix; - struct pmcap pm; - struct pxcap px; -} lm_cap_t; - -typedef enum { - LM_TRANS_SOCK, - LM_TRANS_MAX -} lm_trans_t; - -#define LM_MAX_CAPS (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF - -/* - * FIXME the names of migration callback functions are probably far too long, - * but for now it helps with the implementation. - */ -typedef int (lm_migration_callback_t)(void *pvt); - -typedef enum { - LM_MIGR_STATE_STOP, - LM_MIGR_STATE_RUNNING, - LM_MIGR_STATE_STOP_AND_COPY, - LM_MIGR_STATE_PRE_COPY, - LM_MIGR_STATE_RESUME -} lm_migr_state_t; - -typedef struct { - - /* migration state transition callback */ - /* TODO rename to lm_migration_state_transition_callback */ - /* FIXME maybe we should create a single callback and pass the state? */ - int (*transition)(void *pvt, lm_migr_state_t state); - - /* Callbacks for saving device state */ - - /* - * Function that is called to retrieve pending migration data. If migration - * data were previously made available (function prepare_data has been - * called) then calling this function signifies that they have been read - * (e.g. migration data can be discarded). If the function returns 0 then - * migration has finished and this function won't be called again. - */ - __u64 (*get_pending_bytes)(void *pvt); - - /* - * Function that is called to instruct the device to prepare migration data. - * The function must return only after migration data are available at the - * specified offset. - */ - int (*prepare_data)(void *pvt, __u64 *offset, __u64 *size); - - /* - * Function that is called to read migration data. offset and size can - * be any subrange on the offset and size previously returned by - * prepare_data. The function must return the amount of data read. This - * function can be called even if the migration data can be memory mapped. - * - * Does this mean that reading data_offset/data_size updates the values? - */ - size_t (*read_data)(void *pvt, void *buf, __u64 count, __u64 offset); - - /* Callbacks for restoring device state */ - - /* - * Function that is called when client has written some previously stored - * device state. - */ - int (*data_written)(void *pvt, __u64 count, __u64 offset); - - /* Fuction that is called for writing previously stored device state. */ - size_t (*write_data)(void *pvt, void *buf, __u64 count, __u64 offset); - -} lm_migration_callbacks_t; - -typedef struct { - size_t size; - lm_migration_callbacks_t callbacks; - struct lm_sparse_mmap_areas *mmap_areas; -} lm_migration_t; - -/** - * Device information structure, used to create the lm_ctx. - * To be filled and passed to lm_ctx_create() - */ -typedef struct { - char *uuid; - - /* - * Private data passed to various lm_XXX functions. - */ - void *pvt; - - /* - * Whether an extended PCI configuration space should be created. - */ - bool extended; - - /* - * Function to call for logging. Optional. - */ - lm_log_fn_t *log; - - /* - * Log level. Messages above this level are not logged. Optional - */ - lm_log_lvl_t log_lvl; - - /* - * PCI configuration. - */ - lm_pci_info_t pci_info; - - /* - * Function that is called when the guest resets the device. Optional. - */ - int (*reset) (void *pvt); - - /* - * Function that is called when the guest maps a DMA region. Optional. - */ - void (*map_dma) (void *pvt, uint64_t iova, uint64_t len); - - /* - * Function that is called when the guest unmaps a DMA region. The device - * must release all references to that region before the callback returns. - * This is required if you want to be able to access guest memory. - */ - int (*unmap_dma) (void *pvt, uint64_t iova); - - lm_trans_t trans; - - /* - * Attaching to the transport is non-blocking. The library will not attempt - * to attach during context creation time. The caller must then manually - * call lm_ctx_try_attach(), which is non-blocking, as many times as - * necessary. - */ -#define LM_FLAG_ATTACH_NB (1 << 0) - uint64_t flags; - - /* - * PCI capabilities. - */ - int nr_caps; - lm_cap_t **caps; - - lm_migration_t migration; - -} lm_dev_info_t; - -/** - * Creates libmuser context. - * - * @dev_info: device information used to create the context. - * - * @returns the lm_ctx to be used or NULL on error. Sets errno. - */ -lm_ctx_t * -lm_ctx_create(const lm_dev_info_t *dev_info); - -/** - * Destroys libmuser context. - * - * @lm_ctx: the libmuser context to destroy - */ -void -lm_ctx_destroy(lm_ctx_t *lm_ctx); - -/** - * Once the lm_ctx is configured lm_ctx_drive() drives it. This function waits - * for commands coming from muser.ko and then processes it. - * - * @lm_ctx: the libmuser context to drive - * - * @returns 0 on success, -errno on failure. - */ -int -lm_ctx_drive(lm_ctx_t *lm_ctx); - -/** - * Creates and runs an lm_ctx. - * - * @dev_info: device information used to create the context - * - * @returns 0 on success, -1 on failure. Sets errno. - */ -int -lm_ctx_run(lm_dev_info_t *dev_info); - -/** - * Polls, without blocking, an lm_ctx. This is an alternative to using - * a thread and making a blocking call to lm_ctx_drive(). Instead, the - * application can periodically poll the context directly from one of - * its own threads. - * - * This is only allowed when LM_FLAG_ATTACH_NB is specified during creation. - * - * @lm_ctx: The libmuser context to poll - * - * @returns 0 on success, -errno on failure. - */ -int -lm_ctx_poll(lm_ctx_t *lm_ctx); - -/** - * Triggers an interrupt. - * - * libmuser takes care of using the correct IRQ type (IRQ index: INTx or MSI/X), - * the caller only needs to specify the sub-index. - * - * @lm_ctx: the libmuser context to trigger interrupt - * @subindex: vector subindex to trigger interrupt on - * - * @returns 0 on success, or -1 on failure. Sets errno. - */ -int -lm_irq_trigger(lm_ctx_t *lm_ctx, uint32_t subindex); - -/** - * Sends message to client to trigger an interrupt. - * - * libmuser takes care of using the IRQ type (INTx, MSI/X), the caller only - * needs to specify the sub-index. - * This api can be used to trigger interrupt by sending message to client. - * - * @lm_ctx: the libmuser context to trigger interrupt - * @subindex: vector subindex to trigger interrupt on - * - * @returns 0 on success, or -1 on failure. Sets errno. - */ - -int -lm_irq_message(lm_ctx_t *lm_ctx, uint32_t subindex); - -/* Helper functions */ - -/** - * Converts a guest physical address to a dma_sg_t element which can - * be later passed on to lm_map_sg to memory map the GPA. It is the caller's - * responsibility to unmap it by calling lm_unmap_sg. - * - */ - -/** - * Takes a guest physical address and returns a list of scatter/gather entries - * than can be individually mapped in the program's virtual memory. A single - * linear guest physical address span may need to be split into multiple - * scatter/gather regions due to limitations of how memory can be mapped. - * Field unmap_dma must have been provided at context creation time in order - * to use this function. - * - * @lm_ctx: the libmuser context - * @dma_addr: the guest physical address - * @len: size of memory to be mapped - * @sg: array that receives the scatter/gather entries to be mapped - * @max_sg: maximum number of elements in above array - * @prot: protection as define in - * - * @returns the number of scatter/gather entries created on success, and on - * failure: - * -1: if the GPA address span is invalid, or - * (-x - 1): if @max_sg is too small, where x is the number of scatter/gather - * entries necessary to complete this request. - */ -int -lm_addr_to_sg(lm_ctx_t *lm_ctx, dma_addr_t dma_addr, uint32_t len, - dma_sg_t *sg, int max_sg, int prot); - -/** - * Maps a list scatter/gather entries from the guest's physical address space - * to the program's virtual memory. It is the caller's responsibility to remove - * the mappings by calling lm_unmap_sg. - * Field unmap_dma must have been provided at context creation time in order - * to use this function. - * - * @lm_ctx: the libmuser context - * @sg: array of scatter/gather entries returned by lm_addr_to_sg - * @iov: array of iovec structures (defined in ) to receive each - * mapping - * @cnt: number of scatter/gather entries to map - * - * @returns 0 on success, -1 on failure - */ -int -lm_map_sg(lm_ctx_t *lm_ctx, const dma_sg_t *sg, - struct iovec *iov, int cnt); - -/** - * Unmaps a list scatter/gather entries (previously mapped by lm_map_sg) from - * the program's virtual memory. - * Field unmap_dma must have been provided at context creation time in order - * to use this function. - * - * @lm_ctx: the libmuser context - * @sg: array of scatter/gather entries to unmap - * @iov: array of iovec structures for each scatter/gather entry - * @cnt: number of scatter/gather entries to unmap - */ -void -lm_unmap_sg(lm_ctx_t *lm_ctx, const dma_sg_t *sg, - struct iovec *iov, int cnt); - -/** - * Returns the PCI region given the position and size of an address span in the - * PCI configuration space. - * - * @pos: offset of the address span - * @count: size of the address span - * @off: output parameter that receives the relative offset within the region. - * - * Returns the PCI region (LM_DEV_XXX_REG_IDX), or -errno on error. - */ -int -lm_get_region(loff_t pos, size_t count, loff_t *off); - -/** - * Read from the dma region exposed by the client. - * - * @lm_ctx: the libmuser context - * @sg: a DMA segment obtained from dma_addr_to_sg - * @data: data buffer to read into - */ -int -lm_dma_read(lm_ctx_t *lm_ctx, dma_sg_t *sg, void *data); - -/** - * Write to the dma region exposed by the client. - * - * @lm_ctx: the libmuser context - * @sg: a DMA segment obtained from dma_addr_to_sg - * @data: data buffer to write - */ -int -lm_dma_write(lm_ctx_t *lm_ctx, dma_sg_t *sg, void *data); - -/* - * Advanced stuff. - */ - -/** - * Returns the non-standard part of the PCI configuration space. - */ -uint8_t * -lm_get_pci_non_std_config_space(lm_ctx_t *lm_ctx); - -/* - * Attempts to attach to the transport. LM_FLAG_ATTACH_NB must be set when - * creating the context. Returns 0 on success and -1 on error. If errno is set - * to EAGAIN or EWOULDBLOCK then the transport is not ready to attach to and the - * operation must be retried. - */ -int -lm_ctx_try_attach(lm_ctx_t *lm_ctx); - -/* - * FIXME need to make sure that there can be at most one capability with a given - * ID, otherwise this function will return the first one with this ID. - */ -uint8_t * -lm_ctx_get_cap(lm_ctx_t *lm_ctx, uint8_t id); - -void -lm_log(lm_ctx_t *lm_ctx, lm_log_lvl_t lvl, const char *fmt, ...); - -#endif /* LIB_MUSER_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/muser_priv.h b/lib/muser_priv.h index e469895..5ca63a9 100644 --- a/lib/muser_priv.h +++ b/lib/muser_priv.h @@ -30,8 +30,8 @@ * */ -#ifndef MUSER_PRIV_H -#define MUSER_PRIV_H +#ifndef LIB_MUSER_PRIV_H +#define LIB_MUSER_PRIV_H #include "dma.h" @@ -112,7 +112,8 @@ region_to_offset(uint32_t region); #define offsetofend(TYPE, MEMBER) \ (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) -static inline ssize_t get_minsz(unsigned int cmd) +static inline ssize_t +get_minsz(unsigned int cmd) { switch (cmd) { case VFIO_DEVICE_GET_INFO: @@ -145,7 +146,8 @@ static inline ssize_t get_minsz(unsigned int cmd) return -EOPNOTSUPP; } -static inline const char* vfio_cmd_to_str(int cmd) { +static inline const char * +vfio_cmd_to_str(int cmd) { switch (cmd) { case VFIO_GET_API_VERSION: return "VFIO_GET_API_VERSION"; case VFIO_CHECK_EXTENSION: return "VFIO_CHECK_EXTENSION"; @@ -173,6 +175,6 @@ static inline const char* vfio_cmd_to_str(int cmd) { return NULL; } -#endif /* MUSER_PRIV_H */ +#endif /* LIB_MUSER_PRIV_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/pci.h b/lib/pci.h deleted file mode 100644 index 3d6289f..0000000 --- a/lib/pci.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2019 Nutanix Inc. All rights reserved. - * - * Authors: Thanos Makatos - * Swapnil Ingle - * Felipe Franciosi - * - * 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 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 LIBMUSER_PCI_H -#define LIBMUSER_PCI_H - -#include -#include -#include - -/* - * These are already defined in include/uapi/linux/pci_regs.h, however that - * file doesn't seem to installed. - */ -#define PCI_CFG_SPACE_SIZE 256 -#define PCI_CFG_SPACE_EXP_SIZE 4096 - -/* - * TODO lots of the sizes of each member are defined in pci_regs.h, use those - * instead? - */ - -typedef union { - uint32_t raw; - struct { - uint16_t vid; - uint16_t sid; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_ss_t; -_Static_assert(sizeof(lm_pci_hdr_ss_t) == 0x4, "bad SS size"); - -typedef union { - uint8_t raw; -} __attribute__ ((packed)) lm_pci_hdr_bist_t; -_Static_assert(sizeof(lm_pci_hdr_bist_t) == 0x1, "bad BIST size"); - -typedef union { - uint32_t raw; - union { - struct { - unsigned int region_type:1; - unsigned int locatable:2; - unsigned int prefetchable:1; - unsigned int base_address:28; - } __attribute__ ((packed)) mem; - struct { - unsigned int region_type:1; - unsigned int reserved:1; - unsigned int base_address:30; - } __attribute__ ((packed)) io; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_bar_t; -_Static_assert(sizeof(lm_bar_t) == 0x4, "bad BAR size"); - -typedef union { - uint8_t raw; -} __attribute__ ((packed)) lm_pci_hdr_htype_t; -_Static_assert(sizeof(lm_pci_hdr_htype_t) == 0x1, "bad HTYPE size"); - -typedef union { - uint8_t raw[3]; - struct { - uint8_t pi; - uint8_t scc; - uint8_t bcc; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_cc_t; -_Static_assert(sizeof(lm_pci_hdr_cc_t) == 0x3, "bad CC size"); - -/* device status */ -typedef union { - uint16_t raw; - struct { - unsigned int res1:3; - unsigned int is:1; - unsigned int cl:1; - unsigned int c66:1; - unsigned int res2:1; - unsigned int fbc:1; - unsigned int dpd:1; - unsigned int devt:2; - unsigned int sta:1; - unsigned int rta:1; - unsigned int rma:1; - unsigned int sse:1; - unsigned int dpe:1; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_sts_t; -_Static_assert(sizeof(lm_pci_hdr_sts_t) == 0x2, "bad STS size"); - -typedef union { - uint16_t raw; - struct { - uint8_t iose:1; - uint8_t mse:1; - uint8_t bme:1; - uint8_t sce:1; - uint8_t mwie:1; - uint8_t vga:1; - uint8_t pee:1; - uint8_t zero:1; - uint8_t see:1; - uint8_t fbe:1; - uint8_t id:1; - uint8_t res1:5; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_cmd_t; -_Static_assert(sizeof(lm_pci_hdr_cmd_t) == 0x2, "bad CMD size"); - -typedef union { - uint32_t raw; - struct { - uint16_t vid; - uint16_t did; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_id_t; -_Static_assert(sizeof(lm_pci_hdr_id_t) == 0x4, "bad ID size"); - -typedef union { - uint16_t raw; - struct { - uint8_t iline; - uint8_t ipin; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_intr_t; -_Static_assert(sizeof(lm_pci_hdr_intr_t) == 0x2, "bad INTR size"); - -typedef union { - uint8_t raw[PCI_STD_HEADER_SIZEOF]; - struct { - lm_pci_hdr_id_t id; - lm_pci_hdr_cmd_t cmd; - lm_pci_hdr_sts_t sts; - uint8_t rid; - lm_pci_hdr_cc_t cc; - uint8_t cls; - uint8_t mlt; - lm_pci_hdr_htype_t htype; - lm_pci_hdr_bist_t bist; -#define PCI_BARS_NR 6 - lm_bar_t bars[PCI_BARS_NR]; - uint32_t ccptr; - lm_pci_hdr_ss_t ss; - uint32_t erom; - uint8_t cap; - uint8_t res1[7]; - lm_pci_hdr_intr_t intr; - uint8_t mgnt; - uint8_t mlat; - } __attribute__ ((packed)); -} __attribute__ ((packed)) lm_pci_hdr_t; -_Static_assert(sizeof(lm_pci_hdr_t) == 0x40, "bad PCI header size"); - -typedef struct { - uint8_t raw[PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF]; -} __attribute__ ((packed)) lm_pci_non_std_config_space_t; -_Static_assert(sizeof(lm_pci_non_std_config_space_t) == 0xc0, - "bad non-standard PCI configuration space size"); - -typedef struct { - union { - uint8_t raw[PCI_CFG_SPACE_SIZE]; - struct { - lm_pci_hdr_t hdr; - lm_pci_non_std_config_space_t non_std; - } __attribute__ ((packed)); - } __attribute__ ((packed)); - uint8_t extended[]; -} __attribute__ ((packed)) lm_pci_config_space_t; -_Static_assert(sizeof(lm_pci_config_space_t) == 0x100, - "bad PCI configuration space size"); - -#endif /* LIBMUSER_PCI_H */ - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/tran_sock.h b/lib/tran_sock.h index 9add12c..a4c9a17 100644 --- a/lib/tran_sock.h +++ b/lib/tran_sock.h @@ -30,8 +30,8 @@ * */ -#ifndef TRAN_SOCK_H -#define TRAN_SOCK_H +#ifndef LIB_MUSER_TRAN_SOCK_H +#define LIB_MUSER_TRAN_SOCK_H #include "muser.h" @@ -52,50 +52,56 @@ extern struct transport_ops sock_transport_ops; * Parse JSON supplied from the other side into the known parameters. Note: they * will not be set if not found in the JSON. */ -int vfio_user_parse_version_json(const char *json_str, int *client_max_fdsp, - size_t *pgsizep); +int +vfio_user_parse_version_json(const char *json_str, int *client_max_fdsp, + size_t *pgsizep); /* * Send a message to the other end. The iovecs array should leave the first * entry empty, as it will be used for the header. */ -int vfio_user_send_iovec(int sock, uint16_t msg_id, bool is_reply, - enum vfio_user_command cmd, - struct iovec *iovecs, size_t nr_iovecs, - int *fds, int count, - int err); +int +vfio_user_send_iovec(int sock, uint16_t msg_id, bool is_reply, + enum vfio_user_command cmd, + struct iovec *iovecs, size_t nr_iovecs, + int *fds, int count, + int err); /* * Send a message to the other end with the given data. */ -int vfio_user_send(int sock, uint16_t msg_id, bool is_reply, - enum vfio_user_command cmd, - void *data, size_t data_len); +int +vfio_user_send(int sock, uint16_t msg_id, bool is_reply, + enum vfio_user_command cmd, + void *data, size_t data_len); /* * Send an empty reply back to the other end with the given errno. */ -int vfio_user_send_error(int sock, uint16_t msg_id, - enum vfio_user_command cmd, - int error); +int +vfio_user_send_error(int sock, uint16_t msg_id, + enum vfio_user_command cmd, + int error); /* * Receive a message from the other end, and place the data into the given * buffer. If data is supplied by the other end, it must be exactly *len in * size. */ -int vfio_user_recv(int sock, struct vfio_user_header *hdr, - bool is_reply, uint16_t *msg_id, - void *data, size_t *len); +int +vfio_user_recv(int sock, struct vfio_user_header *hdr, + bool is_reply, uint16_t *msg_id, + void *data, size_t *len); /* * Receive a message from the other end, but automatically allocate a buffer for * it, which must be freed by the caller. If there is no data, *datap is set to * NULL. */ -int vfio_user_recv_alloc(int sock, struct vfio_user_header *hdr, - bool is_reply, uint16_t *msg_id, - void **datap, size_t *lenp); +int +vfio_user_recv_alloc(int sock, struct vfio_user_header *hdr, + bool is_reply, uint16_t *msg_id, + void **datap, size_t *lenp); /* * Send and receive a message to the other end, using iovecs for the send. The @@ -105,23 +111,25 @@ int vfio_user_recv_alloc(int sock, struct vfio_user_header *hdr, * If specified, the given fds are sent to the other side. @hdr is filled with * the reply header if non-NULL. */ -int vfio_user_msg_iovec(int sock, uint16_t msg_id, - enum vfio_user_command cmd, - struct iovec *iovecs, size_t nr_iovecs, - int *send_fds, size_t fd_count, - struct vfio_user_header *hdr, - void *recv_data, size_t recv_len); +int +vfio_user_msg_iovec(int sock, uint16_t msg_id, + enum vfio_user_command cmd, + struct iovec *iovecs, size_t nr_iovecs, + int *send_fds, size_t fd_count, + struct vfio_user_header *hdr, + void *recv_data, size_t recv_len); /* * Send and receive a message to the other end. @hdr is filled with the reply * header if non-NULL. */ -int vfio_user_msg(int sock, uint16_t msg_id, - enum vfio_user_command cmd, - void *send_data, size_t send_len, - struct vfio_user_header *hdr, - void *recv_data, size_t recv_len); +int +vfio_user_msg(int sock, uint16_t msg_id, + enum vfio_user_command cmd, + void *send_data, size_t send_len, + struct vfio_user_header *hdr, + void *recv_data, size_t recv_len); -#endif /* TRAN_SOCK_H */ +#endif /* LIB_MUSER_TRAN_SOCK_H */ /* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/lib/vfio_user.h b/lib/vfio_user.h deleted file mode 100644 index 76cd84c..0000000 --- a/lib/vfio_user.h +++ /dev/null @@ -1,173 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright (c) Intel Corporation. - * All rights reserved. - * - * 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 Intel Corporation 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 THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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 _VFIO_USER_H -#define _VFIO_USER_H - -#include -#include -#include - -enum vfio_user_command { - VFIO_USER_VERSION = 1, - VFIO_USER_DMA_MAP = 2, - VFIO_USER_DMA_UNMAP = 3, - VFIO_USER_DEVICE_GET_INFO = 4, - VFIO_USER_DEVICE_GET_REGION_INFO = 5, - VFIO_USER_DEVICE_GET_IRQ_INFO = 6, - VFIO_USER_DEVICE_SET_IRQS = 7, - VFIO_USER_REGION_READ = 8, - VFIO_USER_REGION_WRITE = 9, - VFIO_USER_DMA_READ = 10, - VFIO_USER_DMA_WRITE = 11, - VFIO_USER_VM_INTERRUPT = 12, - VFIO_USER_DEVICE_RESET = 13, - VFIO_USER_DIRTY_PAGES = 14, - VFIO_USER_MAX, -}; - -enum vfio_user_message_type { - VFIO_USER_MESSAGE_COMMAND = 0, - VFIO_USER_MESSAGE_REPLY = 1, -}; - -#define VFIO_USER_FLAGS_NO_REPLY (0x1) - -struct vfio_user_header { - uint16_t msg_id; - uint16_t cmd; - uint32_t msg_size; - struct { - uint32_t type : 4; -#define VFIO_USER_F_TYPE_COMMAND 0 -#define VFIO_USER_F_TYPE_REPLY 1 - uint32_t no_reply : 1; - uint32_t error : 1; - uint32_t resvd : 26; - } flags; - uint32_t error_no; -} __attribute__((packed)); - -struct vfio_user_version { - uint16_t major; - uint16_t minor; - uint8_t data[]; -} __attribute__((packed)); - -struct vfio_user_dma_region { - uint64_t addr; - uint64_t size; - uint64_t offset; - uint32_t prot; - uint32_t flags; -#define VFIO_USER_F_DMA_REGION_MAPPABLE (1 << 0) -} __attribute__((packed)); - -struct vfio_user_region_access { - uint64_t offset; - uint32_t region; - uint32_t count; - uint8_t data[]; -} __attribute__((packed)); - -struct vfio_user_dma_region_access { - uint64_t addr; - uint32_t count; - uint8_t data[]; -} __attribute__((packed)); - -struct vfio_user_irq_info { - uint32_t subindex; -} __attribute__((packed)); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) - -/* copied from */ - -#define VFIO_REGION_TYPE_MIGRATION (3) -#define VFIO_REGION_SUBTYPE_MIGRATION (1) - -struct vfio_device_migration_info { - __u32 device_state; /* VFIO device state */ -#define VFIO_DEVICE_STATE_STOP (0) -#define VFIO_DEVICE_STATE_RUNNING (1 << 0) -#define VFIO_DEVICE_STATE_SAVING (1 << 1) -#define VFIO_DEVICE_STATE_RESUMING (1 << 2) -#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | \ - VFIO_DEVICE_STATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING) - -#define VFIO_DEVICE_STATE_VALID(state) \ - (state & VFIO_DEVICE_STATE_RESUMING ? \ - (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1) - -#define VFIO_DEVICE_STATE_IS_ERROR(state) \ - ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING)) - -#define VFIO_DEVICE_STATE_SET_ERROR(state) \ - ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING) - - __u32 reserved; - __u64 pending_bytes; - __u64 data_offset; - __u64 data_size; -}; - -struct vfio_bitmap { - __u64 pgsize; /* page size for bitmap in bytes */ - __u64 size; /* in bytes */ - __u64 *data; /* one bit per page */ -}; - -struct vfio_iommu_type1_dirty_bitmap { - __u32 argsz; - __u32 flags; -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) - __u8 data[]; -}; - -struct vfio_iommu_type1_dirty_bitmap_get { - __u64 iova; /* IO virtual address */ - __u64 size; /* Size of iova range */ - struct vfio_bitmap bitmap; -}; - -#endif - -#endif - -/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/samples/client.c b/samples/client.c index 3231e60..91ce8a0 100644 --- a/samples/client.c +++ b/samples/client.c @@ -43,9 +43,9 @@ #include #include -#include "../lib/common.h" -#include "../lib/muser.h" -#include "../lib/tran_sock.h" +#include "common.h" +#include "muser.h" +#include "tran_sock.h" #define CLIENT_MAX_FDS (32) diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c index c8d5454..d4e485f 100644 --- a/samples/gpio-pci-idio-16.c +++ b/samples/gpio-pci-idio-16.c @@ -41,9 +41,9 @@ #include #include -#include "../lib/common.h" -#include "../lib/muser.h" -#include "../lib/tran_sock.h" +#include "common.h" +#include "muser.h" +#include "tran_sock.h" static void _log(UNUSED void *pvt, UNUSED lm_log_lvl_t lvl, char const *msg) diff --git a/samples/null.c b/samples/null.c index 2dd1bdd..97c3fcf 100644 --- a/samples/null.c +++ b/samples/null.c @@ -40,9 +40,9 @@ #include #include -#include "../lib/common.h" -#include "../lib/muser.h" -#include "../lib/tran_sock.h" +#include "common.h" +#include "muser.h" +#include "tran_sock.h" static void null_log(UNUSED void *pvt, UNUSED lm_log_lvl_t lvl, char const *msg) diff --git a/samples/server.c b/samples/server.c index d0482d2..432d0ce 100644 --- a/samples/server.c +++ b/samples/server.c @@ -44,9 +44,9 @@ #include #include -#include "../lib/common.h" -#include "../lib/muser.h" -#include "../lib/tran_sock.h" +#include "common.h" +#include "muser.h" +#include "tran_sock.h" struct dma_regions { uint64_t addr; @@ -65,7 +65,7 @@ struct server_data { __u64 data_size; void *migr_data; size_t migr_data_len; - lm_migr_state_t state; + lm_migr_state_t state; } migration; }; -- cgit v1.1