// File: /workspace/github_c_makefile_star2_O1/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 0x5b39(%rip), %xmm0     # 0x1e2b0
movaps %xmm0, 0x30(%rsp)
movups 0x5b1d(%rip), %xmm0     # 0x1e2a0
movaps %xmm0, 0x20(%rsp)
callq 0x18f62
leaq 0x1b73c(%rip), %r13     # 0x33ed0
movq 0x18(%r13), %r8
movq %rbx, (%rsp)
leaq 0x5437(%rip), %rdx      # 0x1dbda
leaq 0x544c(%rip), %r9       # 0x1dbf6
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
cmpl $0x0, 0xbc(%r14)
je 0x187ff
cmpl $0x0, 0xc0(%r14)
je 0x18825
callq 0x18f62
movq 0x18(%r13), %r8
leaq 0x5447(%rip), %rdx      # 0x1dc26
leaq 0x5410(%rip), %r9       # 0x1dbf6
xorl %r15d, %r15d
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
jmp 0x18aee
callq 0x18f62
movq 0x8(%r13), %r8
leaq 0x53f8(%rip), %rdx      # 0x1dc07
movl $0x1, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
jmp 0x18ae8
leaq 0x5422(%rip), %rdi      # 0x1dc4e
movl $0x2, %esi
xorl %eax, %eax
callq 0xd300
movl %eax, 0x14(%rsp)
testl %eax, %eax
js 0x188d3
leaq 0x5983(%rip), %rdx      # 0x1e1ce
leaq 0x29c2(%rip), %rcx      # 0x1b214
leaq 0x1040(%rsp), %r15
movl $0x1000, %esi           # imm = 0x1000
movq %r15, %rdi
movq %rbx, %r8
xorl %eax, %eax
callq 0xd170
leaq 0x40(%rsp), %rsi
movl $0xfff, %edx            # imm = 0xFFF
movq %r15, %rdi
callq 0xd0e0
testl %eax, %eax
js 0x18913
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0xd250
movq %rax, %rdi
xorl %esi, %esi
movl $0xa, %edx
callq 0xd240
movq %rax, %r15
testl %r15d, %r15d
jne 0x1893a
callq 0x18f62
movq (%r13), %r8
leaq 0x5941(%rip), %rdx      # 0x1e206
leaq 0x40(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
jmp 0x1892d
callq 0x18f62
movq %rax, %rbx
movq (%r13), %r14
movl 0x14(%rsp), %ebp
callq 0xd070
movl (%rax), %edi
callq 0xd410
movq %rax, (%rsp)
leaq 0x5363(%rip), %rdx      # 0x1dc5d
xorl %edi, %edi
xorl %esi, %esi
movq %rbx, %rcx
movq %r14, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x19ca8
jmp 0x18ae8
callq 0x18f62
movq (%r13), %r8
leaq 0x58bd(%rip), %rdx      # 0x1e1e0
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x19ca8
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
callq 0x18f62
cmpl $-0x1, %r15d
je 0x189db
movq 0x18(%r13), %r8
movl %r15d, 0x8(%rsp)
movq %rbx, (%rsp)
leaq 0x534b(%rip), %rdx      # 0x1dca8
leaq 0x5292(%rip), %r9       # 0x1dbf6
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
leaq 0x5361(%rip), %rdx      # 0x1dcdd
leaq 0x1040(%rsp), %r12
movl $0x1000, %esi           # imm = 0x1000
movq %r12, %rdi
movl %r15d, %ecx
xorl %eax, %eax
callq 0xd170
movq %r12, %rdi
movl $0x2, %esi
xorl %eax, %eax
callq 0xd300
movl %eax, %ebp
testl %eax, %eax
js 0x189f9
leaq 0x18(%rsp), %rdx
movl $0x3b67, %esi           # imm = 0x3B67
movl %ebp, %edi
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x18a5f
callq 0x18f62
movq (%r13), %r8
leaq 0x5365(%rip), %rdx      # 0x1dd3b
jmp 0x18aca
movq (%r13), %r8
leaq 0x52a5(%rip), %rdx      # 0x1dc8b
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
jmp 0x18adf
callq 0x18f62
movq %rax, %r14
movq (%r13), %r15
callq 0xd070
movl (%rax), %edi
callq 0xd410
movq %rax, 0x8(%rsp)
movl %ebp, (%rsp)
leaq 0x52ca(%rip), %rdx      # 0x1dcea
leaq 0x1040(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %r14, %rcx
movq %r15, %r8
xorl %eax, %eax
callq 0x19ca8
callq 0x18f62
movq (%r13), %r8
leaq 0x52c3(%rip), %rdx      # 0x1dd0c
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x19ca8
jmp 0x18adf
testb $0x1, 0x1c(%rsp)
jne 0x18a78
callq 0x18f62
movq (%r13), %r8
leaq 0x52f0(%rip), %rdx      # 0x1dd66
jmp 0x18aca
leaq 0x14(%rsp), %rdx
movl $0x3b68, %esi           # imm = 0x3B68
movl %ebp, %edi
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x18aa1
callq 0x18f62
movq (%r13), %r8
leaq 0x5302(%rip), %rdx      # 0x1dda1
jmp 0x18aca
movl 0x14(%rsp), %edi
movl $0x3b66, %esi           # imm = 0x3B66
movl $0x1, %edx
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
je 0x18b03
callq 0x18f62
movq (%r13), %r8
leaq 0x52fc(%rip), %rdx      # 0x1ddc6
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
movl %ebp, %edi
callq 0xd1a0
movl 0x14(%rsp), %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
movq 0xa0(%r14), %rsi
testq %rsi, %rsi
je 0x18bd0
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 0x18b79
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 0x18b8e
callq 0x18f62
movq (%r13), %r8
leaq 0x5287(%rip), %rdx      # 0x1ddfb
jmp 0x18aca
callq 0x18f62
movq (%r13), %r8
leaq 0x5258(%rip), %rdx      # 0x1dde1
jmp 0x18aca
movq 0x28(%rsp), %rax
movq %rax, 0xd0(%r14)
movl 0xa0(%r14), %eax
movl %eax, 0xd8(%r14)
callq 0x18f62
movq 0x18(%r13), %r8
leaq 0x5266(%rip), %rdx      # 0x1de1e
leaq 0x5037(%rip), %r9       # 0x1dbf6
movl $0x3, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19ca8
xorl %r15d, %r15d
movl $0x3b6a, %esi           # imm = 0x3B6A
movl %ebp, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0xd190
testl %eax, %eax
js 0x18c22
movl %eax, %r12d
movl 0x14(%rsp), %edi
callq 0xd1a0
movl %ebp, %edi
callq 0xd1a0
movl %r12d, 0xc0(%r14)
callq 0x18f62
movq 0x18(%r13), %r8
movl %r12d, (%rsp)
leaq 0x5251(%rip), %rdx      # 0x1de67
leaq 0x4fd9(%rip), %r9       # 0x1dbf6
jmp 0x187e9
callq 0x18f62
movq (%r13), %r8
leaq 0x5216(%rip), %rdx      # 0x1de48
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x19ca8
jmp 0x18ad8