xref: /linux/arch/um/drivers/vfio_user.c (revision cfc4ca8986bb1f6182da6cd7bb57f228590b4643)
1*a0e2cb6aSTiwei Bie // SPDX-License-Identifier: GPL-2.0
2*a0e2cb6aSTiwei Bie /*
3*a0e2cb6aSTiwei Bie  * Copyright (C) 2025 Ant Group
4*a0e2cb6aSTiwei Bie  * Author: Tiwei Bie <tiwei.btw@antgroup.com>
5*a0e2cb6aSTiwei Bie  */
6*a0e2cb6aSTiwei Bie #include <errno.h>
7*a0e2cb6aSTiwei Bie #include <fcntl.h>
8*a0e2cb6aSTiwei Bie #include <unistd.h>
9*a0e2cb6aSTiwei Bie #include <stdio.h>
10*a0e2cb6aSTiwei Bie #include <stdint.h>
11*a0e2cb6aSTiwei Bie #include <stdlib.h>
12*a0e2cb6aSTiwei Bie #include <string.h>
13*a0e2cb6aSTiwei Bie #include <sys/ioctl.h>
14*a0e2cb6aSTiwei Bie #include <sys/eventfd.h>
15*a0e2cb6aSTiwei Bie #include <linux/limits.h>
16*a0e2cb6aSTiwei Bie #include <linux/vfio.h>
17*a0e2cb6aSTiwei Bie #include <linux/pci_regs.h>
18*a0e2cb6aSTiwei Bie #include <as-layout.h>
19*a0e2cb6aSTiwei Bie #include <um_malloc.h>
20*a0e2cb6aSTiwei Bie 
21*a0e2cb6aSTiwei Bie #include "vfio_user.h"
22*a0e2cb6aSTiwei Bie 
uml_vfio_user_open_container(void)23*a0e2cb6aSTiwei Bie int uml_vfio_user_open_container(void)
24*a0e2cb6aSTiwei Bie {
25*a0e2cb6aSTiwei Bie 	int r, fd;
26*a0e2cb6aSTiwei Bie 
27*a0e2cb6aSTiwei Bie 	fd = open("/dev/vfio/vfio", O_RDWR);
28*a0e2cb6aSTiwei Bie 	if (fd < 0)
29*a0e2cb6aSTiwei Bie 		return -errno;
30*a0e2cb6aSTiwei Bie 
31*a0e2cb6aSTiwei Bie 	r = ioctl(fd, VFIO_GET_API_VERSION);
32*a0e2cb6aSTiwei Bie 	if (r != VFIO_API_VERSION) {
33*a0e2cb6aSTiwei Bie 		r = r < 0 ? -errno : -EINVAL;
34*a0e2cb6aSTiwei Bie 		goto error;
35*a0e2cb6aSTiwei Bie 	}
36*a0e2cb6aSTiwei Bie 
37*a0e2cb6aSTiwei Bie 	r = ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU);
38*a0e2cb6aSTiwei Bie 	if (r <= 0) {
39*a0e2cb6aSTiwei Bie 		r = r < 0 ? -errno : -EINVAL;
40*a0e2cb6aSTiwei Bie 		goto error;
41*a0e2cb6aSTiwei Bie 	}
42*a0e2cb6aSTiwei Bie 
43*a0e2cb6aSTiwei Bie 	return fd;
44*a0e2cb6aSTiwei Bie 
45*a0e2cb6aSTiwei Bie error:
46*a0e2cb6aSTiwei Bie 	close(fd);
47*a0e2cb6aSTiwei Bie 	return r;
48*a0e2cb6aSTiwei Bie }
49*a0e2cb6aSTiwei Bie 
uml_vfio_user_setup_iommu(int container)50*a0e2cb6aSTiwei Bie int uml_vfio_user_setup_iommu(int container)
51*a0e2cb6aSTiwei Bie {
52*a0e2cb6aSTiwei Bie 	/*
53*a0e2cb6aSTiwei Bie 	 * This is a bit tricky. See the big comment in
54*a0e2cb6aSTiwei Bie 	 * vhost_user_set_mem_table() in virtio_uml.c.
55*a0e2cb6aSTiwei Bie 	 */
56*a0e2cb6aSTiwei Bie 	unsigned long reserved = uml_reserved - uml_physmem;
57*a0e2cb6aSTiwei Bie 	struct vfio_iommu_type1_dma_map dma_map = {
58*a0e2cb6aSTiwei Bie 		.argsz = sizeof(dma_map),
59*a0e2cb6aSTiwei Bie 		.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
60*a0e2cb6aSTiwei Bie 		.vaddr = uml_reserved,
61*a0e2cb6aSTiwei Bie 		.iova = reserved,
62*a0e2cb6aSTiwei Bie 		.size = physmem_size - reserved,
63*a0e2cb6aSTiwei Bie 	};
64*a0e2cb6aSTiwei Bie 
65*a0e2cb6aSTiwei Bie 	if (ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU) < 0)
66*a0e2cb6aSTiwei Bie 		return -errno;
67*a0e2cb6aSTiwei Bie 
68*a0e2cb6aSTiwei Bie 	if (ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map) < 0)
69*a0e2cb6aSTiwei Bie 		return -errno;
70*a0e2cb6aSTiwei Bie 
71*a0e2cb6aSTiwei Bie 	return 0;
72*a0e2cb6aSTiwei Bie }
73*a0e2cb6aSTiwei Bie 
uml_vfio_user_get_group_id(const char * device)74*a0e2cb6aSTiwei Bie int uml_vfio_user_get_group_id(const char *device)
75*a0e2cb6aSTiwei Bie {
76*a0e2cb6aSTiwei Bie 	char *path, *buf, *end;
77*a0e2cb6aSTiwei Bie 	const char *name;
78*a0e2cb6aSTiwei Bie 	int r;
79*a0e2cb6aSTiwei Bie 
80*a0e2cb6aSTiwei Bie 	path = uml_kmalloc(PATH_MAX, UM_GFP_KERNEL);
81*a0e2cb6aSTiwei Bie 	if (!path)
82*a0e2cb6aSTiwei Bie 		return -ENOMEM;
83*a0e2cb6aSTiwei Bie 
84*a0e2cb6aSTiwei Bie 	sprintf(path, "/sys/bus/pci/devices/%s/iommu_group", device);
85*a0e2cb6aSTiwei Bie 
86*a0e2cb6aSTiwei Bie 	buf = uml_kmalloc(PATH_MAX + 1, UM_GFP_KERNEL);
87*a0e2cb6aSTiwei Bie 	if (!buf) {
88*a0e2cb6aSTiwei Bie 		r = -ENOMEM;
89*a0e2cb6aSTiwei Bie 		goto free_path;
90*a0e2cb6aSTiwei Bie 	}
91*a0e2cb6aSTiwei Bie 
92*a0e2cb6aSTiwei Bie 	r = readlink(path, buf, PATH_MAX);
93*a0e2cb6aSTiwei Bie 	if (r < 0) {
94*a0e2cb6aSTiwei Bie 		r = -errno;
95*a0e2cb6aSTiwei Bie 		goto free_buf;
96*a0e2cb6aSTiwei Bie 	}
97*a0e2cb6aSTiwei Bie 	buf[r] = '\0';
98*a0e2cb6aSTiwei Bie 
99*a0e2cb6aSTiwei Bie 	name = basename(buf);
100*a0e2cb6aSTiwei Bie 
101*a0e2cb6aSTiwei Bie 	r = strtoul(name, &end, 10);
102*a0e2cb6aSTiwei Bie 	if (*end != '\0' || end == name) {
103*a0e2cb6aSTiwei Bie 		r = -EINVAL;
104*a0e2cb6aSTiwei Bie 		goto free_buf;
105*a0e2cb6aSTiwei Bie 	}
106*a0e2cb6aSTiwei Bie 
107*a0e2cb6aSTiwei Bie free_buf:
108*a0e2cb6aSTiwei Bie 	kfree(buf);
109*a0e2cb6aSTiwei Bie free_path:
110*a0e2cb6aSTiwei Bie 	kfree(path);
111*a0e2cb6aSTiwei Bie 	return r;
112*a0e2cb6aSTiwei Bie }
113*a0e2cb6aSTiwei Bie 
uml_vfio_user_open_group(int group_id)114*a0e2cb6aSTiwei Bie int uml_vfio_user_open_group(int group_id)
115*a0e2cb6aSTiwei Bie {
116*a0e2cb6aSTiwei Bie 	char *path;
117*a0e2cb6aSTiwei Bie 	int fd;
118*a0e2cb6aSTiwei Bie 
119*a0e2cb6aSTiwei Bie 	path = uml_kmalloc(PATH_MAX, UM_GFP_KERNEL);
120*a0e2cb6aSTiwei Bie 	if (!path)
121*a0e2cb6aSTiwei Bie 		return -ENOMEM;
122*a0e2cb6aSTiwei Bie 
123*a0e2cb6aSTiwei Bie 	sprintf(path, "/dev/vfio/%d", group_id);
124*a0e2cb6aSTiwei Bie 
125*a0e2cb6aSTiwei Bie 	fd = open(path, O_RDWR);
126*a0e2cb6aSTiwei Bie 	if (fd < 0) {
127*a0e2cb6aSTiwei Bie 		fd = -errno;
128*a0e2cb6aSTiwei Bie 		goto out;
129*a0e2cb6aSTiwei Bie 	}
130*a0e2cb6aSTiwei Bie 
131*a0e2cb6aSTiwei Bie out:
132*a0e2cb6aSTiwei Bie 	kfree(path);
133*a0e2cb6aSTiwei Bie 	return fd;
134*a0e2cb6aSTiwei Bie }
135*a0e2cb6aSTiwei Bie 
uml_vfio_user_set_container(int container,int group)136*a0e2cb6aSTiwei Bie int uml_vfio_user_set_container(int container, int group)
137*a0e2cb6aSTiwei Bie {
138*a0e2cb6aSTiwei Bie 	if (ioctl(group, VFIO_GROUP_SET_CONTAINER, &container) < 0)
139*a0e2cb6aSTiwei Bie 		return -errno;
140*a0e2cb6aSTiwei Bie 	return 0;
141*a0e2cb6aSTiwei Bie }
142*a0e2cb6aSTiwei Bie 
uml_vfio_user_unset_container(int container,int group)143*a0e2cb6aSTiwei Bie int uml_vfio_user_unset_container(int container, int group)
144*a0e2cb6aSTiwei Bie {
145*a0e2cb6aSTiwei Bie 	if (ioctl(group, VFIO_GROUP_UNSET_CONTAINER, &container) < 0)
146*a0e2cb6aSTiwei Bie 		return -errno;
147*a0e2cb6aSTiwei Bie 	return 0;
148*a0e2cb6aSTiwei Bie }
149*a0e2cb6aSTiwei Bie 
vfio_set_irqs(int device,int start,int count,int * irqfd)150*a0e2cb6aSTiwei Bie static int vfio_set_irqs(int device, int start, int count, int *irqfd)
151*a0e2cb6aSTiwei Bie {
152*a0e2cb6aSTiwei Bie 	struct vfio_irq_set *irq_set;
153*a0e2cb6aSTiwei Bie 	int argsz = sizeof(*irq_set) + sizeof(*irqfd) * count;
154*a0e2cb6aSTiwei Bie 	int err = 0;
155*a0e2cb6aSTiwei Bie 
156*a0e2cb6aSTiwei Bie 	irq_set = uml_kmalloc(argsz, UM_GFP_KERNEL);
157*a0e2cb6aSTiwei Bie 	if (!irq_set)
158*a0e2cb6aSTiwei Bie 		return -ENOMEM;
159*a0e2cb6aSTiwei Bie 
160*a0e2cb6aSTiwei Bie 	irq_set->argsz = argsz;
161*a0e2cb6aSTiwei Bie 	irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
162*a0e2cb6aSTiwei Bie 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
163*a0e2cb6aSTiwei Bie 	irq_set->start = start;
164*a0e2cb6aSTiwei Bie 	irq_set->count = count;
165*a0e2cb6aSTiwei Bie 	memcpy(irq_set->data, irqfd, sizeof(*irqfd) * count);
166*a0e2cb6aSTiwei Bie 
167*a0e2cb6aSTiwei Bie 	if (ioctl(device, VFIO_DEVICE_SET_IRQS, irq_set) < 0) {
168*a0e2cb6aSTiwei Bie 		err = -errno;
169*a0e2cb6aSTiwei Bie 		goto out;
170*a0e2cb6aSTiwei Bie 	}
171*a0e2cb6aSTiwei Bie 
172*a0e2cb6aSTiwei Bie out:
173*a0e2cb6aSTiwei Bie 	kfree(irq_set);
174*a0e2cb6aSTiwei Bie 	return err;
175*a0e2cb6aSTiwei Bie }
176*a0e2cb6aSTiwei Bie 
uml_vfio_user_setup_device(struct uml_vfio_user_device * dev,int group,const char * device)177*a0e2cb6aSTiwei Bie int uml_vfio_user_setup_device(struct uml_vfio_user_device *dev,
178*a0e2cb6aSTiwei Bie 			       int group, const char *device)
179*a0e2cb6aSTiwei Bie {
180*a0e2cb6aSTiwei Bie 	struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
181*a0e2cb6aSTiwei Bie 	struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
182*a0e2cb6aSTiwei Bie 	int err, i;
183*a0e2cb6aSTiwei Bie 
184*a0e2cb6aSTiwei Bie 	dev->device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, device);
185*a0e2cb6aSTiwei Bie 	if (dev->device < 0)
186*a0e2cb6aSTiwei Bie 		return -errno;
187*a0e2cb6aSTiwei Bie 
188*a0e2cb6aSTiwei Bie 	if (ioctl(dev->device, VFIO_DEVICE_GET_INFO, &device_info) < 0) {
189*a0e2cb6aSTiwei Bie 		err = -errno;
190*a0e2cb6aSTiwei Bie 		goto close_device;
191*a0e2cb6aSTiwei Bie 	}
192*a0e2cb6aSTiwei Bie 
193*a0e2cb6aSTiwei Bie 	dev->num_regions = device_info.num_regions;
194*a0e2cb6aSTiwei Bie 	if (dev->num_regions > VFIO_PCI_CONFIG_REGION_INDEX + 1)
195*a0e2cb6aSTiwei Bie 		dev->num_regions = VFIO_PCI_CONFIG_REGION_INDEX + 1;
196*a0e2cb6aSTiwei Bie 
197*a0e2cb6aSTiwei Bie 	dev->region = uml_kmalloc(sizeof(*dev->region) * dev->num_regions,
198*a0e2cb6aSTiwei Bie 				  UM_GFP_KERNEL);
199*a0e2cb6aSTiwei Bie 	if (!dev->region) {
200*a0e2cb6aSTiwei Bie 		err = -ENOMEM;
201*a0e2cb6aSTiwei Bie 		goto close_device;
202*a0e2cb6aSTiwei Bie 	}
203*a0e2cb6aSTiwei Bie 
204*a0e2cb6aSTiwei Bie 	for (i = 0; i < dev->num_regions; i++) {
205*a0e2cb6aSTiwei Bie 		struct vfio_region_info region = {
206*a0e2cb6aSTiwei Bie 			.argsz = sizeof(region),
207*a0e2cb6aSTiwei Bie 			.index = i,
208*a0e2cb6aSTiwei Bie 		};
209*a0e2cb6aSTiwei Bie 		if (ioctl(dev->device, VFIO_DEVICE_GET_REGION_INFO, &region) < 0) {
210*a0e2cb6aSTiwei Bie 			err = -errno;
211*a0e2cb6aSTiwei Bie 			goto free_region;
212*a0e2cb6aSTiwei Bie 		}
213*a0e2cb6aSTiwei Bie 		dev->region[i].size = region.size;
214*a0e2cb6aSTiwei Bie 		dev->region[i].offset = region.offset;
215*a0e2cb6aSTiwei Bie 	}
216*a0e2cb6aSTiwei Bie 
217*a0e2cb6aSTiwei Bie 	/* Only MSI-X is supported currently. */
218*a0e2cb6aSTiwei Bie 	irq_info.index = VFIO_PCI_MSIX_IRQ_INDEX;
219*a0e2cb6aSTiwei Bie 	if (ioctl(dev->device, VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0) {
220*a0e2cb6aSTiwei Bie 		err = -errno;
221*a0e2cb6aSTiwei Bie 		goto free_region;
222*a0e2cb6aSTiwei Bie 	}
223*a0e2cb6aSTiwei Bie 
224*a0e2cb6aSTiwei Bie 	dev->irq_count = irq_info.count;
225*a0e2cb6aSTiwei Bie 
226*a0e2cb6aSTiwei Bie 	dev->irqfd = uml_kmalloc(sizeof(int) * dev->irq_count, UM_GFP_KERNEL);
227*a0e2cb6aSTiwei Bie 	if (!dev->irqfd) {
228*a0e2cb6aSTiwei Bie 		err = -ENOMEM;
229*a0e2cb6aSTiwei Bie 		goto free_region;
230*a0e2cb6aSTiwei Bie 	}
231*a0e2cb6aSTiwei Bie 
232*a0e2cb6aSTiwei Bie 	memset(dev->irqfd, -1, sizeof(int) * dev->irq_count);
233*a0e2cb6aSTiwei Bie 
234*a0e2cb6aSTiwei Bie 	err = vfio_set_irqs(dev->device, 0, dev->irq_count, dev->irqfd);
235*a0e2cb6aSTiwei Bie 	if (err)
236*a0e2cb6aSTiwei Bie 		goto free_irqfd;
237*a0e2cb6aSTiwei Bie 
238*a0e2cb6aSTiwei Bie 	return 0;
239*a0e2cb6aSTiwei Bie 
240*a0e2cb6aSTiwei Bie free_irqfd:
241*a0e2cb6aSTiwei Bie 	kfree(dev->irqfd);
242*a0e2cb6aSTiwei Bie free_region:
243*a0e2cb6aSTiwei Bie 	kfree(dev->region);
244*a0e2cb6aSTiwei Bie close_device:
245*a0e2cb6aSTiwei Bie 	close(dev->device);
246*a0e2cb6aSTiwei Bie 	return err;
247*a0e2cb6aSTiwei Bie }
248*a0e2cb6aSTiwei Bie 
uml_vfio_user_teardown_device(struct uml_vfio_user_device * dev)249*a0e2cb6aSTiwei Bie void uml_vfio_user_teardown_device(struct uml_vfio_user_device *dev)
250*a0e2cb6aSTiwei Bie {
251*a0e2cb6aSTiwei Bie 	kfree(dev->irqfd);
252*a0e2cb6aSTiwei Bie 	kfree(dev->region);
253*a0e2cb6aSTiwei Bie 	close(dev->device);
254*a0e2cb6aSTiwei Bie }
255*a0e2cb6aSTiwei Bie 
uml_vfio_user_activate_irq(struct uml_vfio_user_device * dev,int index)256*a0e2cb6aSTiwei Bie int uml_vfio_user_activate_irq(struct uml_vfio_user_device *dev, int index)
257*a0e2cb6aSTiwei Bie {
258*a0e2cb6aSTiwei Bie 	int irqfd;
259*a0e2cb6aSTiwei Bie 
260*a0e2cb6aSTiwei Bie 	irqfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
261*a0e2cb6aSTiwei Bie 	if (irqfd < 0)
262*a0e2cb6aSTiwei Bie 		return -errno;
263*a0e2cb6aSTiwei Bie 
264*a0e2cb6aSTiwei Bie 	dev->irqfd[index] = irqfd;
265*a0e2cb6aSTiwei Bie 	return irqfd;
266*a0e2cb6aSTiwei Bie }
267*a0e2cb6aSTiwei Bie 
uml_vfio_user_deactivate_irq(struct uml_vfio_user_device * dev,int index)268*a0e2cb6aSTiwei Bie void uml_vfio_user_deactivate_irq(struct uml_vfio_user_device *dev, int index)
269*a0e2cb6aSTiwei Bie {
270*a0e2cb6aSTiwei Bie 	close(dev->irqfd[index]);
271*a0e2cb6aSTiwei Bie 	dev->irqfd[index] = -1;
272*a0e2cb6aSTiwei Bie }
273*a0e2cb6aSTiwei Bie 
uml_vfio_user_update_irqs(struct uml_vfio_user_device * dev)274*a0e2cb6aSTiwei Bie int uml_vfio_user_update_irqs(struct uml_vfio_user_device *dev)
275*a0e2cb6aSTiwei Bie {
276*a0e2cb6aSTiwei Bie 	return vfio_set_irqs(dev->device, 0, dev->irq_count, dev->irqfd);
277*a0e2cb6aSTiwei Bie }
278*a0e2cb6aSTiwei Bie 
vfio_region_read(struct uml_vfio_user_device * dev,unsigned int index,uint64_t offset,void * buf,uint64_t size)279*a0e2cb6aSTiwei Bie static int vfio_region_read(struct uml_vfio_user_device *dev, unsigned int index,
280*a0e2cb6aSTiwei Bie 			    uint64_t offset, void *buf, uint64_t size)
281*a0e2cb6aSTiwei Bie {
282*a0e2cb6aSTiwei Bie 	if (index >= dev->num_regions || offset + size > dev->region[index].size)
283*a0e2cb6aSTiwei Bie 		return -EINVAL;
284*a0e2cb6aSTiwei Bie 
285*a0e2cb6aSTiwei Bie 	if (pread(dev->device, buf, size, dev->region[index].offset + offset) < 0)
286*a0e2cb6aSTiwei Bie 		return -errno;
287*a0e2cb6aSTiwei Bie 
288*a0e2cb6aSTiwei Bie 	return 0;
289*a0e2cb6aSTiwei Bie }
290*a0e2cb6aSTiwei Bie 
vfio_region_write(struct uml_vfio_user_device * dev,unsigned int index,uint64_t offset,const void * buf,uint64_t size)291*a0e2cb6aSTiwei Bie static int vfio_region_write(struct uml_vfio_user_device *dev, unsigned int index,
292*a0e2cb6aSTiwei Bie 			     uint64_t offset, const void *buf, uint64_t size)
293*a0e2cb6aSTiwei Bie {
294*a0e2cb6aSTiwei Bie 	if (index >= dev->num_regions || offset + size > dev->region[index].size)
295*a0e2cb6aSTiwei Bie 		return -EINVAL;
296*a0e2cb6aSTiwei Bie 
297*a0e2cb6aSTiwei Bie 	if (pwrite(dev->device, buf, size, dev->region[index].offset + offset) < 0)
298*a0e2cb6aSTiwei Bie 		return -errno;
299*a0e2cb6aSTiwei Bie 
300*a0e2cb6aSTiwei Bie 	return 0;
301*a0e2cb6aSTiwei Bie }
302*a0e2cb6aSTiwei Bie 
uml_vfio_user_cfgspace_read(struct uml_vfio_user_device * dev,unsigned int offset,void * buf,int size)303*a0e2cb6aSTiwei Bie int uml_vfio_user_cfgspace_read(struct uml_vfio_user_device *dev,
304*a0e2cb6aSTiwei Bie 				unsigned int offset, void *buf, int size)
305*a0e2cb6aSTiwei Bie {
306*a0e2cb6aSTiwei Bie 	return vfio_region_read(dev, VFIO_PCI_CONFIG_REGION_INDEX,
307*a0e2cb6aSTiwei Bie 				offset, buf, size);
308*a0e2cb6aSTiwei Bie }
309*a0e2cb6aSTiwei Bie 
uml_vfio_user_cfgspace_write(struct uml_vfio_user_device * dev,unsigned int offset,const void * buf,int size)310*a0e2cb6aSTiwei Bie int uml_vfio_user_cfgspace_write(struct uml_vfio_user_device *dev,
311*a0e2cb6aSTiwei Bie 				 unsigned int offset, const void *buf, int size)
312*a0e2cb6aSTiwei Bie {
313*a0e2cb6aSTiwei Bie 	return vfio_region_write(dev, VFIO_PCI_CONFIG_REGION_INDEX,
314*a0e2cb6aSTiwei Bie 				 offset, buf, size);
315*a0e2cb6aSTiwei Bie }
316*a0e2cb6aSTiwei Bie 
uml_vfio_user_bar_read(struct uml_vfio_user_device * dev,int bar,unsigned int offset,void * buf,int size)317*a0e2cb6aSTiwei Bie int uml_vfio_user_bar_read(struct uml_vfio_user_device *dev, int bar,
318*a0e2cb6aSTiwei Bie 			   unsigned int offset, void *buf, int size)
319*a0e2cb6aSTiwei Bie {
320*a0e2cb6aSTiwei Bie 	return vfio_region_read(dev, bar, offset, buf, size);
321*a0e2cb6aSTiwei Bie }
322*a0e2cb6aSTiwei Bie 
uml_vfio_user_bar_write(struct uml_vfio_user_device * dev,int bar,unsigned int offset,const void * buf,int size)323*a0e2cb6aSTiwei Bie int uml_vfio_user_bar_write(struct uml_vfio_user_device *dev, int bar,
324*a0e2cb6aSTiwei Bie 			    unsigned int offset, const void *buf, int size)
325*a0e2cb6aSTiwei Bie {
326*a0e2cb6aSTiwei Bie 	return vfio_region_write(dev, bar, offset, buf, size);
327*a0e2cb6aSTiwei Bie }
328