28 #include <linux/vfio.h>
32 #include <sys/ioctl.h>
38 #define VFIO_GROUP_MAX_PATH 128
39 #define VFIO_CONTAINER_PATH "/dev/vfio/vfio"
40 #define VFIO_GROUP_PATH_FORMAT "/dev/vfio/%d"
53 int vfio_api_version = ioctl(container_fd, VFIO_GET_API_VERSION);
54 if (vfio_api_version != VFIO_API_VERSION) {
55 DOCA_LOG_ERR(
"VFIO API version mismatch. compiled with %d, but runtime is %d",
61 if (ioctl(container_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU) == 0) {
62 DOCA_LOG_ERR(
"VFIO Type 1 IOMMU extension not supported");
66 struct vfio_group_status group_status = {.argsz =
sizeof(group_status)};
68 int status = ioctl(group_fd, VFIO_GROUP_GET_STATUS, &group_status);
70 DOCA_LOG_ERR(
"Failed to get status of VFIO group. Status=%d, errno=%d", status, errno);
74 if ((group_status.flags & VFIO_GROUP_FLAGS_VIABLE) == 0) {
75 DOCA_LOG_ERR(
"VFIO group not viable. Not all devices in IOMMU group are bound to vfio driver");
91 int status = ioctl(group_fd, VFIO_GROUP_SET_CONTAINER, &container_fd);
93 DOCA_LOG_ERR(
"Failed to set group for container. Status=%d, errno=%d", status, errno);
97 status = ioctl(container_fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU);
99 DOCA_LOG_ERR(
"Failed to set IOMMU type 1 extension for container. Status=%d, errno=%d", status, errno);
114 struct vfio_region_info reg = {.argsz =
sizeof(reg)};
116 reg.index = VFIO_PCI_CONFIG_REGION_INDEX;
118 int status = ioctl(
resources->device_fd, VFIO_DEVICE_GET_REGION_INFO, ®);
120 DOCA_LOG_ERR(
"Failed to get Config Region info. Status=%d, errno=%d", status, errno);
125 if (pwrite(
resources->device_fd, &cmd, 2, reg.offset + 0x4) != 2) {
126 DOCA_LOG_ERR(
"Failed to enable PCI cmd. Failed to write to Config Region Space. Status=%d, errno=%d",
141 DOCA_LOG_ERR(
"Failed to open VFIO container. errno=%d", errno);
147 resources->group_fd = open(vfio_group_path, O_RDWR);
149 DOCA_LOG_ERR(
"Failed to open VFIO group. errno=%d", errno);
159 resources->device_fd = ioctl(
resources->group_fd, VFIO_GROUP_GET_DEVICE_FD, pci_address);
161 DOCA_LOG_ERR(
"Failed to get device fd. errno=%d", errno);
175 struct vfio_region_info reg = {.argsz =
sizeof(reg)};
179 int status = ioctl(
resources->device_fd, VFIO_DEVICE_GET_REGION_INFO, ®);
181 DOCA_LOG_ERR(
"Failed to get Bar Region info. Status=%d, errno=%d", status, errno);
188 "The provided stateful region exceeds the boundaries of the emulated device's bar. At bar %d, the size is %lluB, but requested to map region with start address %zu, and size of %zuB",
196 uint8_t *mem =
mmap(0,
198 PROT_READ | PROT_WRITE,
202 if (mem == MAP_FAILED) {
203 DOCA_LOG_ERR(
"Failed to memory map bar region: bar %d start address %zu size %zuB",
211 mapped_mem->
mem = mem;
241 DOCA_LOG_ERR(
"Entered device PCI address exceeding the maximum size of %d",
247 DOCA_LOG_ERR(
"Entered device PCI address does not match supported format: XXXX:XX:XX.X");
251 strncpy(parsed_addr,
addr, addr_len - 1);
252 parsed_addr[addr_len - 1] = 0;
259 struct doca_argp_param *param;
284 struct doca_argp_param *vfio_group_param;
309 struct doca_argp_param *region_index_param;
static doca_error_t pci_callback(void *param, void *config)
static doca_error_t vfio_group_callback(void *param, void *config)
void devemu_host_resources_cleanup(struct devemu_host_resources *resources)
#define VFIO_CONTAINER_PATH
doca_error_t register_vfio_group_param(doca_argp_param_cb_t vfio_group_callback)
doca_error_t register_region_index_param(const char *description, doca_argp_param_cb_t region_callback)
#define VFIO_GROUP_PATH_FORMAT
static bool enable_pci_cmd(struct devemu_host_resources *resources)
doca_error_t register_emulated_pci_address_param(doca_argp_param_cb_t pci_callback)
static bool validate_vfio_group_and_container(int group_fd, int container_fd)
doca_error_t parse_emulated_pci_address(const char *addr, char *parsed_addr)
static bool add_vfio_group_to_container(int group_fd, int container_fd)
doca_error_t map_bar_region_memory(struct devemu_host_resources *resources, const struct bar_region_config *bar_region_config, struct bar_mapped_region *mapped_mem)
DOCA_LOG_REGISTER(DEVEMU_PCI_HOST_COMMON)
#define VFIO_GROUP_MAX_PATH
doca_error_t init_vfio_device(struct devemu_host_resources *resources, int vfio_group, const char *pci_address)
struct rdma_resources resources
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
doca_error_t(* doca_argp_param_cb_t)(void *, void *)
Flag callback function type.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
#define DOCA_DEVINFO_PCI_ADDR_SIZE
Buffer size to hold PCI BDF format: "XXXX:XX:XX.X". Including a null terminator.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
@ DOCA_ERROR_NOT_SUPPORTED
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.