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