// File: /workspace/github_c_makefile_star2_O3/intel[P]pf-bb-config/bb_acc_vfio.c
// Function: vfio_device_open
int vfio_device_open(void *dev)
{
	int   ret, groupid;
	int   vfio_container_fd, vfio_group_fd, vfio_dev_fd;
	char  path[PATH_MAX];

	hw_device *hwd = (hw_device *)dev;
	char *pci_addr = hwd->pci_address;

	struct vfio_group_status group_status = {
		.argsz = sizeof(group_status)
	};

	struct vfio_device_info device_info = {
		.argsz = sizeof(device_info)
	};

	struct vfio_iommu_type1_dma_map dma_map = {
		.argsz = sizeof(dma_map)
	};

	LOG(DEBUG, "PCI device: %s", pci_addr);

	if (!hwd->vfio_mode) {
		LOG(WARN, "not opened in vfio mode");
		return -1;
	}

	if (hwd->vfio_dev_fd) {
		LOG(DEBUG, "VFIO device already opened");
		return 0;
	}

	vfio_container_fd = open("/dev/vfio/vfio", O_RDWR);
	if (vfio_container_fd < 0) {
		LOG(ERR, "Failed to open /dev/vfio/vfio, %d (%s)",
				vfio_container_fd, strerror(errno));
		goto error0;
	}

	groupid = vfio_get_device_groupid(pci_addr);
	if (groupid == -1) {
		LOG(ERR, "Failed to get groupid");
		goto error1;
	}
	LOG(DEBUG, "VFIO: Using PCI device [%s] in group %d",
			pci_addr, groupid);

	snprintf(path, sizeof(path), "/dev/vfio/%d", groupid);
	vfio_group_fd = open(path, O_RDWR);
	if (vfio_group_fd < 0) {
		LOG(ERR, "Failed to open %s, %d (%s)",
				path, vfio_group_fd, strerror(errno));
		LOG(ERR, "Device [%s] not bind to vfio-pci driver",
				pci_addr);
		goto error1;
	}

	ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
	if (ret) {
		LOG(ERR, "ioctl(VFIO_GROUP_GET_STATUS) failed");
		goto error2;
	}

	if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
		LOG(ERR, "Group not viable, are all devices attached to vfio?");
		goto error2;
	}

	/* NOTE: set container ioctl will attach the vfio_group_fd
	* to vfio_container_fd, will not override the vfio_conatiner_fd
	*/
	ret = ioctl(vfio_group_fd, VFIO_GROUP_SET_CONTAINER,
			&vfio_container_fd);
	if (ret) {
		LOG(ERR, "Failed to set group container");
		goto error2;
	}

	ret = ioctl(vfio_container_fd,
			VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);
	if (ret) {
		LOG(ERR, "Failed to set IOMMU");
		goto error2;
	}

	if (hwd->info_ring_total_size) {
		/* Allocate some space and setup a DMA mapping */
		dma_map.vaddr = (uint64_t)mmap(0, hwd->info_ring_total_size,
				PROT_READ | PROT_WRITE,
				MAP_SHARED | MAP_ANONYMOUS, 0, 0);
		if (dma_map.vaddr == (uint64_t)MAP_FAILED) {
			LOG(ERR, "DMA mapping failed");
			goto error2;
		}
		dma_map.size = hwd->info_ring_total_size;
		dma_map.iova = dma_map.vaddr;
		dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;

		ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
		if (ret) {
			LOG(ERR, "Failed to set IOMMU_MAP_DMA");
			goto error2;
		}
		hwd->iommu_map_dma_vaddr = (void *)(dma_map.vaddr);
		hwd->iommu_map_dma_size  = hwd->info_ring_total_size;
		LOG(DEBUG, "VFIO selected IOVA mode 'VA'");
	}

	vfio_dev_fd = ioctl(vfio_group_fd,
			VFIO_GROUP_GET_DEVICE_FD, pci_addr);
	if (vfio_dev_fd < 0) {
		LOG(ERR, "Failed to get device %s", pci_addr);
		goto error2;
	}

	close(vfio_container_fd);
	close(vfio_group_fd);
	hwd->vfio_dev_fd = vfio_dev_fd;

	LOG(DEBUG, "Done, vfio_dev_fd: %d", vfio_dev_fd);
	return 0;

error2:
	close(vfio_group_fd);
error1:
	close(vfio_container_fd);
error0:
	return -1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2048, %rsp           # imm = 0x2048
movq %rdi, %r14
leaq 0x20(%rdi), %rbx
movq $0x8, 0x18(%rsp)
movups 0x5ec5(%rip), %xmm0     # 0x1e310
movaps %xmm0, 0x30(%rsp)
movups 0x5ea9(%rip), %xmm0     # 0x1e300
movaps %xmm0, 0x20(%rsp)
callq 0x18c40
leaq 0x1ba68(%rip), %rbp     # 0x33ed0
movq 0x18(%rbp), %r8
movq %rbx, (%rsp)
leaq 0x57c2(%rip), %rdx      # 0x1dc39
leaq 0x57d7(%rip), %r9       # 0x1dc55
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
cmpl $0x0, 0xbc(%r14)
je 0x184d3
cmpl $0x0, 0xc0(%r14)
je 0x184f9
callq 0x18c40
movq 0x18(%rbp), %r8
leaq 0x57d2(%rip), %rdx      # 0x1dc85
leaq 0x579b(%rip), %r9       # 0x1dc55
xorl %r15d, %r15d
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
jmp 0x186d7
callq 0x18c40
movq 0x8(%rbp), %r8
leaq 0x5783(%rip), %rdx      # 0x1dc66
movl $0x1, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
jmp 0x186d1
leaq 0x57ad(%rip), %rdi      # 0x1dcad
movl $0x2, %esi
xorl %eax, %eax
callq 0xd2f0
movl %eax, %r15d
movl %eax, 0x14(%rsp)
testl %eax, %eax
js 0x18633
leaq 0x5d0b(%rip), %rdx      # 0x1e22d
leaq 0x2ceb(%rip), %rcx      # 0x1b214
leaq 0x1040(%rsp), %r12
movl $0x1000, %esi           # imm = 0x1000
movq %r12, %rdi
movq %rbx, %r8
xorl %eax, %eax
callq 0xd170
leaq 0x40(%rsp), %rsi
movl $0xfff, %edx            # imm = 0xFFF
movq %r12, %rdi
callq 0xd0e0
testl %eax, %eax
js 0x1866c
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0xd240
movq %rax, %rdi
xorl %esi, %esi
movl $0xa, %edx
callq 0xd230
movq %rax, %r12
testl %r12d, %r12d
je 0x18688
cmpl $-0x1, %r12d
je 0x186ab
callq 0x18c40
movq 0x18(%rbp), %r8
movl %r12d, 0x8(%rsp)
movq %rbx, (%rsp)
leaq 0x5758(%rip), %rdx      # 0x1dd07
leaq 0x569f(%rip), %r9       # 0x1dc55
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
leaq 0x576e(%rip), %rdx      # 0x1dd3c
leaq 0x1040(%rsp), %r13
movl $0x1000, %esi           # imm = 0x1000
movq %r13, %rdi
movl %r12d, %ecx
xorl %eax, %eax
callq 0xd170
movq %r13, %rdi
movl $0x2, %esi
xorl %eax, %eax
callq 0xd2f0
movl %eax, %r13d
testl %eax, %eax
js 0x186ec
leaq 0x18(%rsp), %rdx
movl $0x3b67, %esi           # imm = 0x3B67
movl %r13d, %edi
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x18753
callq 0x18c40
movq (%rbp), %r8
leaq 0x576c(%rip), %rdx      # 0x1dd9a
jmp 0x187bf
callq 0x18c40
movq %rax, %rbx
movq (%rbp), %r14
callq 0xd070
movl (%rax), %edi
callq 0xd400
movq %rax, (%rsp)
leaq 0x5666(%rip), %rdx      # 0x1dcbc
xorl %edi, %edi
xorl %esi, %esi
movq %rbx, %rcx
movq %r14, %r8
movl %r15d, %r9d
xorl %eax, %eax
callq 0x199b4
jmp 0x186d1
callq 0x18c40
movq (%rbp), %r8
leaq 0x5bc3(%rip), %rdx      # 0x1e23f
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
jmp 0x186a4
callq 0x18c40
movq (%rbp), %r8
leaq 0x5bcd(%rip), %rdx      # 0x1e265
leaq 0x40(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
callq 0x18c40
movq (%rbp), %r8
leaq 0x562f(%rip), %rdx      # 0x1dcea
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
movl %r15d, %edi
callq 0xd1a0
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %r15d, %eax
addq $0x2048, %rsp           # imm = 0x2048
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x18c40
movq %rax, %r14
movq (%rbp), %r12
callq 0xd070
movl (%rax), %edi
callq 0xd400
movq %rax, 0x8(%rsp)
movl %r13d, (%rsp)
leaq 0x5635(%rip), %rdx      # 0x1dd49
leaq 0x1040(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %r14, %rcx
movq %r12, %r8
xorl %eax, %eax
callq 0x199b4
callq 0x18c40
movq (%rbp), %r8
leaq 0x562e(%rip), %rdx      # 0x1dd6b
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x199b4
jmp 0x186c9
testb $0x1, 0x1c(%rsp)
jne 0x1876c
callq 0x18c40
movq (%rbp), %r8
leaq 0x565b(%rip), %rdx      # 0x1ddc5
jmp 0x187bf
leaq 0x14(%rsp), %rdx
movl $0x3b68, %esi           # imm = 0x3B68
movl %r13d, %edi
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x18796
callq 0x18c40
movq (%rbp), %r8
leaq 0x566c(%rip), %rdx      # 0x1de00
jmp 0x187bf
movl 0x14(%rsp), %edi
movl $0x3b66, %esi           # imm = 0x3B66
movl $0x1, %edx
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x187df
callq 0x18c40
movq (%rbp), %r8
leaq 0x5666(%rip), %rdx      # 0x1de25
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
movl %r13d, %edi
callq 0xd1a0
movl 0x14(%rsp), %r15d
jmp 0x186c9
movq 0xa0(%r14), %rsi
testq %rsi, %rsi
je 0x188ac
xorl %edi, %edi
movl $0x3, %edx
movl $0x21, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0xd120
movq %rax, 0x28(%rsp)
cmpq $-0x1, %rax
je 0x18855
movq 0xa0(%r14), %rcx
leaq 0x20(%rsp), %rdx
movq %rcx, 0x18(%rdx)
movq %rax, 0x10(%rdx)
movl $0x3, 0x4(%rdx)
movl 0x14(%rsp), %edi
movl $0x3b71, %esi           # imm = 0x3B71
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x1886a
callq 0x18c40
movq (%rbp), %r8
leaq 0x560a(%rip), %rdx      # 0x1de5a
jmp 0x187bf
callq 0x18c40
movq (%rbp), %r8
leaq 0x55db(%rip), %rdx      # 0x1de40
jmp 0x187bf
movq 0x28(%rsp), %rax
movq %rax, 0xd0(%r14)
movl 0xa0(%r14), %eax
movl %eax, 0xd8(%r14)
callq 0x18c40
movq 0x18(%rbp), %r8
leaq 0x55e9(%rip), %rdx      # 0x1de7d
leaq 0x53ba(%rip), %r9       # 0x1dc55
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x199b4
xorl %r15d, %r15d
movl $0x3b6a, %esi           # imm = 0x3B6A
movl %r13d, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
js 0x18900
movl %eax, %r12d
movl 0x14(%rsp), %edi
callq 0xd1a0
movl %r13d, %edi
callq 0xd1a0
movl %r12d, 0xc0(%r14)
callq 0x18c40
movq 0x18(%rbp), %r8
movl %r12d, (%rsp)
leaq 0x55d2(%rip), %rdx      # 0x1dec6
leaq 0x535a(%rip), %r9       # 0x1dc55
jmp 0x184bd
callq 0x18c40
movq (%rbp), %r8
leaq 0x5597(%rip), %rdx      # 0x1dea7
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x199b4
jmp 0x187cd