// File: /workspace/github_c_makefile_star2_O2/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 0x6333(%rip), %xmm0     # 0x1e2c0
movaps %xmm0, 0x30(%rsp)
movups 0x6317(%rip), %xmm0     # 0x1e2b0
movaps %xmm0, 0x20(%rsp)
callq 0x18754
leaq 0x1cf26(%rip), %rbp     # 0x34ed0
movq 0x18(%rbp), %r8
movq %rbx, (%rsp)
leaq 0x5c30(%rip), %rdx      # 0x1dbe9
leaq 0x5c45(%rip), %r9       # 0x1dc05
pushq $0x3
popq %rdi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
cmpl $0x0, 0xbc(%r14)
je 0x18011
cmpl $0x0, 0xc0(%r14)
je 0x18035
callq 0x18754
movq 0x18(%rbp), %r8
leaq 0x5c42(%rip), %rdx      # 0x1dc35
leaq 0x5c0b(%rip), %r9       # 0x1dc05
xorl %r15d, %r15d
pushq $0x3
popq %rdi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
jmp 0x18209
callq 0x18754
movq 0x8(%rbp), %r8
leaq 0x5bf5(%rip), %rdx      # 0x1dc16
pushq $0x1
popq %rdi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
jmp 0x18205
leaq 0x5c21(%rip), %rdi      # 0x1dc5d
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0xd300
movl %eax, %r15d
movl %eax, 0x14(%rsp)
testl %eax, %eax
js 0x18167
leaq 0x6181(%rip), %rdx      # 0x1e1dd
leaq 0x31b1(%rip), %rcx      # 0x1b214
leaq 0x1040(%rsp), %r12
movl $0x1000, %esi           # imm = 0x1000
movq %r12, %rdi
movq %rbx, %r8
xorl %eax, %eax
callq 0xd180
leaq 0x40(%rsp), %rsi
movl $0xfff, %edx            # imm = 0xFFF
movq %r12, %rdi
callq 0xd0e0
testl %eax, %eax
js 0x181a0
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0xd250
pushq $0xa
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
callq 0xd240
movq %rax, %r12
testl %r12d, %r12d
je 0x181bc
cmpl $-0x1, %r12d
je 0x181df
callq 0x18754
movq 0x18(%rbp), %r8
movl %r12d, 0x8(%rsp)
movq %rbx, (%rsp)
leaq 0x5bd0(%rip), %rdx      # 0x1dcb7
leaq 0x5b17(%rip), %r9       # 0x1dc05
pushq $0x3
popq %rdi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
leaq 0x5be8(%rip), %rdx      # 0x1dcec
leaq 0x1040(%rsp), %r13
movl $0x1000, %esi           # imm = 0x1000
movq %r13, %rdi
movl %r12d, %ecx
xorl %eax, %eax
callq 0xd180
pushq $0x2
popq %rsi
movq %r13, %rdi
xorl %eax, %eax
callq 0xd300
movl %eax, %r13d
testl %eax, %eax
js 0x1821e
leaq 0x18(%rsp), %rdx
movl $0x3b67, %esi           # imm = 0x3B67
movl %r13d, %edi
xorl %eax, %eax
callq 0xd1a0
testl %eax, %eax
je 0x18285
callq 0x18754
movq (%rbp), %r8
leaq 0x5be8(%rip), %rdx      # 0x1dd4a
jmp 0x182ef
callq 0x18754
movq %rax, %rbx
movq (%rbp), %r14
callq 0xd070
movl (%rax), %edi
callq 0xd410
movq %rax, (%rsp)
leaq 0x5ae2(%rip), %rdx      # 0x1dc6c
xorl %edi, %edi
xorl %esi, %esi
movq %rbx, %rcx
movq %r14, %r8
movl %r15d, %r9d
xorl %eax, %eax
callq 0x19400
jmp 0x18205
callq 0x18754
movq (%rbp), %r8
leaq 0x603f(%rip), %rdx      # 0x1e1ef
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
jmp 0x181d8
callq 0x18754
movq (%rbp), %r8
leaq 0x6049(%rip), %rdx      # 0x1e215
leaq 0x40(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
callq 0x18754
movq (%rbp), %r8
leaq 0x5aab(%rip), %rdx      # 0x1dc9a
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
movl %r15d, %edi
callq 0xd1b0
pushq $-0x1
popq %r15
movl %r15d, %eax
addq $0x2048, %rsp           # imm = 0x2048
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x18754
movq %rax, %r14
movq (%rbp), %r12
callq 0xd070
movl (%rax), %edi
callq 0xd410
movq %rax, 0x8(%rsp)
movl %r13d, (%rsp)
leaq 0x5ab3(%rip), %rdx      # 0x1dcf9
leaq 0x1040(%rsp), %r9
xorl %edi, %edi
xorl %esi, %esi
movq %r14, %rcx
movq %r12, %r8
xorl %eax, %eax
callq 0x19400
callq 0x18754
movq (%rbp), %r8
leaq 0x5aac(%rip), %rdx      # 0x1dd1b
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x19400
jmp 0x181fd
testb $0x1, 0x1c(%rsp)
jne 0x1829e
callq 0x18754
movq (%rbp), %r8
leaq 0x5ad9(%rip), %rdx      # 0x1dd75
jmp 0x182ef
leaq 0x14(%rsp), %rdx
movl $0x3b68, %esi           # imm = 0x3B68
movl %r13d, %edi
xorl %eax, %eax
callq 0xd1a0
testl %eax, %eax
je 0x182c8
callq 0x18754
movq (%rbp), %r8
leaq 0x5aea(%rip), %rdx      # 0x1ddb0
jmp 0x182ef
movl 0x14(%rsp), %edi
pushq $0x1
popq %rdx
movl $0x3b66, %esi           # imm = 0x3B66
xorl %eax, %eax
callq 0xd1a0
testl %eax, %eax
je 0x1830f
callq 0x18754
movq (%rbp), %r8
leaq 0x5ae6(%rip), %rdx      # 0x1ddd5
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
movl %r13d, %edi
callq 0xd1b0
movl 0x14(%rsp), %r15d
jmp 0x181fd
movq 0xa0(%r14), %rsi
testq %rsi, %rsi
je 0x183d6
pushq $0x3
popq %rdx
pushq $0x21
popq %rcx
xorl %edi, %edi
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0xd120
movq %rax, 0x28(%rsp)
cmpq $-0x1, %rax
je 0x18381
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 0xd1a0
testl %eax, %eax
je 0x18396
callq 0x18754
movq (%rbp), %r8
leaq 0x5a8e(%rip), %rdx      # 0x1de0a
jmp 0x182ef
callq 0x18754
movq (%rbp), %r8
leaq 0x5a5f(%rip), %rdx      # 0x1ddf0
jmp 0x182ef
movq 0x28(%rsp), %rax
movq %rax, 0xd0(%r14)
movl 0xa0(%r14), %eax
movl %eax, 0xd8(%r14)
callq 0x18754
movq 0x18(%rbp), %r8
leaq 0x5a6d(%rip), %rdx      # 0x1de2d
leaq 0x583e(%rip), %r9       # 0x1dc05
pushq $0x3
popq %rdi
xorl %esi, %esi
movq %rax, %rcx
xorl %eax, %eax
callq 0x19400
xorl %r15d, %r15d
movl $0x3b6a, %esi           # imm = 0x3B6A
movl %r13d, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0xd1a0
testl %eax, %eax
js 0x1842a
movl %eax, %r12d
movl 0x14(%rsp), %edi
callq 0xd1b0
movl %r13d, %edi
callq 0xd1b0
movl %r12d, 0xc0(%r14)
callq 0x18754
movq 0x18(%rbp), %r8
movl %r12d, (%rsp)
leaq 0x5a58(%rip), %rdx      # 0x1de76
leaq 0x57e0(%rip), %r9       # 0x1dc05
jmp 0x17ffd
callq 0x18754
movq (%rbp), %r8
leaq 0x5a1d(%rip), %rdx      # 0x1de57
xorl %edi, %edi
xorl %esi, %esi
movq %rax, %rcx
movq %rbx, %r9
xorl %eax, %eax
callq 0x19400
jmp 0x182fd