Пример #1
0
int
clear_group(int vfio_group_fd)
{
	int i;
	int socket_fd, ret;

	if (internal_config.process_type == RTE_PROC_PRIMARY) {

		i = get_vfio_group_idx(vfio_group_fd);
		if (i < 0)
			return -1;
		vfio_cfg.vfio_groups[i].group_no = -1;
		vfio_cfg.vfio_groups[i].fd = -1;
		vfio_cfg.vfio_groups[i].devices = 0;
		vfio_cfg.vfio_active_groups--;
		return 0;
	}

	/* This is just for SECONDARY processes */
	socket_fd = vfio_mp_sync_connect_to_primary();

	if (socket_fd < 0) {
		RTE_LOG(ERR, EAL, "  cannot connect to primary process!\n");
		return -1;
	}

	if (vfio_mp_sync_send_request(socket_fd, SOCKET_CLR_GROUP) < 0) {
		RTE_LOG(ERR, EAL, "  cannot request container fd!\n");
		close(socket_fd);
		return -1;
	}

	if (vfio_mp_sync_send_request(socket_fd, vfio_group_fd) < 0) {
		RTE_LOG(ERR, EAL, "  cannot send group fd!\n");
		close(socket_fd);
		return -1;
	}

	ret = vfio_mp_sync_receive_request(socket_fd);
	switch (ret) {
	case SOCKET_NO_FD:
		RTE_LOG(ERR, EAL, "  BAD VFIO group fd!\n");
		close(socket_fd);
		break;
	case SOCKET_OK:
		close(socket_fd);
		return 0;
	case SOCKET_ERR:
		RTE_LOG(ERR, EAL, "  Socket error\n");
		close(socket_fd);
		break;
	default:
		RTE_LOG(ERR, EAL, "  UNKNOWN reply, %d\n", ret);
		close(socket_fd);
	}
	return -1;
}
Пример #2
0
/*
 * socket listening thread for primary process
 */
static __attribute__((noreturn)) void *
pci_vfio_mp_sync_thread(void __rte_unused * arg)
{
	int ret, fd, vfio_group_no;

	/* wait for requests on the socket */
	for (;;) {
		int conn_sock;
		struct sockaddr_un addr;
		socklen_t sockaddr_len = sizeof(addr);

		/* this is a blocking call */
		conn_sock = accept(mp_socket_fd, (struct sockaddr *) &addr,
				&sockaddr_len);

		/* just restart on error */
		if (conn_sock == -1)
			continue;

		/* set socket to linger after close */
		struct linger l;
		l.l_onoff = 1;
		l.l_linger = 60;
		setsockopt(conn_sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));

		ret = vfio_mp_sync_receive_request(conn_sock);

		switch (ret) {
		case SOCKET_REQ_CONTAINER:
			fd = pci_vfio_get_container_fd();
			if (fd < 0)
				vfio_mp_sync_send_request(conn_sock, SOCKET_ERR);
			else
				vfio_mp_sync_send_fd(conn_sock, fd);
			break;
		case SOCKET_REQ_GROUP:
			/* wait for group number */
			vfio_group_no = vfio_mp_sync_receive_request(conn_sock);
			if (vfio_group_no < 0) {
				close(conn_sock);
				continue;
			}

			fd = pci_vfio_get_group_fd(vfio_group_no);

			if (fd < 0)
				vfio_mp_sync_send_request(conn_sock, SOCKET_ERR);
			/* if VFIO group exists but isn't bound to VFIO driver */
			else if (fd == 0)
				vfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD);
			/* if group exists and is bound to VFIO driver */
			else {
				vfio_mp_sync_send_request(conn_sock, SOCKET_OK);
				vfio_mp_sync_send_fd(conn_sock, fd);
			}
			break;
		default:
			vfio_mp_sync_send_request(conn_sock, SOCKET_ERR);
			break;
		}
		close(conn_sock);
	}
}
Пример #3
0
int
vfio_get_group_fd(int iommu_group_no)
{
	int i;
	int vfio_group_fd;
	char filename[PATH_MAX];
	struct vfio_group *cur_grp;

	/* check if we already have the group descriptor open */
	for (i = 0; i < VFIO_MAX_GROUPS; i++)
		if (vfio_cfg.vfio_groups[i].group_no == iommu_group_no)
			return vfio_cfg.vfio_groups[i].fd;

	/* Lets see first if there is room for a new group */
	if (vfio_cfg.vfio_active_groups == VFIO_MAX_GROUPS) {
		RTE_LOG(ERR, EAL, "Maximum number of VFIO groups reached!\n");
		return -1;
	}

	/* Now lets get an index for the new group */
	for (i = 0; i < VFIO_MAX_GROUPS; i++)
		if (vfio_cfg.vfio_groups[i].group_no == -1) {
			cur_grp = &vfio_cfg.vfio_groups[i];
			break;
		}

	/* This should not happen */
	if (i == VFIO_MAX_GROUPS) {
		RTE_LOG(ERR, EAL, "No VFIO group free slot found\n");
		return -1;
	}
	/* if primary, try to open the group */
	if (internal_config.process_type == RTE_PROC_PRIMARY) {
		/* try regular group format */
		snprintf(filename, sizeof(filename),
				 VFIO_GROUP_FMT, iommu_group_no);
		vfio_group_fd = open(filename, O_RDWR);
		if (vfio_group_fd < 0) {
			/* if file not found, it's not an error */
			if (errno != ENOENT) {
				RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename,
						strerror(errno));
				return -1;
			}

			/* special case: try no-IOMMU path as well */
			snprintf(filename, sizeof(filename),
					VFIO_NOIOMMU_GROUP_FMT, iommu_group_no);
			vfio_group_fd = open(filename, O_RDWR);
			if (vfio_group_fd < 0) {
				if (errno != ENOENT) {
					RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename,
							strerror(errno));
					return -1;
				}
				return 0;
			}
			/* noiommu group found */
		}

		cur_grp->group_no = iommu_group_no;
		cur_grp->fd = vfio_group_fd;
		vfio_cfg.vfio_active_groups++;
		return vfio_group_fd;
	}
	/* if we're in a secondary process, request group fd from the primary
	 * process via our socket
	 */
	else {
		int socket_fd, ret;

		socket_fd = vfio_mp_sync_connect_to_primary();

		if (socket_fd < 0) {
			RTE_LOG(ERR, EAL, "  cannot connect to primary process!\n");
			return -1;
		}
		if (vfio_mp_sync_send_request(socket_fd, SOCKET_REQ_GROUP) < 0) {
			RTE_LOG(ERR, EAL, "  cannot request container fd!\n");
			close(socket_fd);
			return -1;
		}
		if (vfio_mp_sync_send_request(socket_fd, iommu_group_no) < 0) {
			RTE_LOG(ERR, EAL, "  cannot send group number!\n");
			close(socket_fd);
			return -1;
		}
		ret = vfio_mp_sync_receive_request(socket_fd);
		switch (ret) {
		case SOCKET_NO_FD:
			close(socket_fd);
			return 0;
		case SOCKET_OK:
			vfio_group_fd = vfio_mp_sync_receive_fd(socket_fd);
			/* if we got the fd, store it and return it */
			if (vfio_group_fd > 0) {
				close(socket_fd);
				cur_grp->group_no = iommu_group_no;
				cur_grp->fd = vfio_group_fd;
				vfio_cfg.vfio_active_groups++;
				return vfio_group_fd;
			}
			/* fall-through on error */
		default:
			RTE_LOG(ERR, EAL, "  cannot get container fd!\n");
			close(socket_fd);
			return -1;
		}
	}
	return -1;
}