xref: /spdk/lib/vfio_user/host/vfio_user.c (revision fecffda6ecf8853b82edccde429b68252f0a62c5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2020 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 /*
7  * vfio-user client socket messages.
8  */
9 
10 #include "spdk/stdinc.h"
11 #include "spdk/queue.h"
12 #include "spdk/util.h"
13 #include "spdk/log.h"
14 #include "spdk/vfio_user_spec.h"
15 
16 #include "vfio_user_internal.h"
17 
18 struct vfio_user_request {
19 	struct vfio_user_header hdr;
20 #define VFIO_USER_MAX_PAYLOAD_SIZE	(4096)
21 	uint8_t payload[VFIO_USER_MAX_PAYLOAD_SIZE];
22 	int fds[VFIO_MAXIMUM_SPARSE_MMAP_REGIONS];
23 	int fd_num;
24 };
25 
26 #ifdef DEBUG
27 static const char *vfio_user_message_str[VFIO_USER_MAX] = {
28 	[VFIO_USER_VERSION]			= "VFIO_USER_VERSION",
29 	[VFIO_USER_DMA_MAP]			= "VFIO_USER_DMA_MAP",
30 	[VFIO_USER_DMA_UNMAP]			= "VFIO_USER_DMA_UNMAP",
31 	[VFIO_USER_DEVICE_GET_INFO]		= "VFIO_USER_DEVICE_GET_INFO",
32 	[VFIO_USER_DEVICE_GET_REGION_INFO]	= "VFIO_USER_DEVICE_GET_REGION_INFO",
33 	[VFIO_USER_DEVICE_GET_IRQ_INFO]		= "VFIO_USER_DEVICE_GET_IRQ_INFO",
34 	[VFIO_USER_DEVICE_SET_IRQS]		= "VFIO_USER_DEVICE_SET_IRQS",
35 	[VFIO_USER_REGION_READ]			= "VFIO_USER_REGION_READ",
36 	[VFIO_USER_REGION_WRITE]		= "VFIO_USER_REGION_WRITE",
37 	[VFIO_USER_DMA_READ]			= "VFIO_USER_DMA_READ",
38 	[VFIO_USER_DMA_WRITE]			= "VFIO_USER_DMA_WRITE",
39 	[VFIO_USER_DEVICE_RESET]		= "VFIO_USER_DEVICE_RESET",
40 };
41 #endif
42 
43 static int
44 vfio_user_write(int fd, void *buf, int len, int *fds, int num_fds)
45 {
46 	int r;
47 	struct msghdr msgh;
48 	struct iovec iov;
49 	size_t fd_size = num_fds * sizeof(int);
50 	char control[CMSG_SPACE(VFIO_MAXIMUM_SPARSE_MMAP_REGIONS * sizeof(int))];
51 	struct cmsghdr *cmsg;
52 
53 	memset(&msgh, 0, sizeof(msgh));
54 	memset(control, 0, sizeof(control));
55 
56 	iov.iov_base = (uint8_t *)buf;
57 	iov.iov_len = len;
58 
59 	msgh.msg_iov = &iov;
60 	msgh.msg_iovlen = 1;
61 
62 	assert(num_fds <= VFIO_MAXIMUM_SPARSE_MMAP_REGIONS);
63 
64 	if (fds && num_fds) {
65 		msgh.msg_control = control;
66 		msgh.msg_controllen = CMSG_SPACE(fd_size);
67 		cmsg = CMSG_FIRSTHDR(&msgh);
68 		assert(cmsg != NULL);
69 		cmsg->cmsg_len = CMSG_LEN(fd_size);
70 		cmsg->cmsg_level = SOL_SOCKET;
71 		cmsg->cmsg_type = SCM_RIGHTS;
72 		memcpy(CMSG_DATA(cmsg), fds, fd_size);
73 	} else {
74 		msgh.msg_control = NULL;
75 		msgh.msg_controllen = 0;
76 	}
77 
78 	do {
79 		r = sendmsg(fd, &msgh, MSG_NOSIGNAL);
80 	} while (r < 0 && errno == EINTR);
81 
82 	if (r == -1) {
83 		return -errno;
84 	}
85 
86 	return 0;
87 }
88 
89 static int
90 read_fd_message(int sockfd, char *buf, int buflen, int *fds, int *fd_num)
91 {
92 	struct iovec iov;
93 	struct msghdr msgh;
94 	char control[CMSG_SPACE(VFIO_MAXIMUM_SPARSE_MMAP_REGIONS * sizeof(int))];
95 	struct cmsghdr *cmsg;
96 	int got_fds = 0;
97 	int ret;
98 
99 	memset(&msgh, 0, sizeof(msgh));
100 	iov.iov_base = buf;
101 	iov.iov_len  = buflen;
102 
103 	msgh.msg_iov = &iov;
104 	msgh.msg_iovlen = 1;
105 	msgh.msg_control = control;
106 	msgh.msg_controllen = sizeof(control);
107 
108 	ret = recvmsg(sockfd, &msgh, 0);
109 	if (ret <= 0) {
110 		return ret;
111 	}
112 
113 	if (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
114 		return -ENOTSUP;
115 	}
116 
117 	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
118 	     cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
119 		if ((cmsg->cmsg_level == SOL_SOCKET) &&
120 		    (cmsg->cmsg_type == SCM_RIGHTS)) {
121 			got_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
122 			*fd_num = got_fds;
123 			assert(got_fds <= VFIO_MAXIMUM_SPARSE_MMAP_REGIONS);
124 			memcpy(fds, CMSG_DATA(cmsg), got_fds * sizeof(int));
125 			break;
126 		}
127 	}
128 
129 	return ret;
130 }
131 
132 static int
133 vfio_user_read(int fd, struct vfio_user_request *req)
134 {
135 	int ret;
136 	size_t sz_payload;
137 
138 	ret = read_fd_message(fd, (char *)req, sizeof(struct vfio_user_header), req->fds, &req->fd_num);
139 	if (ret <= 0) {
140 		return ret;
141 	}
142 
143 	if (req->hdr.flags.error) {
144 		SPDK_ERRLOG("Command %u return failure\n", req->hdr.cmd);
145 		errno = req->hdr.error_no;
146 		return -EFAULT;
147 	}
148 
149 	if (req->hdr.msg_size > sizeof(struct vfio_user_header)) {
150 		sz_payload = req->hdr.msg_size - sizeof(struct vfio_user_header);
151 		ret = read(fd, req->payload, sz_payload);
152 		if (ret <= 0) {
153 			return ret;
154 		}
155 	}
156 
157 	return 0;
158 }
159 
160 int
161 vfio_user_dev_send_request(struct vfio_device *dev, enum vfio_user_command command,
162 			   void *arg, size_t arg_len, size_t buf_len, int *fds, int max_fds)
163 {
164 	struct vfio_user_request req = {};
165 	size_t sz_payload;
166 	int ret;
167 	bool fds_write = false;
168 
169 	if (arg_len > VFIO_USER_MAX_PAYLOAD_SIZE) {
170 		SPDK_ERRLOG("Oversized argument length, command %u\n", command);
171 		return -EINVAL;
172 	}
173 
174 	req.hdr.cmd = command;
175 	req.hdr.msg_size = sizeof(struct vfio_user_header) + arg_len;
176 	memcpy(req.payload, arg, arg_len);
177 
178 	if (command == VFIO_USER_DMA_MAP || command == VFIO_USER_DMA_UNMAP) {
179 		fds_write = true;
180 	}
181 
182 	SPDK_DEBUGLOG(vfio_user, "[I] Command %s, msg size %u, fds %p, max_fds %d\n",
183 		      vfio_user_message_str[command], req.hdr.msg_size, fds, max_fds);
184 
185 	if (fds_write && fds) {
186 		ret = vfio_user_write(dev->fd, (void *)&req, req.hdr.msg_size, fds, max_fds);
187 	} else {
188 		ret = vfio_user_write(dev->fd, (void *)&req, req.hdr.msg_size, NULL, 0);
189 	}
190 
191 	if (ret) {
192 		return ret;
193 	}
194 
195 	/* a reply is mandatory */
196 	memset(&req, 0, sizeof(req));
197 	ret = vfio_user_read(dev->fd, &req);
198 	if (ret) {
199 		return ret;
200 	}
201 
202 	SPDK_DEBUGLOG(vfio_user, "[I] Command %s response, msg size %u\n",
203 		      vfio_user_message_str[req.hdr.cmd], req.hdr.msg_size);
204 
205 	assert(req.hdr.flags.type == VFIO_USER_MESSAGE_REPLY);
206 	sz_payload = req.hdr.msg_size - sizeof(struct vfio_user_header);
207 	if (!sz_payload) {
208 		return 0;
209 	}
210 
211 	if (!fds_write) {
212 		if (sz_payload > buf_len) {
213 			SPDK_ERRLOG("Payload size error sz %zd, buf_len %zd\n", sz_payload, buf_len);
214 			return -EIO;
215 		}
216 		memcpy(arg, req.payload, sz_payload);
217 		/* VFIO_USER_DEVICE_GET_REGION_INFO may contains BAR fd */
218 		if (fds && req.fd_num) {
219 			assert(req.fd_num < max_fds);
220 			memcpy(fds, req.fds, sizeof(int) * req.fd_num);
221 		}
222 	}
223 
224 	return 0;
225 }
226 
227 static int
228 vfio_user_check_version(struct vfio_device *dev)
229 {
230 	int ret;
231 	struct vfio_user_request req = {};
232 	struct vfio_user_version *version = (struct vfio_user_version *)req.payload;
233 
234 	version->major = VFIO_USER_MAJOR_VER;
235 	version->minor = VFIO_USER_MINOR_VER;
236 
237 	ret = vfio_user_dev_send_request(dev, VFIO_USER_VERSION, req.payload,
238 					 sizeof(struct vfio_user_version), sizeof(req.payload), NULL, 0);
239 	if (ret < 0) {
240 		return ret;
241 	}
242 
243 	SPDK_DEBUGLOG(vfio_user, "%s Negotiate version %u.%u\n", vfio_user_message_str[VFIO_USER_VERSION],
244 		      version->major, version->minor);
245 
246 	return 0;
247 }
248 
249 int
250 vfio_user_get_dev_region_info(struct vfio_device *dev, struct vfio_region_info *region_info,
251 			      size_t buf_len, int *fds, int num_fds)
252 {
253 	assert(buf_len > sizeof(struct vfio_region_info));
254 	region_info->argsz = buf_len - sizeof(struct vfio_region_info);
255 	return vfio_user_dev_send_request(dev, VFIO_USER_DEVICE_GET_REGION_INFO,
256 					  region_info, region_info->argsz, buf_len, fds, num_fds);
257 }
258 
259 int
260 vfio_user_get_dev_info(struct vfio_device *dev, struct vfio_user_device_info *dev_info,
261 		       size_t buf_len)
262 {
263 	dev_info->argsz = sizeof(struct vfio_user_device_info);
264 	return vfio_user_dev_send_request(dev, VFIO_USER_DEVICE_GET_INFO,
265 					  dev_info, dev_info->argsz, buf_len, NULL, 0);
266 }
267 
268 int
269 vfio_user_dev_dma_map_unmap(struct vfio_device *dev, struct vfio_memory_region *mr, bool map)
270 {
271 	struct vfio_user_dma_map dma_map = { 0 };
272 	struct vfio_user_dma_unmap dma_unmap = { 0 };
273 
274 	if (map) {
275 		dma_map.argsz = sizeof(struct vfio_user_dma_map);
276 		dma_map.addr = mr->iova;
277 		dma_map.size = mr->size;
278 		dma_map.offset = mr->offset;
279 		dma_map.flags = VFIO_USER_F_DMA_REGION_READ | VFIO_USER_F_DMA_REGION_WRITE;
280 
281 		return vfio_user_dev_send_request(dev, VFIO_USER_DMA_MAP,
282 						  &dma_map, sizeof(dma_map), sizeof(dma_map), &mr->fd, 1);
283 	} else {
284 		dma_unmap.argsz = sizeof(struct vfio_user_dma_unmap);
285 		dma_unmap.addr = mr->iova;
286 		dma_unmap.size = mr->size;
287 		return vfio_user_dev_send_request(dev, VFIO_USER_DMA_UNMAP,
288 						  &dma_unmap, sizeof(dma_unmap), sizeof(dma_unmap), &mr->fd, 1);
289 	}
290 }
291 
292 int
293 vfio_user_dev_mmio_access(struct vfio_device *dev, uint32_t index, uint64_t offset,
294 			  size_t len, void *buf, bool is_write)
295 {
296 	struct vfio_user_region_access *access;
297 	size_t arg_len;
298 	int ret;
299 
300 	arg_len = sizeof(*access) + len;
301 	access = calloc(1, arg_len);
302 	if (!access) {
303 		return -ENOMEM;
304 	}
305 
306 	access->offset = offset;
307 	access->region = index;
308 	access->count = len;
309 	if (is_write) {
310 		memcpy(access->data, buf, len);
311 		ret = vfio_user_dev_send_request(dev, VFIO_USER_REGION_WRITE,
312 						 access, arg_len, arg_len, NULL, 0);
313 	} else {
314 		ret = vfio_user_dev_send_request(dev, VFIO_USER_REGION_READ,
315 						 access, sizeof(*access), arg_len, NULL, 0);
316 	}
317 
318 	if (ret) {
319 		free(access);
320 		return ret;
321 	}
322 
323 	if (!is_write) {
324 		memcpy(buf, (void *)access->data, len);
325 	}
326 
327 	free(access);
328 	return 0;
329 }
330 
331 int
332 vfio_user_dev_setup(struct vfio_device *dev)
333 {
334 	int fd;
335 	int flag;
336 	struct sockaddr_un un;
337 	ssize_t rc;
338 
339 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
340 	if (fd < 0) {
341 		SPDK_ERRLOG("socket() error\n");
342 		return -errno;
343 	}
344 
345 	flag = fcntl(fd, F_GETFD);
346 	if (fcntl(fd, F_SETFD, flag | FD_CLOEXEC) < 0) {
347 		SPDK_ERRLOG("fcntl failed\n");
348 	}
349 
350 	memset(&un, 0, sizeof(un));
351 	un.sun_family = AF_UNIX;
352 	rc = snprintf(un.sun_path, sizeof(un.sun_path), "%s", dev->path);
353 	if (rc < 0 || (size_t)rc >= sizeof(un.sun_path)) {
354 		SPDK_ERRLOG("socket path too long\n");
355 		close(fd);
356 		if (rc < 0) {
357 			return -errno;
358 		} else {
359 			return -EINVAL;
360 		}
361 	}
362 	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
363 		SPDK_ERRLOG("connect error\n");
364 		close(fd);
365 		return -errno;
366 	}
367 
368 	dev->fd = fd;
369 
370 	if (vfio_user_check_version(dev)) {
371 		SPDK_ERRLOG("Check VFIO_USER_VERSION message failed\n");
372 		close(fd);
373 		return -EFAULT;
374 	}
375 
376 	return 0;
377 }
378 
379 SPDK_LOG_REGISTER_COMPONENT(vfio_user)
380