xref: /openbmc/qemu/hw/vfio/device.c (revision 68c07d76359589c9de2aa190d247afca7eb8cb8f)
1*68c07d76SCédric Le Goater /*
2*68c07d76SCédric Le Goater  * VFIO device
3*68c07d76SCédric Le Goater  *
4*68c07d76SCédric Le Goater  * Copyright Red Hat, Inc. 2012
5*68c07d76SCédric Le Goater  *
6*68c07d76SCédric Le Goater  * Authors:
7*68c07d76SCédric Le Goater  *  Alex Williamson <alex.williamson@redhat.com>
8*68c07d76SCédric Le Goater  *
9*68c07d76SCédric Le Goater  * This work is licensed under the terms of the GNU GPL, version 2.  See
10*68c07d76SCédric Le Goater  * the COPYING file in the top-level directory.
11*68c07d76SCédric Le Goater  *
12*68c07d76SCédric Le Goater  * Based on qemu-kvm device-assignment:
13*68c07d76SCédric Le Goater  *  Adapted for KVM by Qumranet.
14*68c07d76SCédric Le Goater  *  Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com)
15*68c07d76SCédric Le Goater  *  Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com)
16*68c07d76SCédric Le Goater  *  Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com)
17*68c07d76SCédric Le Goater  *  Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com)
18*68c07d76SCédric Le Goater  *  Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com)
19*68c07d76SCédric Le Goater  */
20*68c07d76SCédric Le Goater 
21*68c07d76SCédric Le Goater #include "qemu/osdep.h"
22*68c07d76SCédric Le Goater #include <sys/ioctl.h>
23*68c07d76SCédric Le Goater 
24*68c07d76SCédric Le Goater #include "hw/vfio/vfio-common.h"
25*68c07d76SCédric Le Goater #include "hw/vfio/pci.h"
26*68c07d76SCédric Le Goater #include "hw/hw.h"
27*68c07d76SCédric Le Goater #include "trace.h"
28*68c07d76SCédric Le Goater #include "qapi/error.h"
29*68c07d76SCédric Le Goater #include "qemu/error-report.h"
30*68c07d76SCédric Le Goater #include "qemu/units.h"
31*68c07d76SCédric Le Goater #include "monitor/monitor.h"
32*68c07d76SCédric Le Goater #include "vfio-helpers.h"
33*68c07d76SCédric Le Goater 
34*68c07d76SCédric Le Goater /*
35*68c07d76SCédric Le Goater  * Common VFIO interrupt disable
36*68c07d76SCédric Le Goater  */
37*68c07d76SCédric Le Goater void vfio_disable_irqindex(VFIODevice *vbasedev, int index)
38*68c07d76SCédric Le Goater {
39*68c07d76SCédric Le Goater     struct vfio_irq_set irq_set = {
40*68c07d76SCédric Le Goater         .argsz = sizeof(irq_set),
41*68c07d76SCédric Le Goater         .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER,
42*68c07d76SCédric Le Goater         .index = index,
43*68c07d76SCédric Le Goater         .start = 0,
44*68c07d76SCédric Le Goater         .count = 0,
45*68c07d76SCédric Le Goater     };
46*68c07d76SCédric Le Goater 
47*68c07d76SCédric Le Goater     ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
48*68c07d76SCédric Le Goater }
49*68c07d76SCédric Le Goater 
50*68c07d76SCédric Le Goater void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index)
51*68c07d76SCédric Le Goater {
52*68c07d76SCédric Le Goater     struct vfio_irq_set irq_set = {
53*68c07d76SCédric Le Goater         .argsz = sizeof(irq_set),
54*68c07d76SCédric Le Goater         .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK,
55*68c07d76SCédric Le Goater         .index = index,
56*68c07d76SCédric Le Goater         .start = 0,
57*68c07d76SCédric Le Goater         .count = 1,
58*68c07d76SCédric Le Goater     };
59*68c07d76SCédric Le Goater 
60*68c07d76SCédric Le Goater     ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
61*68c07d76SCédric Le Goater }
62*68c07d76SCédric Le Goater 
63*68c07d76SCédric Le Goater void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index)
64*68c07d76SCédric Le Goater {
65*68c07d76SCédric Le Goater     struct vfio_irq_set irq_set = {
66*68c07d76SCédric Le Goater         .argsz = sizeof(irq_set),
67*68c07d76SCédric Le Goater         .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK,
68*68c07d76SCédric Le Goater         .index = index,
69*68c07d76SCédric Le Goater         .start = 0,
70*68c07d76SCédric Le Goater         .count = 1,
71*68c07d76SCédric Le Goater     };
72*68c07d76SCédric Le Goater 
73*68c07d76SCédric Le Goater     ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
74*68c07d76SCédric Le Goater }
75*68c07d76SCédric Le Goater 
76*68c07d76SCédric Le Goater static inline const char *action_to_str(int action)
77*68c07d76SCédric Le Goater {
78*68c07d76SCédric Le Goater     switch (action) {
79*68c07d76SCédric Le Goater     case VFIO_IRQ_SET_ACTION_MASK:
80*68c07d76SCédric Le Goater         return "MASK";
81*68c07d76SCédric Le Goater     case VFIO_IRQ_SET_ACTION_UNMASK:
82*68c07d76SCédric Le Goater         return "UNMASK";
83*68c07d76SCédric Le Goater     case VFIO_IRQ_SET_ACTION_TRIGGER:
84*68c07d76SCédric Le Goater         return "TRIGGER";
85*68c07d76SCédric Le Goater     default:
86*68c07d76SCédric Le Goater         return "UNKNOWN ACTION";
87*68c07d76SCédric Le Goater     }
88*68c07d76SCédric Le Goater }
89*68c07d76SCédric Le Goater 
90*68c07d76SCédric Le Goater static const char *index_to_str(VFIODevice *vbasedev, int index)
91*68c07d76SCédric Le Goater {
92*68c07d76SCédric Le Goater     if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) {
93*68c07d76SCédric Le Goater         return NULL;
94*68c07d76SCédric Le Goater     }
95*68c07d76SCédric Le Goater 
96*68c07d76SCédric Le Goater     switch (index) {
97*68c07d76SCédric Le Goater     case VFIO_PCI_INTX_IRQ_INDEX:
98*68c07d76SCédric Le Goater         return "INTX";
99*68c07d76SCédric Le Goater     case VFIO_PCI_MSI_IRQ_INDEX:
100*68c07d76SCédric Le Goater         return "MSI";
101*68c07d76SCédric Le Goater     case VFIO_PCI_MSIX_IRQ_INDEX:
102*68c07d76SCédric Le Goater         return "MSIX";
103*68c07d76SCédric Le Goater     case VFIO_PCI_ERR_IRQ_INDEX:
104*68c07d76SCédric Le Goater         return "ERR";
105*68c07d76SCédric Le Goater     case VFIO_PCI_REQ_IRQ_INDEX:
106*68c07d76SCédric Le Goater         return "REQ";
107*68c07d76SCédric Le Goater     default:
108*68c07d76SCédric Le Goater         return NULL;
109*68c07d76SCédric Le Goater     }
110*68c07d76SCédric Le Goater }
111*68c07d76SCédric Le Goater 
112*68c07d76SCédric Le Goater bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
113*68c07d76SCédric Le Goater                             int action, int fd, Error **errp)
114*68c07d76SCédric Le Goater {
115*68c07d76SCédric Le Goater     ERRP_GUARD();
116*68c07d76SCédric Le Goater     g_autofree struct vfio_irq_set *irq_set = NULL;
117*68c07d76SCédric Le Goater     int argsz;
118*68c07d76SCédric Le Goater     const char *name;
119*68c07d76SCédric Le Goater     int32_t *pfd;
120*68c07d76SCédric Le Goater 
121*68c07d76SCédric Le Goater     argsz = sizeof(*irq_set) + sizeof(*pfd);
122*68c07d76SCédric Le Goater 
123*68c07d76SCédric Le Goater     irq_set = g_malloc0(argsz);
124*68c07d76SCédric Le Goater     irq_set->argsz = argsz;
125*68c07d76SCédric Le Goater     irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | action;
126*68c07d76SCédric Le Goater     irq_set->index = index;
127*68c07d76SCédric Le Goater     irq_set->start = subindex;
128*68c07d76SCédric Le Goater     irq_set->count = 1;
129*68c07d76SCédric Le Goater     pfd = (int32_t *)&irq_set->data;
130*68c07d76SCédric Le Goater     *pfd = fd;
131*68c07d76SCédric Le Goater 
132*68c07d76SCédric Le Goater     if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
133*68c07d76SCédric Le Goater         return true;
134*68c07d76SCédric Le Goater     }
135*68c07d76SCédric Le Goater 
136*68c07d76SCédric Le Goater     error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure");
137*68c07d76SCédric Le Goater 
138*68c07d76SCédric Le Goater     name = index_to_str(vbasedev, index);
139*68c07d76SCédric Le Goater     if (name) {
140*68c07d76SCédric Le Goater         error_prepend(errp, "%s-%d: ", name, subindex);
141*68c07d76SCédric Le Goater     } else {
142*68c07d76SCédric Le Goater         error_prepend(errp, "index %d-%d: ", index, subindex);
143*68c07d76SCédric Le Goater     }
144*68c07d76SCédric Le Goater     error_prepend(errp,
145*68c07d76SCédric Le Goater                   "Failed to %s %s eventfd signaling for interrupt ",
146*68c07d76SCédric Le Goater                   fd < 0 ? "tear down" : "set up", action_to_str(action));
147*68c07d76SCédric Le Goater     return false;
148*68c07d76SCédric Le Goater }
149*68c07d76SCédric Le Goater 
150*68c07d76SCédric Le Goater int vfio_get_region_info(VFIODevice *vbasedev, int index,
151*68c07d76SCédric Le Goater                          struct vfio_region_info **info)
152*68c07d76SCédric Le Goater {
153*68c07d76SCédric Le Goater     size_t argsz = sizeof(struct vfio_region_info);
154*68c07d76SCédric Le Goater 
155*68c07d76SCédric Le Goater     *info = g_malloc0(argsz);
156*68c07d76SCédric Le Goater 
157*68c07d76SCédric Le Goater     (*info)->index = index;
158*68c07d76SCédric Le Goater retry:
159*68c07d76SCédric Le Goater     (*info)->argsz = argsz;
160*68c07d76SCédric Le Goater 
161*68c07d76SCédric Le Goater     if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) {
162*68c07d76SCédric Le Goater         g_free(*info);
163*68c07d76SCédric Le Goater         *info = NULL;
164*68c07d76SCédric Le Goater         return -errno;
165*68c07d76SCédric Le Goater     }
166*68c07d76SCédric Le Goater 
167*68c07d76SCédric Le Goater     if ((*info)->argsz > argsz) {
168*68c07d76SCédric Le Goater         argsz = (*info)->argsz;
169*68c07d76SCédric Le Goater         *info = g_realloc(*info, argsz);
170*68c07d76SCédric Le Goater 
171*68c07d76SCédric Le Goater         goto retry;
172*68c07d76SCédric Le Goater     }
173*68c07d76SCédric Le Goater 
174*68c07d76SCédric Le Goater     return 0;
175*68c07d76SCédric Le Goater }
176*68c07d76SCédric Le Goater 
177*68c07d76SCédric Le Goater int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
178*68c07d76SCédric Le Goater                              uint32_t subtype, struct vfio_region_info **info)
179*68c07d76SCédric Le Goater {
180*68c07d76SCédric Le Goater     int i;
181*68c07d76SCédric Le Goater 
182*68c07d76SCédric Le Goater     for (i = 0; i < vbasedev->num_regions; i++) {
183*68c07d76SCédric Le Goater         struct vfio_info_cap_header *hdr;
184*68c07d76SCédric Le Goater         struct vfio_region_info_cap_type *cap_type;
185*68c07d76SCédric Le Goater 
186*68c07d76SCédric Le Goater         if (vfio_get_region_info(vbasedev, i, info)) {
187*68c07d76SCédric Le Goater             continue;
188*68c07d76SCédric Le Goater         }
189*68c07d76SCédric Le Goater 
190*68c07d76SCédric Le Goater         hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE);
191*68c07d76SCédric Le Goater         if (!hdr) {
192*68c07d76SCédric Le Goater             g_free(*info);
193*68c07d76SCédric Le Goater             continue;
194*68c07d76SCédric Le Goater         }
195*68c07d76SCédric Le Goater 
196*68c07d76SCédric Le Goater         cap_type = container_of(hdr, struct vfio_region_info_cap_type, header);
197*68c07d76SCédric Le Goater 
198*68c07d76SCédric Le Goater         trace_vfio_get_dev_region(vbasedev->name, i,
199*68c07d76SCédric Le Goater                                   cap_type->type, cap_type->subtype);
200*68c07d76SCédric Le Goater 
201*68c07d76SCédric Le Goater         if (cap_type->type == type && cap_type->subtype == subtype) {
202*68c07d76SCédric Le Goater             return 0;
203*68c07d76SCédric Le Goater         }
204*68c07d76SCédric Le Goater 
205*68c07d76SCédric Le Goater         g_free(*info);
206*68c07d76SCédric Le Goater     }
207*68c07d76SCédric Le Goater 
208*68c07d76SCédric Le Goater     *info = NULL;
209*68c07d76SCédric Le Goater     return -ENODEV;
210*68c07d76SCédric Le Goater }
211*68c07d76SCédric Le Goater 
212*68c07d76SCédric Le Goater bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type)
213*68c07d76SCédric Le Goater {
214*68c07d76SCédric Le Goater     g_autofree struct vfio_region_info *info = NULL;
215*68c07d76SCédric Le Goater     bool ret = false;
216*68c07d76SCédric Le Goater 
217*68c07d76SCédric Le Goater     if (!vfio_get_region_info(vbasedev, region, &info)) {
218*68c07d76SCédric Le Goater         if (vfio_get_region_info_cap(info, cap_type)) {
219*68c07d76SCédric Le Goater             ret = true;
220*68c07d76SCédric Le Goater         }
221*68c07d76SCédric Le Goater     }
222*68c07d76SCédric Le Goater 
223*68c07d76SCédric Le Goater     return ret;
224*68c07d76SCédric Le Goater }
225*68c07d76SCédric Le Goater 
226*68c07d76SCédric Le Goater bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
227*68c07d76SCédric Le Goater {
228*68c07d76SCédric Le Goater     ERRP_GUARD();
229*68c07d76SCédric Le Goater     struct stat st;
230*68c07d76SCédric Le Goater 
231*68c07d76SCédric Le Goater     if (vbasedev->fd < 0) {
232*68c07d76SCédric Le Goater         if (stat(vbasedev->sysfsdev, &st) < 0) {
233*68c07d76SCédric Le Goater             error_setg_errno(errp, errno, "no such host device");
234*68c07d76SCédric Le Goater             error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev);
235*68c07d76SCédric Le Goater             return false;
236*68c07d76SCédric Le Goater         }
237*68c07d76SCédric Le Goater         /* User may specify a name, e.g: VFIO platform device */
238*68c07d76SCédric Le Goater         if (!vbasedev->name) {
239*68c07d76SCédric Le Goater             vbasedev->name = g_path_get_basename(vbasedev->sysfsdev);
240*68c07d76SCédric Le Goater         }
241*68c07d76SCédric Le Goater     } else {
242*68c07d76SCédric Le Goater         if (!vbasedev->iommufd) {
243*68c07d76SCédric Le Goater             error_setg(errp, "Use FD passing only with iommufd backend");
244*68c07d76SCédric Le Goater             return false;
245*68c07d76SCédric Le Goater         }
246*68c07d76SCédric Le Goater         /*
247*68c07d76SCédric Le Goater          * Give a name with fd so any function printing out vbasedev->name
248*68c07d76SCédric Le Goater          * will not break.
249*68c07d76SCédric Le Goater          */
250*68c07d76SCédric Le Goater         if (!vbasedev->name) {
251*68c07d76SCédric Le Goater             vbasedev->name = g_strdup_printf("VFIO_FD%d", vbasedev->fd);
252*68c07d76SCédric Le Goater         }
253*68c07d76SCédric Le Goater     }
254*68c07d76SCédric Le Goater 
255*68c07d76SCédric Le Goater     return true;
256*68c07d76SCédric Le Goater }
257*68c07d76SCédric Le Goater 
258*68c07d76SCédric Le Goater void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp)
259*68c07d76SCédric Le Goater {
260*68c07d76SCédric Le Goater     ERRP_GUARD();
261*68c07d76SCédric Le Goater     int fd = monitor_fd_param(monitor_cur(), str, errp);
262*68c07d76SCédric Le Goater 
263*68c07d76SCédric Le Goater     if (fd < 0) {
264*68c07d76SCédric Le Goater         error_prepend(errp, "Could not parse remote object fd %s:", str);
265*68c07d76SCédric Le Goater         return;
266*68c07d76SCédric Le Goater     }
267*68c07d76SCédric Le Goater     vbasedev->fd = fd;
268*68c07d76SCédric Le Goater }
269*68c07d76SCédric Le Goater 
270*68c07d76SCédric Le Goater void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops,
271*68c07d76SCédric Le Goater                       DeviceState *dev, bool ram_discard)
272*68c07d76SCédric Le Goater {
273*68c07d76SCédric Le Goater     vbasedev->type = type;
274*68c07d76SCédric Le Goater     vbasedev->ops = ops;
275*68c07d76SCédric Le Goater     vbasedev->dev = dev;
276*68c07d76SCédric Le Goater     vbasedev->fd = -1;
277*68c07d76SCédric Le Goater 
278*68c07d76SCédric Le Goater     vbasedev->ram_block_discard_allowed = ram_discard;
279*68c07d76SCédric Le Goater }
280*68c07d76SCédric Le Goater 
281*68c07d76SCédric Le Goater int vfio_device_get_aw_bits(VFIODevice *vdev)
282*68c07d76SCédric Le Goater {
283*68c07d76SCédric Le Goater     /*
284*68c07d76SCédric Le Goater      * iova_ranges is a sorted list. For old kernels that support
285*68c07d76SCédric Le Goater      * VFIO but not support query of iova ranges, iova_ranges is NULL,
286*68c07d76SCédric Le Goater      * in this case HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX(64) is returned.
287*68c07d76SCédric Le Goater      */
288*68c07d76SCédric Le Goater     GList *l = g_list_last(vdev->bcontainer->iova_ranges);
289*68c07d76SCédric Le Goater 
290*68c07d76SCédric Le Goater     if (l) {
291*68c07d76SCédric Le Goater         Range *range = l->data;
292*68c07d76SCédric Le Goater         return range_get_last_bit(range) + 1;
293*68c07d76SCédric Le Goater     }
294*68c07d76SCédric Le Goater 
295*68c07d76SCédric Le Goater     return HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX;
296*68c07d76SCédric Le Goater }
297*68c07d76SCédric Le Goater 
298*68c07d76SCédric Le Goater bool vfio_device_is_mdev(VFIODevice *vbasedev)
299*68c07d76SCédric Le Goater {
300*68c07d76SCédric Le Goater     g_autofree char *subsys = NULL;
301*68c07d76SCédric Le Goater     g_autofree char *tmp = NULL;
302*68c07d76SCédric Le Goater 
303*68c07d76SCédric Le Goater     if (!vbasedev->sysfsdev) {
304*68c07d76SCédric Le Goater         return false;
305*68c07d76SCédric Le Goater     }
306*68c07d76SCédric Le Goater 
307*68c07d76SCédric Le Goater     tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev);
308*68c07d76SCédric Le Goater     subsys = realpath(tmp, NULL);
309*68c07d76SCédric Le Goater     return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0);
310*68c07d76SCédric Le Goater }
311*68c07d76SCédric Le Goater 
312*68c07d76SCédric Le Goater bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp)
313*68c07d76SCédric Le Goater {
314*68c07d76SCédric Le Goater     HostIOMMUDevice *hiod = vbasedev->hiod;
315*68c07d76SCédric Le Goater 
316*68c07d76SCédric Le Goater     if (!hiod) {
317*68c07d76SCédric Le Goater         return true;
318*68c07d76SCédric Le Goater     }
319*68c07d76SCédric Le Goater 
320*68c07d76SCédric Le Goater     return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp);
321*68c07d76SCédric Le Goater }
322*68c07d76SCédric Le Goater 
323*68c07d76SCédric Le Goater VFIODevice *vfio_get_vfio_device(Object *obj)
324*68c07d76SCédric Le Goater {
325*68c07d76SCédric Le Goater     if (object_dynamic_cast(obj, TYPE_VFIO_PCI)) {
326*68c07d76SCédric Le Goater         return &VFIO_PCI(obj)->vbasedev;
327*68c07d76SCédric Le Goater     } else {
328*68c07d76SCédric Le Goater         return NULL;
329*68c07d76SCédric Le Goater     }
330*68c07d76SCédric Le Goater }
331