xref: /qemu/hw/virtio/vdpa-dev.c (revision b430a2bd2303b9940cc80ec746887f463a25fc5c)
1*b430a2bdSLongpeng /*
2*b430a2bdSLongpeng  * Vhost Vdpa Device
3*b430a2bdSLongpeng  *
4*b430a2bdSLongpeng  * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
5*b430a2bdSLongpeng  *
6*b430a2bdSLongpeng  * Authors:
7*b430a2bdSLongpeng  *   Longpeng <longpeng2@huawei.com>
8*b430a2bdSLongpeng  *
9*b430a2bdSLongpeng  * Largely based on the "vhost-user-blk-pci.c" and "vhost-user-blk.c"
10*b430a2bdSLongpeng  * implemented by:
11*b430a2bdSLongpeng  *   Changpeng Liu <changpeng.liu@intel.com>
12*b430a2bdSLongpeng  *
13*b430a2bdSLongpeng  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
14*b430a2bdSLongpeng  * See the COPYING.LIB file in the top-level directory.
15*b430a2bdSLongpeng  */
16*b430a2bdSLongpeng #include "qemu/osdep.h"
17*b430a2bdSLongpeng #include <sys/ioctl.h>
18*b430a2bdSLongpeng #include <linux/vhost.h>
19*b430a2bdSLongpeng #include "qapi/error.h"
20*b430a2bdSLongpeng #include "qemu/error-report.h"
21*b430a2bdSLongpeng #include "qemu/cutils.h"
22*b430a2bdSLongpeng #include "hw/qdev-core.h"
23*b430a2bdSLongpeng #include "hw/qdev-properties.h"
24*b430a2bdSLongpeng #include "hw/qdev-properties-system.h"
25*b430a2bdSLongpeng #include "hw/virtio/vhost.h"
26*b430a2bdSLongpeng #include "hw/virtio/virtio.h"
27*b430a2bdSLongpeng #include "hw/virtio/virtio-bus.h"
28*b430a2bdSLongpeng #include "hw/virtio/virtio-access.h"
29*b430a2bdSLongpeng #include "hw/virtio/vdpa-dev.h"
30*b430a2bdSLongpeng #include "sysemu/sysemu.h"
31*b430a2bdSLongpeng #include "sysemu/runstate.h"
32*b430a2bdSLongpeng 
33*b430a2bdSLongpeng static void
34*b430a2bdSLongpeng vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq)
35*b430a2bdSLongpeng {
36*b430a2bdSLongpeng     /* Nothing to do */
37*b430a2bdSLongpeng }
38*b430a2bdSLongpeng 
39*b430a2bdSLongpeng static uint32_t
40*b430a2bdSLongpeng vhost_vdpa_device_get_u32(int fd, unsigned long int cmd, Error **errp)
41*b430a2bdSLongpeng {
42*b430a2bdSLongpeng     uint32_t val = (uint32_t)-1;
43*b430a2bdSLongpeng 
44*b430a2bdSLongpeng     if (ioctl(fd, cmd, &val) < 0) {
45*b430a2bdSLongpeng         error_setg(errp, "vhost-vdpa-device: cmd 0x%lx failed: %s",
46*b430a2bdSLongpeng                    cmd, strerror(errno));
47*b430a2bdSLongpeng     }
48*b430a2bdSLongpeng 
49*b430a2bdSLongpeng     return val;
50*b430a2bdSLongpeng }
51*b430a2bdSLongpeng 
52*b430a2bdSLongpeng static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
53*b430a2bdSLongpeng {
54*b430a2bdSLongpeng     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
55*b430a2bdSLongpeng     VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev);
56*b430a2bdSLongpeng     uint16_t max_queue_size;
57*b430a2bdSLongpeng     struct vhost_virtqueue *vqs;
58*b430a2bdSLongpeng     int i, ret;
59*b430a2bdSLongpeng 
60*b430a2bdSLongpeng     if (!v->vhostdev) {
61*b430a2bdSLongpeng         error_setg(errp, "vhost-vdpa-device: vhostdev are missing");
62*b430a2bdSLongpeng         return;
63*b430a2bdSLongpeng     }
64*b430a2bdSLongpeng 
65*b430a2bdSLongpeng     v->vhostfd = qemu_open(v->vhostdev, O_RDWR, errp);
66*b430a2bdSLongpeng     if (*errp) {
67*b430a2bdSLongpeng         return;
68*b430a2bdSLongpeng     }
69*b430a2bdSLongpeng     v->vdpa.device_fd = v->vhostfd;
70*b430a2bdSLongpeng 
71*b430a2bdSLongpeng     v->vdev_id = vhost_vdpa_device_get_u32(v->vhostfd,
72*b430a2bdSLongpeng                                            VHOST_VDPA_GET_DEVICE_ID, errp);
73*b430a2bdSLongpeng     if (*errp) {
74*b430a2bdSLongpeng         goto out;
75*b430a2bdSLongpeng     }
76*b430a2bdSLongpeng 
77*b430a2bdSLongpeng     max_queue_size = vhost_vdpa_device_get_u32(v->vhostfd,
78*b430a2bdSLongpeng                                                VHOST_VDPA_GET_VRING_NUM, errp);
79*b430a2bdSLongpeng     if (*errp) {
80*b430a2bdSLongpeng         goto out;
81*b430a2bdSLongpeng     }
82*b430a2bdSLongpeng 
83*b430a2bdSLongpeng     if (v->queue_size > max_queue_size) {
84*b430a2bdSLongpeng         error_setg(errp, "vhost-vdpa-device: invalid queue_size: %u (max:%u)",
85*b430a2bdSLongpeng                    v->queue_size, max_queue_size);
86*b430a2bdSLongpeng         goto out;
87*b430a2bdSLongpeng     } else if (!v->queue_size) {
88*b430a2bdSLongpeng         v->queue_size = max_queue_size;
89*b430a2bdSLongpeng     }
90*b430a2bdSLongpeng 
91*b430a2bdSLongpeng     v->num_queues = vhost_vdpa_device_get_u32(v->vhostfd,
92*b430a2bdSLongpeng                                               VHOST_VDPA_GET_VQS_COUNT, errp);
93*b430a2bdSLongpeng     if (*errp) {
94*b430a2bdSLongpeng         goto out;
95*b430a2bdSLongpeng     }
96*b430a2bdSLongpeng 
97*b430a2bdSLongpeng     if (!v->num_queues || v->num_queues > VIRTIO_QUEUE_MAX) {
98*b430a2bdSLongpeng         error_setg(errp, "invalid number of virtqueues: %u (max:%u)",
99*b430a2bdSLongpeng                    v->num_queues, VIRTIO_QUEUE_MAX);
100*b430a2bdSLongpeng         goto out;
101*b430a2bdSLongpeng     }
102*b430a2bdSLongpeng 
103*b430a2bdSLongpeng     v->dev.nvqs = v->num_queues;
104*b430a2bdSLongpeng     vqs = g_new0(struct vhost_virtqueue, v->dev.nvqs);
105*b430a2bdSLongpeng     v->dev.vqs = vqs;
106*b430a2bdSLongpeng     v->dev.vq_index = 0;
107*b430a2bdSLongpeng     v->dev.vq_index_end = v->dev.nvqs;
108*b430a2bdSLongpeng     v->dev.backend_features = 0;
109*b430a2bdSLongpeng     v->started = false;
110*b430a2bdSLongpeng 
111*b430a2bdSLongpeng     ret = vhost_dev_init(&v->dev, &v->vdpa, VHOST_BACKEND_TYPE_VDPA, 0, NULL);
112*b430a2bdSLongpeng     if (ret < 0) {
113*b430a2bdSLongpeng         error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s",
114*b430a2bdSLongpeng                    strerror(-ret));
115*b430a2bdSLongpeng         goto free_vqs;
116*b430a2bdSLongpeng     }
117*b430a2bdSLongpeng 
118*b430a2bdSLongpeng     v->config_size = vhost_vdpa_device_get_u32(v->vhostfd,
119*b430a2bdSLongpeng                                                VHOST_VDPA_GET_CONFIG_SIZE,
120*b430a2bdSLongpeng                                                errp);
121*b430a2bdSLongpeng     if (*errp) {
122*b430a2bdSLongpeng         goto vhost_cleanup;
123*b430a2bdSLongpeng     }
124*b430a2bdSLongpeng 
125*b430a2bdSLongpeng     /*
126*b430a2bdSLongpeng      * Invoke .post_init() to initialize the transport-specific fields
127*b430a2bdSLongpeng      * before calling virtio_init().
128*b430a2bdSLongpeng      */
129*b430a2bdSLongpeng     if (v->post_init && v->post_init(v, errp) < 0) {
130*b430a2bdSLongpeng         goto vhost_cleanup;
131*b430a2bdSLongpeng     }
132*b430a2bdSLongpeng 
133*b430a2bdSLongpeng     v->config = g_malloc0(v->config_size);
134*b430a2bdSLongpeng 
135*b430a2bdSLongpeng     ret = vhost_dev_get_config(&v->dev, v->config, v->config_size, NULL);
136*b430a2bdSLongpeng     if (ret < 0) {
137*b430a2bdSLongpeng         error_setg(errp, "vhost-vdpa-device: get config failed");
138*b430a2bdSLongpeng         goto free_config;
139*b430a2bdSLongpeng     }
140*b430a2bdSLongpeng 
141*b430a2bdSLongpeng     virtio_init(vdev, v->vdev_id, v->config_size);
142*b430a2bdSLongpeng 
143*b430a2bdSLongpeng     v->virtqs = g_new0(VirtQueue *, v->dev.nvqs);
144*b430a2bdSLongpeng     for (i = 0; i < v->dev.nvqs; i++) {
145*b430a2bdSLongpeng         v->virtqs[i] = virtio_add_queue(vdev, v->queue_size,
146*b430a2bdSLongpeng                                         vhost_vdpa_device_dummy_handle_output);
147*b430a2bdSLongpeng     }
148*b430a2bdSLongpeng 
149*b430a2bdSLongpeng     return;
150*b430a2bdSLongpeng 
151*b430a2bdSLongpeng free_config:
152*b430a2bdSLongpeng     g_free(v->config);
153*b430a2bdSLongpeng vhost_cleanup:
154*b430a2bdSLongpeng     vhost_dev_cleanup(&v->dev);
155*b430a2bdSLongpeng free_vqs:
156*b430a2bdSLongpeng     g_free(vqs);
157*b430a2bdSLongpeng out:
158*b430a2bdSLongpeng     qemu_close(v->vhostfd);
159*b430a2bdSLongpeng     v->vhostfd = -1;
160*b430a2bdSLongpeng }
161*b430a2bdSLongpeng 
162*b430a2bdSLongpeng static void vhost_vdpa_device_unrealize(DeviceState *dev)
163*b430a2bdSLongpeng {
164*b430a2bdSLongpeng     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
165*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
166*b430a2bdSLongpeng     int i;
167*b430a2bdSLongpeng 
168*b430a2bdSLongpeng     virtio_set_status(vdev, 0);
169*b430a2bdSLongpeng 
170*b430a2bdSLongpeng     for (i = 0; i < s->num_queues; i++) {
171*b430a2bdSLongpeng         virtio_delete_queue(s->virtqs[i]);
172*b430a2bdSLongpeng     }
173*b430a2bdSLongpeng     g_free(s->virtqs);
174*b430a2bdSLongpeng     virtio_cleanup(vdev);
175*b430a2bdSLongpeng 
176*b430a2bdSLongpeng     g_free(s->config);
177*b430a2bdSLongpeng     g_free(s->dev.vqs);
178*b430a2bdSLongpeng     vhost_dev_cleanup(&s->dev);
179*b430a2bdSLongpeng     qemu_close(s->vhostfd);
180*b430a2bdSLongpeng     s->vhostfd = -1;
181*b430a2bdSLongpeng }
182*b430a2bdSLongpeng 
183*b430a2bdSLongpeng static void
184*b430a2bdSLongpeng vhost_vdpa_device_get_config(VirtIODevice *vdev, uint8_t *config)
185*b430a2bdSLongpeng {
186*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
187*b430a2bdSLongpeng 
188*b430a2bdSLongpeng     memcpy(config, s->config, s->config_size);
189*b430a2bdSLongpeng }
190*b430a2bdSLongpeng 
191*b430a2bdSLongpeng static void
192*b430a2bdSLongpeng vhost_vdpa_device_set_config(VirtIODevice *vdev, const uint8_t *config)
193*b430a2bdSLongpeng {
194*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
195*b430a2bdSLongpeng     int ret;
196*b430a2bdSLongpeng 
197*b430a2bdSLongpeng     ret = vhost_dev_set_config(&s->dev, s->config, 0, s->config_size,
198*b430a2bdSLongpeng                                VHOST_SET_CONFIG_TYPE_MASTER);
199*b430a2bdSLongpeng     if (ret) {
200*b430a2bdSLongpeng         error_report("set device config space failed");
201*b430a2bdSLongpeng         return;
202*b430a2bdSLongpeng     }
203*b430a2bdSLongpeng }
204*b430a2bdSLongpeng 
205*b430a2bdSLongpeng static uint64_t vhost_vdpa_device_get_features(VirtIODevice *vdev,
206*b430a2bdSLongpeng                                                uint64_t features,
207*b430a2bdSLongpeng                                                Error **errp)
208*b430a2bdSLongpeng {
209*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
210*b430a2bdSLongpeng     uint64_t backend_features = s->dev.features;
211*b430a2bdSLongpeng 
212*b430a2bdSLongpeng     if (!virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM)) {
213*b430a2bdSLongpeng         virtio_clear_feature(&backend_features, VIRTIO_F_IOMMU_PLATFORM);
214*b430a2bdSLongpeng     }
215*b430a2bdSLongpeng 
216*b430a2bdSLongpeng     return backend_features;
217*b430a2bdSLongpeng }
218*b430a2bdSLongpeng 
219*b430a2bdSLongpeng static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp)
220*b430a2bdSLongpeng {
221*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
222*b430a2bdSLongpeng     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
223*b430a2bdSLongpeng     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
224*b430a2bdSLongpeng     int i, ret;
225*b430a2bdSLongpeng 
226*b430a2bdSLongpeng     if (!k->set_guest_notifiers) {
227*b430a2bdSLongpeng         error_setg(errp, "binding does not support guest notifiers");
228*b430a2bdSLongpeng         return -ENOSYS;
229*b430a2bdSLongpeng     }
230*b430a2bdSLongpeng 
231*b430a2bdSLongpeng     ret = vhost_dev_enable_notifiers(&s->dev, vdev);
232*b430a2bdSLongpeng     if (ret < 0) {
233*b430a2bdSLongpeng         error_setg_errno(errp, -ret, "Error enabling host notifiers");
234*b430a2bdSLongpeng         return ret;
235*b430a2bdSLongpeng     }
236*b430a2bdSLongpeng 
237*b430a2bdSLongpeng     ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);
238*b430a2bdSLongpeng     if (ret < 0) {
239*b430a2bdSLongpeng         error_setg_errno(errp, -ret, "Error binding guest notifier");
240*b430a2bdSLongpeng         goto err_host_notifiers;
241*b430a2bdSLongpeng     }
242*b430a2bdSLongpeng 
243*b430a2bdSLongpeng     s->dev.acked_features = vdev->guest_features;
244*b430a2bdSLongpeng 
245*b430a2bdSLongpeng     ret = vhost_dev_start(&s->dev, vdev, false);
246*b430a2bdSLongpeng     if (ret < 0) {
247*b430a2bdSLongpeng         error_setg_errno(errp, -ret, "Error starting vhost");
248*b430a2bdSLongpeng         goto err_guest_notifiers;
249*b430a2bdSLongpeng     }
250*b430a2bdSLongpeng     s->started = true;
251*b430a2bdSLongpeng 
252*b430a2bdSLongpeng     /*
253*b430a2bdSLongpeng      * guest_notifier_mask/pending not used yet, so just unmask
254*b430a2bdSLongpeng      * everything here. virtio-pci will do the right thing by
255*b430a2bdSLongpeng      * enabling/disabling irqfd.
256*b430a2bdSLongpeng      */
257*b430a2bdSLongpeng     for (i = 0; i < s->dev.nvqs; i++) {
258*b430a2bdSLongpeng         vhost_virtqueue_mask(&s->dev, vdev, i, false);
259*b430a2bdSLongpeng     }
260*b430a2bdSLongpeng 
261*b430a2bdSLongpeng     return ret;
262*b430a2bdSLongpeng 
263*b430a2bdSLongpeng err_guest_notifiers:
264*b430a2bdSLongpeng     k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
265*b430a2bdSLongpeng err_host_notifiers:
266*b430a2bdSLongpeng     vhost_dev_disable_notifiers(&s->dev, vdev);
267*b430a2bdSLongpeng     return ret;
268*b430a2bdSLongpeng }
269*b430a2bdSLongpeng 
270*b430a2bdSLongpeng static void vhost_vdpa_device_stop(VirtIODevice *vdev)
271*b430a2bdSLongpeng {
272*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
273*b430a2bdSLongpeng     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
274*b430a2bdSLongpeng     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
275*b430a2bdSLongpeng     int ret;
276*b430a2bdSLongpeng 
277*b430a2bdSLongpeng     if (!s->started) {
278*b430a2bdSLongpeng         return;
279*b430a2bdSLongpeng     }
280*b430a2bdSLongpeng     s->started = false;
281*b430a2bdSLongpeng 
282*b430a2bdSLongpeng     if (!k->set_guest_notifiers) {
283*b430a2bdSLongpeng         return;
284*b430a2bdSLongpeng     }
285*b430a2bdSLongpeng 
286*b430a2bdSLongpeng     vhost_dev_stop(&s->dev, vdev, false);
287*b430a2bdSLongpeng 
288*b430a2bdSLongpeng     ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
289*b430a2bdSLongpeng     if (ret < 0) {
290*b430a2bdSLongpeng         error_report("vhost guest notifier cleanup failed: %d", ret);
291*b430a2bdSLongpeng         return;
292*b430a2bdSLongpeng     }
293*b430a2bdSLongpeng 
294*b430a2bdSLongpeng     vhost_dev_disable_notifiers(&s->dev, vdev);
295*b430a2bdSLongpeng }
296*b430a2bdSLongpeng 
297*b430a2bdSLongpeng static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status)
298*b430a2bdSLongpeng {
299*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
300*b430a2bdSLongpeng     bool should_start = virtio_device_started(vdev, status);
301*b430a2bdSLongpeng     Error *local_err = NULL;
302*b430a2bdSLongpeng     int ret;
303*b430a2bdSLongpeng 
304*b430a2bdSLongpeng     if (!vdev->vm_running) {
305*b430a2bdSLongpeng         should_start = false;
306*b430a2bdSLongpeng     }
307*b430a2bdSLongpeng 
308*b430a2bdSLongpeng     if (s->started == should_start) {
309*b430a2bdSLongpeng         return;
310*b430a2bdSLongpeng     }
311*b430a2bdSLongpeng 
312*b430a2bdSLongpeng     if (should_start) {
313*b430a2bdSLongpeng         ret = vhost_vdpa_device_start(vdev, &local_err);
314*b430a2bdSLongpeng         if (ret < 0) {
315*b430a2bdSLongpeng             error_reportf_err(local_err, "vhost-vdpa-device: start failed: ");
316*b430a2bdSLongpeng         }
317*b430a2bdSLongpeng     } else {
318*b430a2bdSLongpeng         vhost_vdpa_device_stop(vdev);
319*b430a2bdSLongpeng     }
320*b430a2bdSLongpeng }
321*b430a2bdSLongpeng 
322*b430a2bdSLongpeng static Property vhost_vdpa_device_properties[] = {
323*b430a2bdSLongpeng     DEFINE_PROP_STRING("vhostdev", VhostVdpaDevice, vhostdev),
324*b430a2bdSLongpeng     DEFINE_PROP_UINT16("queue-size", VhostVdpaDevice, queue_size, 0),
325*b430a2bdSLongpeng     DEFINE_PROP_END_OF_LIST(),
326*b430a2bdSLongpeng };
327*b430a2bdSLongpeng 
328*b430a2bdSLongpeng static const VMStateDescription vmstate_vhost_vdpa_device = {
329*b430a2bdSLongpeng     .name = "vhost-vdpa-device",
330*b430a2bdSLongpeng     .minimum_version_id = 1,
331*b430a2bdSLongpeng     .version_id = 1,
332*b430a2bdSLongpeng     .fields = (VMStateField[]) {
333*b430a2bdSLongpeng         VMSTATE_VIRTIO_DEVICE,
334*b430a2bdSLongpeng         VMSTATE_END_OF_LIST()
335*b430a2bdSLongpeng     },
336*b430a2bdSLongpeng };
337*b430a2bdSLongpeng 
338*b430a2bdSLongpeng static void vhost_vdpa_device_class_init(ObjectClass *klass, void *data)
339*b430a2bdSLongpeng {
340*b430a2bdSLongpeng     DeviceClass *dc = DEVICE_CLASS(klass);
341*b430a2bdSLongpeng     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
342*b430a2bdSLongpeng 
343*b430a2bdSLongpeng     device_class_set_props(dc, vhost_vdpa_device_properties);
344*b430a2bdSLongpeng     dc->desc = "VDPA-based generic device assignment";
345*b430a2bdSLongpeng     dc->vmsd = &vmstate_vhost_vdpa_device;
346*b430a2bdSLongpeng     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
347*b430a2bdSLongpeng     vdc->realize = vhost_vdpa_device_realize;
348*b430a2bdSLongpeng     vdc->unrealize = vhost_vdpa_device_unrealize;
349*b430a2bdSLongpeng     vdc->get_config = vhost_vdpa_device_get_config;
350*b430a2bdSLongpeng     vdc->set_config = vhost_vdpa_device_set_config;
351*b430a2bdSLongpeng     vdc->get_features = vhost_vdpa_device_get_features;
352*b430a2bdSLongpeng     vdc->set_status = vhost_vdpa_device_set_status;
353*b430a2bdSLongpeng }
354*b430a2bdSLongpeng 
355*b430a2bdSLongpeng static void vhost_vdpa_device_instance_init(Object *obj)
356*b430a2bdSLongpeng {
357*b430a2bdSLongpeng     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(obj);
358*b430a2bdSLongpeng 
359*b430a2bdSLongpeng     device_add_bootindex_property(obj, &s->bootindex, "bootindex",
360*b430a2bdSLongpeng                                   NULL, DEVICE(obj));
361*b430a2bdSLongpeng }
362*b430a2bdSLongpeng 
363*b430a2bdSLongpeng static const TypeInfo vhost_vdpa_device_info = {
364*b430a2bdSLongpeng     .name = TYPE_VHOST_VDPA_DEVICE,
365*b430a2bdSLongpeng     .parent = TYPE_VIRTIO_DEVICE,
366*b430a2bdSLongpeng     .instance_size = sizeof(VhostVdpaDevice),
367*b430a2bdSLongpeng     .class_init = vhost_vdpa_device_class_init,
368*b430a2bdSLongpeng     .instance_init = vhost_vdpa_device_instance_init,
369*b430a2bdSLongpeng };
370*b430a2bdSLongpeng 
371*b430a2bdSLongpeng static void register_vhost_vdpa_device_type(void)
372*b430a2bdSLongpeng {
373*b430a2bdSLongpeng     type_register_static(&vhost_vdpa_device_info);
374*b430a2bdSLongpeng }
375*b430a2bdSLongpeng 
376*b430a2bdSLongpeng type_init(register_vhost_vdpa_device_type);
377