Commit da231290 authored by Changpeng Liu's avatar Changpeng Liu Committed by Tomasz Zawadzki
Browse files

lib/vfu_tgt: add library for PCI device emulation



Previously SPDK use libvfio-user library to provide emulated NVMe
devices to VM, but it's limited to NVMe device type only.  Here we
add SPDK vfu_target library abstraction based on libvfio-user which
supports more PCI device types.

We will add virtio-blk and virtio-scsi devices emulation based on
vfu_tgt library in following patches, actually this library can
support NVMe emulation too, due to the fact that the NVMe emulation
is already exist, so we will keep the NVMe emulation which based on
libvfio-user directly as it is.

Change-Id: Ib0ead6c6118fa62308355fe432003dd928a2fae9
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12597


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent c7f50109
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ SPDK_LIB_LIST += event_nbd
ifeq ($(CONFIG_VHOST),y)
SPDK_LIB_LIST += event_vhost_blk event_vhost_scsi
endif
ifeq ($(CONFIG_VFIO_USER),y)
SPDK_LIB_LIST += event_vfu_tgt
endif
endif

include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
+37 −0
Original line number Diff line number Diff line
@@ -7973,6 +7973,43 @@ crdt1 | Optional | number | Command Retry Delay Time 1
crdt2                   | Optional | number      | Command Retry Delay Time 2
crdt3                   | Optional | number      | Command Retry Delay Time 3

## Vfio-user Target

### vfu_tgt_set_base_path {#rpc_vfu_tgt_set_base_path}

Set base path of Unix Domain socket file.

#### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
path                    | Required | string      | Base path

#### Example

Example request:

~~~json
{
  "params": {
    "path": "/var/run/vfu_tgt"
  },
  "jsonrpc": "2.0",
  "method": "vfu_tgt_set_base_path",
  "id": 1
}
~~~

Example response:

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": true
}
~~~

## Vhost Target {#jsonrpc_components_vhost_tgt}

The following common preconditions need to be met in all target types.
+121 −0
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (c) Intel Corporation.
 *   All rights reserved.
 */

#ifndef _VFU_TARGET_H
#define _VFU_TARGET_H

#include <vfio-user/libvfio-user.h>
#include <vfio-user/pci_defs.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*spdk_vfu_init_cb)(int rc);
typedef void (*spdk_vfu_fini_cb)(void);

void spdk_vfu_init(spdk_vfu_init_cb init_cb);
void spdk_vfu_fini(spdk_vfu_fini_cb fini_cb);

struct spdk_vfu_endpoint;

#define SPDK_VFU_MAX_NAME_LEN (64)

struct spdk_vfu_sparse_mmap {
	uint64_t offset;
	uint64_t len;
};

#define SPDK_VFU_MAXIMUM_SPARSE_MMAP_REGIONS	8

typedef ssize_t (*spdk_vfu_access_cb)(vfu_ctx_t *vfu_ctx, char *buf, size_t count, loff_t pos,
				      bool is_write);

struct spdk_vfu_pci_region {
	uint64_t offset;
	uint64_t len;
	uint64_t flags;
	uint32_t nr_sparse_mmaps;
	int fd;
	struct spdk_vfu_sparse_mmap mmaps[SPDK_VFU_MAXIMUM_SPARSE_MMAP_REGIONS];
	spdk_vfu_access_cb access_cb;
};

struct spdk_vfu_pci_device {
	struct {
		/* Vendor ID */
		uint16_t vid;
		/* Device ID */
		uint16_t did;
		/* Subsystem Vendor ID */
		uint16_t ssvid;
		/* Subsystem ID */
		uint16_t ssid;
	} id;

	struct {
		/* Base Class Code */
		uint8_t bcc;
		/* Sub Class code */
		uint8_t scc;
		/* Programming Interface */
		uint8_t pi;
	} class;

	/* Standard PCI Capabilities */
	struct pmcap pmcap;
	struct pxcap pxcap;
	struct msixcap msixcap;
	uint16_t nr_vendor_caps;

	uint16_t intr_ipin;
	uint32_t nr_int_irqs;
	uint32_t nr_msix_irqs;

	struct spdk_vfu_pci_region regions[VFU_PCI_DEV_NUM_REGIONS];
};

struct spdk_vfu_endpoint_ops {
	/* PCI device type name */
	char name[SPDK_VFU_MAX_NAME_LEN];

	void *(*init)(struct spdk_vfu_endpoint *endpoint,
		      char *basename, const char *endpoint_name);
	int (*get_device_info)(struct spdk_vfu_endpoint *endpoint,
			       struct spdk_vfu_pci_device *device_info);
	uint16_t (*get_vendor_capability)(struct spdk_vfu_endpoint *endpoint, char *buf,
					  uint16_t buf_len, uint16_t idx);
	int (*attach_device)(struct spdk_vfu_endpoint *endpoint);
	int (*detach_device)(struct spdk_vfu_endpoint *endpoint);
	int (*destruct)(struct spdk_vfu_endpoint *endpoint);

	int (*post_memory_add)(struct spdk_vfu_endpoint *endpoint, void *map_start, void *map_end);
	int (*pre_memory_remove)(struct spdk_vfu_endpoint *endpoint, void *map_start, void *map_end);
	int (*reset_device)(struct spdk_vfu_endpoint *endpoint);
	int (*quiesce_device)(struct spdk_vfu_endpoint *endpoint);
};

int spdk_vfu_register_endpoint_ops(struct spdk_vfu_endpoint_ops *ops);
int spdk_vfu_create_endpoint(const char *endpoint_name, const char *cpumask_str,
			     const char *dev_type_name);
int spdk_vfu_delete_endpoint(const char *endpoint_name);
int spdk_vfu_set_socket_path(const char *basename);
const char *spdk_vfu_get_endpoint_id(struct spdk_vfu_endpoint *endpoint);
const char *spdk_vfu_get_endpoint_name(struct spdk_vfu_endpoint *endpoint);
vfu_ctx_t *spdk_vfu_get_vfu_ctx(struct spdk_vfu_endpoint *endpoint);
void *spdk_vfu_get_endpoint_private(struct spdk_vfu_endpoint *endpoint);
bool spdk_vfu_endpoint_msix_enabled(struct spdk_vfu_endpoint *endpoint);
bool spdk_vfu_endpoint_intx_enabled(struct spdk_vfu_endpoint *endpoint);
void *spdk_vfu_endpoint_get_pci_config(struct spdk_vfu_endpoint *endpoint);
struct spdk_vfu_endpoint *spdk_vfu_get_endpoint_by_name(const char *name);
void *spdk_vfu_map_one(struct spdk_vfu_endpoint *endpoint, uint64_t addr, uint64_t len,
		       dma_sg_t *sg, struct iovec *iov, int prot);
void spdk_vfu_unmap_sg(struct spdk_vfu_endpoint *endpoint, dma_sg_t *sg, struct iovec *iov,
		       int iovcnt);
#ifdef __cplusplus
}
#endif

#endif
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ DIRS-$(CONFIG_VHOST) += vhost
DIRS-$(CONFIG_VIRTIO) += virtio
DIRS-$(CONFIG_REDUCE) += reduce
DIRS-$(CONFIG_RDMA) += rdma
DIRS-$(CONFIG_VFIO_USER) += vfio_user
DIRS-$(CONFIG_VFIO_USER) += vfio_user vfu_tgt

# If CONFIG_ENV is pointing at a directory in lib, build it.
# Out-of-tree env implementations must be built separately by the user.

lib/vfu_tgt/Makefile

0 → 100644
+21 −0
Original line number Diff line number Diff line
#  SPDX-License-Identifier: BSD-3-Clause
#  Copyright (c) Intel Corporation.
#  All rights reserved.
#

SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 1
SO_MINOR := 0

C_SRCS += tgt_endpoint.c tgt_rpc.c
CFLAGS += -I$(VFIO_USER_INCLUDE_DIR)
LDFLAGS += -L$(VFIO_USER_LIBRARY_DIR)
LOCAL_SYS_LIBS += -lvfio-user -ljson-c

LIBNAME = vfu_tgt

SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_vfu_tgt.map)

include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
Loading