All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chenbo Xia <chenbo.xia@intel.com>
To: dev@dpdk.org, thomas@monjalon.net, david.marchand@redhat.com
Cc: stephen@networkplumber.org, cunming.liang@intel.com,
	xiuchun.lu@intel.com, miao.li@intel.com, jingjing.wu@intel.com
Subject: [dpdk-dev] [PATCH v2 5/8] emu/iavf: add resource management and internal logic of iavf
Date: Sat, 19 Dec 2020 14:28:03 +0800	[thread overview]
Message-ID: <20201219062806.56477-6-chenbo.xia@intel.com> (raw)
In-Reply-To: <20201219062806.56477-1-chenbo.xia@intel.com>

This patch adds the allocation and release of device resources.
Device resources include PCI BARs' memory and interrupt related
resources. Device internal logic is also added.

Signed-off-by: Chenbo Xia <chenbo.xia@intel.com>
Signed-off-by: Xiuchun Lu <xiuchun.lu@intel.com>
---
 drivers/emu/iavf/iavf_emu.c       |   1 +
 drivers/emu/iavf/iavf_emudev.c    |  20 +
 drivers/emu/iavf/iavf_vfio_user.c | 669 ++++++++++++++++++++++++++++++
 drivers/emu/iavf/iavf_vfio_user.h |  41 ++
 drivers/emu/iavf/meson.build      |   8 +
 5 files changed, 739 insertions(+)

diff --git a/drivers/emu/iavf/iavf_emu.c b/drivers/emu/iavf/iavf_emu.c
index dfd9796920..c1a702d744 100644
--- a/drivers/emu/iavf/iavf_emu.c
+++ b/drivers/emu/iavf/iavf_emu.c
@@ -18,6 +18,7 @@ static int iavf_emu_dev_close(struct rte_emudev *dev)
 	}
 
 	iavf = (struct iavf_emudev *)dev->priv_data;
+	iavf_emu_uninit_vfio_user(iavf);
 	iavf_emu_unregister_vfio_user(iavf);
 	iavf_emu_uninit_device(iavf);
 	dev->priv_data = NULL;
diff --git a/drivers/emu/iavf/iavf_emudev.c b/drivers/emu/iavf/iavf_emudev.c
index fbbe3d95a7..70cf558eef 100644
--- a/drivers/emu/iavf/iavf_emudev.c
+++ b/drivers/emu/iavf/iavf_emudev.c
@@ -178,10 +178,30 @@ rte_emu_iavf_probe(struct rte_vdev_device *dev)
 		goto err_reg;
 	}
 
+	ret = iavf_emu_init_vfio_user(iavf);
+	if (ret) {
+		EMU_IAVF_LOG(ERR,
+			"Emulated iavf failed to init vfio user.\n");
+		ret = -1;
+		goto err_init;
+	}
+
+	ret = iavf_emu_start_vfio_user(iavf);
+	if (ret) {
+		EMU_IAVF_LOG(ERR,
+			"Emulated iavf failed to start vfio user.\n");
+		ret = -1;
+		goto err_start;
+	}
+
 	edev->started = 1;
 	rte_kvargs_free(kvlist);
 	return 0;
 
+err_start:
+	iavf_emu_uninit_vfio_user(iavf);
+err_init:
+	iavf_emu_unregister_vfio_user(iavf);
 err_reg:
 	iavf_emu_uninit_device(iavf);
 err_ndev:
diff --git a/drivers/emu/iavf/iavf_vfio_user.c b/drivers/emu/iavf/iavf_vfio_user.c
index aae47de9f3..a4208de618 100644
--- a/drivers/emu/iavf/iavf_vfio_user.c
+++ b/drivers/emu/iavf/iavf_vfio_user.c
@@ -2,13 +2,36 @@
  * Copyright(c) 2020 Intel Corporation
  */
 
+#include <linux/pci.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <pthread.h>
+#include <sys/types.h>
 
 #include <rte_malloc.h>
+#include <rte_emudev.h>
+#include <rte_memcpy.h>
 
 #include "iavf_vfio_user.h"
 #include <iavf_type.h>
 
+#define STORE_LE16(addr, val)   (*(__u16 *)addr = val)
+#define STORE_LE32(addr, val)   (*(__u32 *)addr = val)
+
+#define IAVF_EMU_BAR0_SIZE 0x10000
+#define IAVF_EMU_BAR3_SIZE 0x1000
+#define IAVF_EMU_BAR_SIZE_MASK 0xffffffff
+#define IAVF_EMU_BAR_MASK(sz) (~(sz) + 1)
+#define IAVF_EMU_MSIX_TABLE_SIZE 0x5
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_SUBDEVICE_ID 0x1100
+#define PCI_CLASS_ETHERNET 0x0200
+
 struct iavf_emu_sock_list {
 	TAILQ_ENTRY(iavf_emu_sock_list) next;
 	struct rte_emudev *emu_dev;
@@ -174,6 +197,14 @@ static int iavf_emu_setup_queues(struct iavf_emudev *dev)
 	return 0;
 }
 
+static inline void iavf_emu_cleanup_queues(struct iavf_emudev *dev)
+{
+	memset(&dev->adq, 0, RTE_IAVF_EMU_ADMINQ_NUM *
+		sizeof(struct iavf_emu_adminQ));
+
+	rte_free(dev->lanq);
+}
+
 static inline void iavf_emu_reset_queues(struct iavf_emudev *dev)
 {
 	memset(&dev->adq, 0, RTE_IAVF_EMU_ADMINQ_NUM *
@@ -191,6 +222,576 @@ static void iavf_emu_reset_all_resources(struct iavf_emudev *dev)
 	iavf_emu_reset_regions(dev);
 }
 
+static int iavf_emu_init_dev(struct iavf_emudev *dev)
+{
+	struct iavf_emu_vfio_user *vfio;
+	struct vfio_device_info *dev_info;
+	struct rte_vfio_user_regions *reg;
+	struct rte_vfio_user_irq_info *irq;
+	struct vfio_region_info_cap_sparse_mmap *sparse;
+	int ret;
+	uint32_t i, j;
+
+	vfio = rte_zmalloc_socket("vfio", sizeof(*vfio), 0, dev->numa_node);
+	if (!vfio) {
+		EMU_IAVF_LOG(ERR, "Failed to alloc iavf_emu_vfio_user\n");
+		ret = -1;
+		goto exit;
+	}
+
+	dev_info = rte_zmalloc_socket("vfio_dev_info",
+		sizeof(*dev_info), 0, dev->numa_node);
+	if (!dev_info) {
+		EMU_IAVF_LOG(ERR, "Failed to alloc vfio dev_info\n");
+		ret = -1;
+		goto err_info;
+	}
+	dev_info->argsz = sizeof(*dev_info);
+	dev_info->flags = VFIO_DEVICE_FLAGS_PCI | VFIO_DEVICE_FLAGS_RESET;
+	dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
+	dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
+
+	reg = rte_zmalloc_socket("vfio_user_regions",
+		sizeof(*reg) + dev_info->num_regions *
+		sizeof(struct rte_vfio_user_reg_info), 0, dev->numa_node);
+	if (!reg) {
+		EMU_IAVF_LOG(ERR, "Failed to alloc vfio_user_regions\n");
+		ret = -1;
+		goto err_reg;
+	}
+	reg->reg_num = dev_info->num_regions;
+
+	for (i = 0; i < reg->reg_num; i++) {
+		struct rte_vfio_user_reg_info *vinfo = &reg->reg_info[i];
+		size_t sz = sizeof(struct vfio_region_info);
+
+		/* BAR0 has two sparse mmap area */
+		if (i == VFIO_PCI_BAR0_REGION_INDEX)
+			sz += sizeof(*sparse) + 2 * sizeof(*sparse->areas);
+
+		vinfo->info = rte_zmalloc_socket("vfio_region_info",
+			sz, 0, dev->numa_node);
+		if (!vinfo->info) {
+			EMU_IAVF_LOG(ERR, "Failed to alloc region info "
+				"for region %d\n", i);
+			ret = -1;
+			goto err_reg_alloc;
+		}
+
+		vinfo->info->index = i;
+
+		switch (i) {
+		case VFIO_PCI_CONFIG_REGION_INDEX:
+			vinfo->info->argsz = sz;
+			vinfo->info->offset = 0;
+			vinfo->info->size = IAVF_EMU_CFG_SPACE_SIZE;
+			vinfo->info->flags = VFIO_REGION_INFO_FLAG_READ |
+				       VFIO_REGION_INFO_FLAG_WRITE;
+			break;
+		case VFIO_PCI_BAR0_REGION_INDEX:
+			vinfo->info->argsz = sz;
+			vinfo->info->offset = 0;
+			vinfo->info->size = IAVF_EMU_BAR0_SIZE;
+			vinfo->info->flags  = VFIO_REGION_INFO_FLAG_READ |
+				       VFIO_REGION_INFO_FLAG_WRITE |
+				       VFIO_REGION_INFO_FLAG_MMAP |
+				       VFIO_REGION_INFO_FLAG_CAPS;
+			vinfo->info->cap_offset =
+						sizeof(struct vfio_region_info);
+
+			sparse = (struct vfio_region_info_cap_sparse_mmap *)
+						((uint8_t *)vinfo->info +
+						vinfo->info->cap_offset);
+			sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
+			sparse->header.version = 1;
+			sparse->nr_areas = 2;
+			sparse->areas[0].offset = 0;
+			sparse->areas[0].size = 0x3000;
+			sparse->areas[1].offset = 0x6000;
+			sparse->areas[1].size = IAVF_EMU_BAR0_SIZE - 0x6000;
+
+			break;
+		case VFIO_PCI_BAR3_REGION_INDEX:
+			vinfo->info->argsz = sz;
+			vinfo->info->offset = 0;
+			vinfo->info->size = IAVF_EMU_BAR3_SIZE;
+			vinfo->info->flags  = VFIO_REGION_INFO_FLAG_READ |
+				       VFIO_REGION_INFO_FLAG_WRITE |
+				       VFIO_REGION_INFO_FLAG_MMAP;
+			break;
+		default:
+			vinfo->info->argsz = sz;
+			vinfo->info->offset = 0;
+			vinfo->info->size = 0;
+			vinfo->info->flags = 0;
+		}
+	}
+
+	irq = rte_zmalloc_socket("vfio_user_irq_info", sizeof(*irq) +
+		VFIO_PCI_NUM_IRQS * sizeof(struct vfio_irq_info),
+		0, dev->numa_node);
+	if (!irq) {
+		EMU_IAVF_LOG(ERR, "Failed to alloc vfio_user_irqs\n");
+		ret = -1;
+		goto err_irq;
+	}
+	irq->irq_num = VFIO_PCI_NUM_IRQS;
+
+	for (i = 0; i < VFIO_PCI_NUM_IRQS; i++) {
+		irq->irq_info[i].index = i;
+		irq->irq_info[i].flags =
+			VFIO_IRQ_INFO_EVENTFD | VFIO_IRQ_INFO_NORESIZE;
+		if (i == VFIO_PCI_MSIX_IRQ_INDEX)
+			irq->irq_info[i].count =
+				IAVF_EMU_MSIX_TABLE_SIZE + 1;
+		else if (i == VFIO_PCI_ERR_IRQ_INDEX)
+			irq->irq_info[i].count = 1;
+		else
+			irq->irq_info[i].count = 0;
+	}
+
+	vfio->dev_info = dev_info;
+	vfio->reg = reg;
+	vfio->irq = irq;
+	dev->vfio = vfio;
+
+	return 0;
+
+err_irq:
+err_reg_alloc:
+	for (j = 0; j < i; j++)
+		rte_free(reg->reg_info[j].info);
+	rte_free(reg);
+err_reg:
+	rte_free(dev_info);
+err_info:
+	rte_free(vfio);
+exit:
+	return ret;
+}
+
+static int iavf_emu_uninit_dev(struct iavf_emudev *dev)
+{
+	struct iavf_emu_vfio_user *vfio;
+	struct rte_vfio_user_regions *reg;
+	uint32_t i;
+
+	if (!dev->vfio)
+		return -1;
+
+	vfio = dev->vfio;
+	rte_free(vfio->dev_info);
+
+	reg = vfio->reg;
+	for (i = 0; i < reg->reg_num; i++)
+		rte_free(reg->reg_info[i].info);
+	rte_free(reg);
+
+	rte_free(vfio->irq);
+	rte_free(vfio);
+
+	return 0;
+}
+
+static int handle_pci_cmd_write(struct iavf_emu_pci_hdr *hdr,
+	char *buf, size_t count)
+{
+	/* Below are all R/W bits in command register */
+	uint16_t rw_bitmask = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER | PCI_COMMAND_PARITY |
+		PCI_COMMAND_SERR | PCI_COMMAND_INTX_DISABLE;
+	uint16_t val;
+
+	if (count != 2) {
+		EMU_IAVF_LOG(ERR, "Wrong write count (%lu) for PCI_COMMAND\n",
+			count);
+		return -1;
+	}
+
+	val = *(uint16_t *)buf;
+	/* Only write the R/W bits */
+	hdr->cmd = (rw_bitmask & val) | (~rw_bitmask & hdr->cmd);
+
+	return 2;
+}
+
+static int handle_pci_status_write(struct iavf_emu_pci_hdr *hdr,
+	char *buf, size_t count)
+{
+	/* Below are all write-1-to-clear bits in status register */
+	uint16_t rw1c_bitmask = PCI_STATUS_PARITY |
+		PCI_STATUS_SIG_TARGET_ABORT |
+		PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT |
+		PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY;
+	uint16_t val;
+
+	if (count != 2) {
+		EMU_IAVF_LOG(ERR, "Wrong write count (%lu) for PCI_STATUS\n",
+			count);
+		return -1;
+	}
+
+	val = *(uint16_t *)buf;
+	/* Clear the write-1-to-clear bits*/
+	hdr->status = ~(rw1c_bitmask & val) & hdr->status;
+
+	return 2;
+}
+
+static int handle_pci_bar_write(struct iavf_emu_pci_hdr *hdr,
+	char *buf, size_t count, loff_t pos)
+{
+	uint32_t val, size;
+	uint8_t idx;
+
+	if (count != 4) {
+		EMU_IAVF_LOG(ERR, "Wrong write count (%lu) for "
+			"Base Address Register\n",
+			count);
+		return -1;
+	}
+
+	val = *(uint32_t *)buf;
+
+	if (pos == PCI_BASE_ADDRESS_0)
+		size = IAVF_EMU_BAR0_SIZE;
+	else if (pos == PCI_BASE_ADDRESS_3)
+		size = IAVF_EMU_BAR3_SIZE;
+	else
+		size = 0;
+
+	if (val == IAVF_EMU_BAR_SIZE_MASK)
+		val &= IAVF_EMU_BAR_MASK(size);
+
+	idx = (pos - PCI_BASE_ADDRESS_0) / 0x4;
+	hdr->bar[idx] |= val & ~PCI_BASE_ADDRESS_MEM_MASK;
+
+	return 4;
+}
+
+static int handle_cfg_write(struct iavf_emu_pci_hdr *hdr,
+	char *buf, size_t count, loff_t pos)
+{
+	int ret = count;
+
+	switch (pos) {
+	case PCI_COMMAND:
+		ret = handle_pci_cmd_write(hdr, buf, count);
+		break;
+	case PCI_STATUS:
+		ret = handle_pci_status_write(hdr, buf, count);
+		break;
+	case PCI_INTERRUPT_LINE:
+		if (count != 1) {
+			EMU_IAVF_LOG(ERR, "Wrong write count (%lu)"
+				"for PCI_INTERRUPT_LINE\n",
+				count);
+			return -1;
+		}
+		hdr->intrl = *(uint8_t *)buf;
+		ret = 1;
+		break;
+	case PCI_BASE_ADDRESS_0:
+		/* FALLTHROUGH */
+	case PCI_BASE_ADDRESS_1:
+		/* FALLTHROUGH */
+	case PCI_BASE_ADDRESS_2:
+		/* FALLTHROUGH */
+	case PCI_BASE_ADDRESS_3:
+		/* FALLTHROUGH */
+	case PCI_BASE_ADDRESS_4:
+		/* FALLTHROUGH */
+	case PCI_BASE_ADDRESS_5:
+		ret = handle_pci_bar_write(hdr, buf, count, pos);
+		break;
+	default:
+		EMU_IAVF_LOG(INFO, "Write request for cfg (pos: %ld) ignored\n",
+			pos);
+		break;
+	}
+
+	return ret;
+}
+
+static ssize_t iavf_emu_cfg_rw(struct rte_vfio_user_reg_info *reg, char *buf,
+	size_t count, loff_t pos, bool iswrite)
+{
+	struct iavf_emu_cfg_space *cfg;
+	char *reg_pos;
+	int ret = 0;
+
+	if (!reg->base) {
+		EMU_IAVF_LOG(ERR, "Config space not exist\n");
+		return -EFAULT;
+	}
+
+	if (pos + count > reg->info->size) {
+		EMU_IAVF_LOG(ERR, "Access exceeds config space size\n");
+		return -EINVAL;
+	}
+
+	cfg = (struct iavf_emu_cfg_space *)reg->base;
+	reg_pos = (char *)reg->base + pos;
+
+	if (!iswrite) {
+		rte_memcpy(buf, reg_pos, count);
+		ret = count;
+	} else {
+		ret = handle_cfg_write(&cfg->hdr, buf, count, pos);
+		if (ret < 0) {
+			EMU_IAVF_LOG(ERR, "Failed to write cfg space\n");
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int iavf_emu_init_cfg_space(struct rte_vfio_user_reg_info *vinfo,
+	unsigned int numa_node)
+{
+	char *v_cfg;
+
+	vinfo->base = rte_zmalloc_socket("cfg space",
+		IAVF_EMU_CFG_SPACE_SIZE,
+		0, numa_node);
+	if (!vinfo->base) {
+		EMU_IAVF_LOG(ERR, "Failed to alloc cfg space\n");
+		return -1;
+	}
+	vinfo->rw = iavf_emu_cfg_rw;
+	vinfo->fd = -1;
+	vinfo->priv = NULL;
+
+	v_cfg = (char *)vinfo->base;
+
+	STORE_LE16((uint16_t *)&v_cfg[PCI_VENDOR_ID],
+		PCI_VENDOR_ID_INTEL);
+	STORE_LE16((uint16_t *)&v_cfg[PCI_DEVICE_ID],
+		IAVF_DEV_ID_ADAPTIVE_VF);
+	STORE_LE16((uint16_t *)&v_cfg[PCI_SUBSYSTEM_VENDOR_ID],
+		PCI_VENDOR_ID_INTEL);
+	STORE_LE16((uint16_t *)&v_cfg[PCI_SUBSYSTEM_ID],
+		   PCI_SUBDEVICE_ID);
+
+	STORE_LE16((uint16_t *)&v_cfg[PCI_COMMAND],
+		   PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	STORE_LE16((uint16_t *)&v_cfg[PCI_CLASS_DEVICE],
+		   PCI_CLASS_ETHERNET);
+	v_cfg[PCI_CLASS_REVISION] = 0x01;
+
+	STORE_LE16((uint16_t *)&v_cfg[PCI_STATUS],
+			   PCI_STATUS_CAP_LIST);
+
+	STORE_LE32((uint32_t *)&v_cfg[PCI_BASE_ADDRESS_0],
+		   PCI_BASE_ADDRESS_SPACE_MEMORY |
+		   PCI_BASE_ADDRESS_MEM_TYPE_32	 |
+		   PCI_BASE_ADDRESS_MEM_PREFETCH);
+
+	STORE_LE32((uint32_t *)&v_cfg[PCI_BASE_ADDRESS_3],
+		   PCI_BASE_ADDRESS_SPACE_MEMORY |
+		   PCI_BASE_ADDRESS_MEM_TYPE_32);
+
+	STORE_LE16((uint16_t *)&v_cfg[PCI_CAPABILITY_LIST],
+			   0x70);
+	STORE_LE16((uint16_t *)&v_cfg[0x70],
+			   PCI_CAP_ID_MSIX);
+
+	STORE_LE16((uint16_t *)&v_cfg[0x70 + PCI_MSIX_FLAGS],
+			(IAVF_EMU_MSIX_TABLE_SIZE & PCI_MSIX_FLAGS_QSIZE) |
+			PCI_MSIX_FLAGS_ENABLE);
+
+	STORE_LE32((uint32_t *)&v_cfg[0x70 + PCI_MSIX_TABLE],
+			   (0x3 & PCI_MSIX_TABLE_BIR));
+
+	STORE_LE32((uint32_t *)&v_cfg[0x70 + PCI_MSIX_PBA],
+			(0x3 & PCI_MSIX_PBA_BIR) |
+			(0x100 & PCI_MSIX_PBA_OFFSET));
+
+	return 0;
+}
+
+static inline void iavf_emu_uninit_cfg_space(
+	struct rte_vfio_user_reg_info *vinfo)
+{
+	rte_free(vinfo->base);
+	vinfo->rw = NULL;
+	vinfo->info->size = 0;
+	vinfo->fd = -1;
+}
+static ssize_t iavf_emu_bar0_rw(struct rte_vfio_user_reg_info *reg, char *buf,
+	size_t count, loff_t pos, bool iswrite)
+{
+	struct iavf_emudev *dev = (struct iavf_emudev *)reg->priv;
+	char *reg_pos;
+
+	if (!reg->base) {
+		EMU_IAVF_LOG(ERR, "BAR 0 does not exist\n");
+		return -EFAULT;
+	}
+
+	if (pos + count > reg->info->size) {
+		EMU_IAVF_LOG(ERR, "Access exceeds BAR 0 size\n");
+		return -EINVAL;
+	}
+
+	reg_pos = (char *)reg->base + pos;
+
+	if (!iswrite) {
+		rte_memcpy(buf, reg_pos, count);
+	} else {
+		int tmp;
+		uint32_t val;
+		int idx = -1;
+
+		if (count != 4)
+			return -EINVAL;
+
+		val = *(uint32_t *)buf;
+		/* Only handle interrupt enable/disable for now */
+		if (pos == IAVF_VFINT_DYN_CTL01) {
+			tmp = val & IAVF_VFINT_DYN_CTL01_INTENA_MASK;
+			idx = 0;
+		} else if ((pos >= IAVF_VFINT_DYN_CTLN1(0)) && pos <=
+			IAVF_VFINT_DYN_CTLN1(RTE_IAVF_EMU_MAX_INTR - 1)) {
+			tmp = val & IAVF_VFINT_DYN_CTLN1_INTENA_MASK;
+			idx = pos - IAVF_VFINT_DYN_CTLN1(0);
+			if (idx % 4)
+				return -EINVAL;
+			idx = idx / 4;
+		}
+
+		if (idx != -1 &&
+			tmp != dev->intr->info[idx].enable && dev->ready) {
+			dev->ops->update_status(dev->edev);
+			dev->intr->info[idx].enable = tmp;
+		}
+
+		rte_memcpy(reg_pos, buf, count);
+	}
+
+	return count;
+}
+
+static int iavf_emu_alloc_reg(struct iavf_emudev *dev)
+{
+	struct rte_vfio_user_regions *reg = dev->vfio->reg;
+	struct rte_vfio_user_reg_info *vinfo;
+	char shm_str[64];
+	uint32_t i;
+	int ret;
+
+	for (i = 0; i < reg->reg_num; i++) {
+		vinfo = &reg->reg_info[i];
+
+		switch (i) {
+		case VFIO_PCI_CONFIG_REGION_INDEX:
+			ret = iavf_emu_init_cfg_space(vinfo, dev->numa_node);
+			if (ret)
+				return ret;
+			break;
+		case VFIO_PCI_BAR0_REGION_INDEX:
+		case VFIO_PCI_BAR3_REGION_INDEX:
+			sprintf(shm_str, "AVF%d_BAR%d",
+				dev->edev->dev_id, i);
+			vinfo->fd = shm_open(shm_str,
+				O_RDWR|O_CREAT, 0700);
+			if (vinfo->fd == -1) {
+				EMU_IAVF_LOG(ERR,
+					"Failed to open shm for BAR %d\n", i);
+				goto exit;
+			}
+
+			if (ftruncate(vinfo->fd, vinfo->info->size) == -1) {
+				EMU_IAVF_LOG(ERR,
+					"Failed to ftruncate BAR %d\n", i);
+				ret = -1;
+				goto exit;
+			}
+
+			vinfo->base = mmap(NULL, vinfo->info->size,
+					PROT_READ | PROT_WRITE,
+					MAP_SHARED, vinfo->fd, 0);
+			memset(vinfo->base, 0, vinfo->info->size);
+			if (vinfo->base == MAP_FAILED) {
+				EMU_IAVF_LOG(ERR,
+					"Failed to mmap BAR %d\n", i);
+				ret = -1;
+				goto exit;
+			}
+			vinfo->priv = (void *)dev;
+			if (i == VFIO_PCI_BAR0_REGION_INDEX)
+				vinfo->rw = iavf_emu_bar0_rw;
+			else
+				vinfo->rw = NULL;
+			break;
+		default:
+			vinfo->base = NULL;
+			vinfo->rw = NULL;
+			vinfo->fd = -1;
+			vinfo->priv = NULL;
+			break;
+		}
+	}
+
+	return 0;
+
+exit:
+	for (;; i--) {
+		vinfo = &reg->reg_info[i];
+
+		if (i == VFIO_PCI_CONFIG_REGION_INDEX)
+			iavf_emu_uninit_cfg_space(vinfo);
+
+		if (!vinfo->info->size) {
+			if (!vinfo->base)
+				munmap(vinfo->base, vinfo->info->size);
+			if (vinfo->fd > 0) {
+				close(vinfo->fd);
+				sprintf(shm_str, "AVF%d_BAR%d",
+					dev->edev->dev_id, i);
+				shm_unlink(shm_str);
+				vinfo->fd = -1;
+			}
+		}
+
+		if (i == 0)
+			break;
+	}
+	return ret;
+}
+
+static void iavf_emu_free_reg(struct iavf_emudev *dev)
+{
+	struct rte_vfio_user_regions *reg = dev->vfio->reg;
+	struct rte_vfio_user_reg_info *vinfo;
+	char shm_str[64];
+	uint32_t i;
+
+	for (i = 0; i < reg->reg_num; i++) {
+		vinfo = &reg->reg_info[i];
+
+		switch (i) {
+		case VFIO_PCI_CONFIG_REGION_INDEX:
+			iavf_emu_uninit_cfg_space(vinfo);
+			break;
+		case VFIO_PCI_BAR0_REGION_INDEX:
+			/* FALLTHROUGH */
+		case VFIO_PCI_BAR3_REGION_INDEX:
+			munmap(vinfo->base, vinfo->info->size);
+			close(vinfo->fd);
+			vinfo->fd = -1;
+			sprintf(shm_str, "AVF%d_BAR%d",
+				dev->edev->dev_id, i);
+			shm_unlink(shm_str);
+			vinfo->info->size = 0;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 static inline struct iavf_emu_sock_list *
 iavf_emu_find_sock_list(char *sock_addr)
 {
@@ -382,3 +983,71 @@ int iavf_emu_unregister_vfio_user(struct iavf_emudev *dev)
 
 	return 0;
 }
+
+int iavf_emu_init_vfio_user(struct iavf_emudev *dev)
+{
+	int ret;
+	struct iavf_emu_sock_list *list;
+
+	if (iavf_emu_init_dev(dev)) {
+		EMU_IAVF_LOG(ERR, "Emulated iavf dev init failed.\n");
+		ret = -1;
+		goto exit;
+	}
+
+	if (iavf_emu_alloc_reg(dev)) {
+		EMU_IAVF_LOG(ERR, "Emulated iavf alloc region failed.\n");
+		ret = -1;
+		goto err_alloc_reg;
+	}
+
+	ret = rte_vfio_user_set_dev_info(dev->sock_addr, dev->vfio->dev_info);
+	if (ret) {
+		EMU_IAVF_LOG(ERR, "Failed to set vfio dev info\n");
+		goto err_set;
+	}
+
+	ret = rte_vfio_user_set_reg_info(dev->sock_addr, dev->vfio->reg);
+	if (ret) {
+		EMU_IAVF_LOG(ERR, "Failed to set vfio region info\n");
+		goto err_set;
+	}
+
+	ret = rte_vfio_user_set_irq_info(dev->sock_addr, dev->vfio->irq);
+	if (ret) {
+		EMU_IAVF_LOG(ERR, "Failed to set vfio irq info\n");
+		goto err_set;
+	}
+
+	list = rte_zmalloc_socket("list", sizeof(*list), 0, dev->numa_node);
+	list->emu_dev = dev->edev;
+	pthread_mutex_lock(&sock_list_lock);
+	TAILQ_INSERT_TAIL(&sock_list, list, next);
+	pthread_mutex_unlock(&sock_list_lock);
+
+	return 0;
+
+err_set:
+	iavf_emu_free_reg(dev);
+err_alloc_reg:
+	iavf_emu_uninit_dev(dev);
+exit:
+	return ret;
+}
+
+void iavf_emu_uninit_vfio_user(struct iavf_emudev *dev)
+{
+	iavf_emu_free_reg(dev);
+	iavf_emu_uninit_dev(dev);
+}
+
+int iavf_emu_start_vfio_user(struct iavf_emudev *dev)
+{
+	int ret;
+
+	ret = rte_vfio_user_start(dev->sock_addr);
+	if (ret)
+		EMU_IAVF_LOG(ERR, "Start vfio user failed.\n");
+
+	return ret;
+}
diff --git a/drivers/emu/iavf/iavf_vfio_user.h b/drivers/emu/iavf/iavf_vfio_user.h
index aa2f3edc87..2ccb04eb48 100644
--- a/drivers/emu/iavf/iavf_vfio_user.h
+++ b/drivers/emu/iavf/iavf_vfio_user.h
@@ -5,12 +5,53 @@
 #ifndef _IAVF_VFIO_USER_H
 #define _IAVF_VFIO_USER_H
 
+#include <linux/pci_regs.h>
+
 #include <rte_vfio_user.h>
 
 #include "iavf_emu_internal.h"
 
+#define IAVF_EMU_CFG_SPACE_SIZE 0x100
+
+struct iavf_emu_pci_hdr {
+	uint16_t vid;		/* Vendor ID */
+	uint16_t did;		/* Device ID */
+	uint16_t cmd;		/* Command */
+	uint16_t status;	/* Status */
+	uint8_t rid;		/* Revision ID */
+	uint8_t cc_pi;		/* Program I/F in Class Code*/
+	uint8_t cc_sub;		/* Sub-Class Code */
+	uint8_t cc_base;	/* Base Class Code */
+	uint8_t cl_size;	/* Cache Line Size*/
+	uint8_t lt_timer;	/* Latency Timer */
+	uint8_t hdr_type;	/* Header Type */
+	uint8_t bist;		/* BIST */
+	uint32_t bar[6];	/* Base Address Registers */
+	uint32_t ccp;		/* Cardbus CIC Pointer */
+	uint16_t sub_vid;	/* Subsystem Vendor ID */
+	uint16_t sub_sid;	/* Subsystem ID */
+	uint32_t rom;		/* Expansion ROM Base Address */
+	uint8_t cap;		/* Capabilities Pointer */
+	uint8_t rsvd[7];	/* Reserved */
+	uint8_t intrl;		/* Interrupt Line */
+	uint8_t intrp;		/* Interrupt Pin */
+	uint8_t min_gnt;	/* Min_Gnt Register */
+	uint8_t max_lat;	/* Max_Lat Register */
+} __attribute((packed));
+
+struct iavf_emu_cfg_space {
+	struct iavf_emu_pci_hdr hdr;
+	uint8_t cfg_non_std[IAVF_EMU_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF];
+} __attribute((packed));
+
 int iavf_emu_register_vfio_user(struct iavf_emudev *dev);
 
 int iavf_emu_unregister_vfio_user(struct iavf_emudev *dev);
 
+int iavf_emu_init_vfio_user(struct iavf_emudev *dev);
+
+void iavf_emu_uninit_vfio_user(struct iavf_emudev *dev);
+
+int iavf_emu_start_vfio_user(struct iavf_emudev *dev);
+
 #endif
diff --git a/drivers/emu/iavf/meson.build b/drivers/emu/iavf/meson.build
index 4f651258c2..3cab2226b7 100644
--- a/drivers/emu/iavf/meson.build
+++ b/drivers/emu/iavf/meson.build
@@ -1,6 +1,14 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2020 Intel Corporation
 
+librt = cc.find_library('rt', required: false)
+if not librt.found()
+	build = false
+	subdir_done()
+endif
+
+ext_deps += librt
+
 sources = files('iavf_emu.c', 'iavf_vfio_user.c',
 	'iavf_emudev.c')
 
-- 
2.17.1


  parent reply	other threads:[~2020-12-19  6:45 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-18  7:47 [dpdk-dev] [PATCH 0/8] Introduce emudev library and iavf emudev driver Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 1/8] lib: introduce emudev library Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 2/8] doc: add emudev library guide Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 3/8] emu: introduce emulated iavf driver Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 4/8] emu/iavf: add vfio-user device register and unregister Chenbo Xia
2021-01-07  7:18   ` Xing, Beilei
2021-01-07  8:41     ` Xia, Chenbo
2020-12-18  7:47 ` [dpdk-dev] [PATCH 5/8] emu/iavf: add resource management and internal logic of iavf Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 6/8] emu/iavf: add emudev operations to fit in emudev framework Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 7/8] test/emudev: introduce functional test Chenbo Xia
2020-12-18  7:47 ` [dpdk-dev] [PATCH 8/8] doc: update release notes for iavf emudev driver Chenbo Xia
2020-12-18  9:53 ` [dpdk-dev] [PATCH 0/8] Introduce emudev library and " David Marchand
2020-12-19  6:11   ` Xia, Chenbo
2020-12-21  9:52     ` Maxime Coquelin
2020-12-21 12:01       ` Maxime Coquelin
2020-12-22  3:09         ` Xia, Chenbo
2020-12-22  8:48           ` Maxime Coquelin
2020-12-23  5:28             ` Xia, Chenbo
2020-12-19  6:27 ` [dpdk-dev] [PATCH v2 " Chenbo Xia
2020-12-19  6:27   ` [dpdk-dev] [PATCH v2 1/8] lib: introduce emudev library Chenbo Xia
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 2/8] doc: add emudev library guide Chenbo Xia
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 3/8] emu: introduce emulated iavf driver Chenbo Xia
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 4/8] emu/iavf: add vfio-user device register and unregister Chenbo Xia
2021-01-04  6:45     ` Wu, Jingjing
2021-01-05  1:26       ` Xia, Chenbo
2021-01-05 13:41     ` Wu, Jingjing
2021-01-06  7:41       ` Xia, Chenbo
2020-12-19  6:28   ` Chenbo Xia [this message]
2020-12-29  6:05     ` [dpdk-dev] [PATCH v2 5/8] emu/iavf: add resource management and internal logic of iavf Wu, Jingjing
2020-12-30  1:59       ` Xia, Chenbo
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 6/8] emu/iavf: add emudev operations to fit in emudev framework Chenbo Xia
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 7/8] test/emudev: introduce functional test Chenbo Xia
2020-12-19  6:28   ` [dpdk-dev] [PATCH v2 8/8] doc: update release notes for iavf emudev driver Chenbo Xia
2021-01-13 16:52   ` [dpdk-dev] [PATCH v2 0/8] Introduce emudev library and " Thomas Monjalon
2021-01-14  1:35     ` Xia, Chenbo
2021-01-14  6:25   ` [dpdk-dev] [PATCH v3 " Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 1/8] lib: introduce emudev library Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 2/8] doc: add emudev library guide Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 3/8] emu: introduce emulated iavf driver Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 4/8] emu/iavf: add vfio-user device register and unregister Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 5/8] emu/iavf: add resource management and internal logic of iavf Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 6/8] emu/iavf: add emudev operations to fit in emudev framework Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 7/8] test/emudev: introduce functional test Chenbo Xia
2021-01-14  6:25     ` [dpdk-dev] [PATCH v3 8/8] doc: update release notes for iavf emudev driver Chenbo Xia
2024-02-12 22:49     ` [dpdk-dev] [PATCH v3 0/8] Introduce emudev library and " Stephen Hemminger
2023-06-14 19:47 ` [dpdk-dev] [PATCH " Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201219062806.56477-6-chenbo.xia@intel.com \
    --to=chenbo.xia@intel.com \
    --cc=cunming.liang@intel.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=jingjing.wu@intel.com \
    --cc=miao.li@intel.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    --cc=xiuchun.lu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.