1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4 
5 #include <unistd.h>
6 #include <string.h>
7 
8 #include <rte_compat.h>
9 #include <rte_errno.h>
10 #include <rte_log.h>
11 #include <rte_vfio.h>
12 #include <rte_eal.h>
13 
14 #include "eal_vfio.h"
15 
16 /**
17  * @file
18  * VFIO socket for communication between primary and secondary processes.
19  *
20  * This file is only compiled if RTE_EAL_VFIO is set.
21  */
22 
23 #ifdef VFIO_PRESENT
24 
25 static int
vfio_mp_primary(const struct rte_mp_msg * msg,const void * peer)26 vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
27 {
28 	int fd = -1;
29 	int ret;
30 	struct rte_mp_msg reply;
31 	struct vfio_mp_param *r = (struct vfio_mp_param *)reply.param;
32 	const struct vfio_mp_param *m =
33 		(const struct vfio_mp_param *)msg->param;
34 
35 	if (msg->len_param != sizeof(*m)) {
36 		RTE_LOG(ERR, EAL, "vfio received invalid message!\n");
37 		return -1;
38 	}
39 
40 	memset(&reply, 0, sizeof(reply));
41 
42 	switch (m->req) {
43 	case SOCKET_REQ_GROUP:
44 		r->req = SOCKET_REQ_GROUP;
45 		r->group_num = m->group_num;
46 		fd = rte_vfio_get_group_fd(m->group_num);
47 		if (fd < 0 && fd != -ENOENT)
48 			r->result = SOCKET_ERR;
49 		else if (fd == -ENOENT)
50 			/* if VFIO group exists but isn't bound to VFIO driver */
51 			r->result = SOCKET_NO_FD;
52 		else {
53 			/* if group exists and is bound to VFIO driver */
54 			r->result = SOCKET_OK;
55 			reply.num_fds = 1;
56 			reply.fds[0] = fd;
57 		}
58 		break;
59 	case SOCKET_REQ_CONTAINER:
60 		r->req = SOCKET_REQ_CONTAINER;
61 		fd = rte_vfio_get_container_fd();
62 		if (fd < 0)
63 			r->result = SOCKET_ERR;
64 		else {
65 			r->result = SOCKET_OK;
66 			reply.num_fds = 1;
67 			reply.fds[0] = fd;
68 		}
69 		break;
70 	case SOCKET_REQ_DEFAULT_CONTAINER:
71 		r->req = SOCKET_REQ_DEFAULT_CONTAINER;
72 		fd = vfio_get_default_container_fd();
73 		if (fd < 0)
74 			r->result = SOCKET_ERR;
75 		else {
76 			r->result = SOCKET_OK;
77 			reply.num_fds = 1;
78 			reply.fds[0] = fd;
79 		}
80 		break;
81 	case SOCKET_REQ_IOMMU_TYPE:
82 	{
83 		int iommu_type_id;
84 
85 		r->req = SOCKET_REQ_IOMMU_TYPE;
86 
87 		iommu_type_id = vfio_get_iommu_type();
88 
89 		if (iommu_type_id < 0)
90 			r->result = SOCKET_ERR;
91 		else {
92 			r->iommu_type_id = iommu_type_id;
93 			r->result = SOCKET_OK;
94 		}
95 		break;
96 	}
97 	default:
98 		RTE_LOG(ERR, EAL, "vfio received invalid message!\n");
99 		return -1;
100 	}
101 
102 	strcpy(reply.name, EAL_VFIO_MP);
103 	reply.len_param = sizeof(*r);
104 
105 	ret = rte_mp_reply(&reply, peer);
106 	if (m->req == SOCKET_REQ_CONTAINER && fd >= 0)
107 		close(fd);
108 	return ret;
109 }
110 
111 int
vfio_mp_sync_setup(void)112 vfio_mp_sync_setup(void)
113 {
114 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
115 		int ret = rte_mp_action_register(EAL_VFIO_MP, vfio_mp_primary);
116 		if (ret && rte_errno != ENOTSUP)
117 			return -1;
118 	}
119 
120 	return 0;
121 }
122 
123 #endif
124