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