xref: /qemu/hw/vfio-user/pci.c (revision 9fca2b7d702f7ba216c571504922b2f8994537cc)
1 /*
2  * vfio PCI device over a UNIX socket.
3  *
4  * Copyright © 2018, 2021 Oracle and/or its affiliates.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include <sys/ioctl.h>
10 #include "qemu/osdep.h"
11 #include "qapi-visit-sockets.h"
12 
13 #include "hw/qdev-properties.h"
14 #include "hw/vfio/pci.h"
15 
16 #define TYPE_VFIO_USER_PCI "vfio-user-pci"
17 OBJECT_DECLARE_SIMPLE_TYPE(VFIOUserPCIDevice, VFIO_USER_PCI)
18 
19 struct VFIOUserPCIDevice {
20     VFIOPCIDevice device;
21     SocketAddress *socket;
22 };
23 
24 /*
25  * Emulated devices don't use host hot reset
26  */
27 static void vfio_user_compute_needs_reset(VFIODevice *vbasedev)
28 {
29     vbasedev->needs_reset = false;
30 }
31 
32 static Object *vfio_user_pci_get_object(VFIODevice *vbasedev)
33 {
34     VFIOUserPCIDevice *vdev = container_of(vbasedev, VFIOUserPCIDevice,
35                                            device.vbasedev);
36 
37     return OBJECT(vdev);
38 }
39 
40 static VFIODeviceOps vfio_user_pci_ops = {
41     .vfio_compute_needs_reset = vfio_user_compute_needs_reset,
42     .vfio_eoi = vfio_pci_intx_eoi,
43     .vfio_get_object = vfio_user_pci_get_object,
44     /* No live migration support yet. */
45     .vfio_save_config = NULL,
46     .vfio_load_config = NULL,
47 };
48 
49 static void vfio_user_pci_realize(PCIDevice *pdev, Error **errp)
50 {
51     ERRP_GUARD();
52     VFIOUserPCIDevice *udev = VFIO_USER_PCI(pdev);
53     VFIOPCIDevice *vdev = VFIO_PCI_BASE(pdev);
54     VFIODevice *vbasedev = &vdev->vbasedev;
55     const char *sock_name;
56     AddressSpace *as;
57 
58     if (!udev->socket) {
59         error_setg(errp, "No socket specified");
60         error_append_hint(errp, "e.g. -device '{"
61             "\"driver\":\"vfio-user-pci\", "
62             "\"socket\": {\"path\": \"/tmp/vfio-user.sock\", "
63             "\"type\": \"unix\"}'"
64             "}'\n");
65         return;
66     }
67 
68     sock_name = udev->socket->u.q_unix.path;
69 
70     vbasedev->name = g_strdup_printf("vfio-user:%s", sock_name);
71 
72     /*
73      * vfio-user devices are effectively mdevs (don't use a host iommu).
74      */
75     vbasedev->mdev = true;
76 
77     as = pci_device_iommu_address_space(pdev);
78     if (!vfio_device_attach_by_iommu_type(TYPE_VFIO_IOMMU_USER,
79                                           vbasedev->name, vbasedev,
80                                           as, errp)) {
81         error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->name);
82         return;
83     }
84 }
85 
86 static void vfio_user_instance_init(Object *obj)
87 {
88     PCIDevice *pci_dev = PCI_DEVICE(obj);
89     VFIOPCIDevice *vdev = VFIO_PCI_BASE(obj);
90     VFIODevice *vbasedev = &vdev->vbasedev;
91 
92     device_add_bootindex_property(obj, &vdev->bootindex,
93                                   "bootindex", NULL,
94                                   &pci_dev->qdev);
95     vdev->host.domain = ~0U;
96     vdev->host.bus = ~0U;
97     vdev->host.slot = ~0U;
98     vdev->host.function = ~0U;
99 
100     vfio_device_init(vbasedev, VFIO_DEVICE_TYPE_PCI, &vfio_user_pci_ops,
101                      DEVICE(vdev), false);
102 
103     vdev->nv_gpudirect_clique = 0xFF;
104 
105     /*
106      * QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
107      * line, therefore, no need to wait to realize like other devices.
108      */
109     pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
110 }
111 
112 static void vfio_user_instance_finalize(Object *obj)
113 {
114     VFIOPCIDevice *vdev = VFIO_PCI_BASE(obj);
115 
116     vfio_pci_put_device(vdev);
117 }
118 
119 static const Property vfio_user_pci_dev_properties[] = {
120     DEFINE_PROP_UINT32("x-pci-vendor-id", VFIOPCIDevice,
121                        vendor_id, PCI_ANY_ID),
122     DEFINE_PROP_UINT32("x-pci-device-id", VFIOPCIDevice,
123                        device_id, PCI_ANY_ID),
124     DEFINE_PROP_UINT32("x-pci-sub-vendor-id", VFIOPCIDevice,
125                        sub_vendor_id, PCI_ANY_ID),
126     DEFINE_PROP_UINT32("x-pci-sub-device-id", VFIOPCIDevice,
127                        sub_device_id, PCI_ANY_ID),
128 };
129 
130 static void vfio_user_pci_set_socket(Object *obj, Visitor *v, const char *name,
131                                      void *opaque, Error **errp)
132 {
133     VFIOUserPCIDevice *udev = VFIO_USER_PCI(obj);
134     bool success;
135 
136     qapi_free_SocketAddress(udev->socket);
137 
138     udev->socket = NULL;
139 
140     success = visit_type_SocketAddress(v, name, &udev->socket, errp);
141 
142     if (!success) {
143         return;
144     }
145 
146     if (udev->socket->type != SOCKET_ADDRESS_TYPE_UNIX) {
147         error_setg(errp, "Unsupported socket type %s",
148                    SocketAddressType_str(udev->socket->type));
149         qapi_free_SocketAddress(udev->socket);
150         udev->socket = NULL;
151         return;
152     }
153 }
154 
155 static void vfio_user_pci_dev_class_init(ObjectClass *klass, const void *data)
156 {
157     DeviceClass *dc = DEVICE_CLASS(klass);
158     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass);
159 
160     device_class_set_props(dc, vfio_user_pci_dev_properties);
161 
162     object_class_property_add(klass, "socket", "SocketAddress", NULL,
163                               vfio_user_pci_set_socket, NULL, NULL);
164     object_class_property_set_description(klass, "socket",
165                                           "SocketAddress (UNIX sockets only)");
166 
167     dc->desc = "VFIO over socket PCI device assignment";
168     pdc->realize = vfio_user_pci_realize;
169 }
170 
171 static const TypeInfo vfio_user_pci_dev_info = {
172     .name = TYPE_VFIO_USER_PCI,
173     .parent = TYPE_VFIO_PCI_BASE,
174     .instance_size = sizeof(VFIOUserPCIDevice),
175     .class_init = vfio_user_pci_dev_class_init,
176     .instance_init = vfio_user_instance_init,
177     .instance_finalize = vfio_user_instance_finalize,
178 };
179 
180 static void register_vfio_user_dev_type(void)
181 {
182     type_register_static(&vfio_user_pci_dev_info);
183 }
184 
185  type_init(register_vfio_user_dev_type)
186