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