1 /* 2 * Vhost Vdpa Device PCI Bindings 3 * 4 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved. 5 * 6 * Authors: 7 * Longpeng <longpeng2@huawei.com> 8 * 9 * Largely based on the "vhost-user-blk-pci.c" and "vhost-user-blk.c" 10 * implemented by: 11 * Changpeng Liu <changpeng.liu@intel.com> 12 * 13 * This work is licensed under the terms of the GNU LGPL, version 2 or later. 14 * See the COPYING.LIB file in the top-level directory. 15 */ 16 #include "qemu/osdep.h" 17 #include <sys/ioctl.h> 18 #include <linux/vhost.h> 19 #include "hw/virtio/virtio.h" 20 #include "hw/virtio/vdpa-dev.h" 21 #include "hw/pci/pci.h" 22 #include "hw/qdev-properties.h" 23 #include "qapi/error.h" 24 #include "qemu/error-report.h" 25 #include "qemu/module.h" 26 #include "hw/virtio/virtio-pci.h" 27 #include "qom/object.h" 28 29 30 typedef struct VhostVdpaDevicePCI VhostVdpaDevicePCI; 31 32 #define TYPE_VHOST_VDPA_DEVICE_PCI "vhost-vdpa-device-pci-base" 33 DECLARE_INSTANCE_CHECKER(VhostVdpaDevicePCI, VHOST_VDPA_DEVICE_PCI, 34 TYPE_VHOST_VDPA_DEVICE_PCI) 35 36 struct VhostVdpaDevicePCI { 37 VirtIOPCIProxy parent_obj; 38 VhostVdpaDevice vdev; 39 }; 40 41 static void vhost_vdpa_device_pci_instance_init(Object *obj) 42 { 43 VhostVdpaDevicePCI *dev = VHOST_VDPA_DEVICE_PCI(obj); 44 45 virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), 46 TYPE_VHOST_VDPA_DEVICE); 47 object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), 48 "bootindex"); 49 } 50 51 static Property vhost_vdpa_device_pci_properties[] = { 52 DEFINE_PROP_END_OF_LIST(), 53 }; 54 55 static int vhost_vdpa_device_pci_post_init(VhostVdpaDevice *v, Error **errp) 56 { 57 VhostVdpaDevicePCI *dev = container_of(v, VhostVdpaDevicePCI, vdev); 58 VirtIOPCIProxy *vpci_dev = &dev->parent_obj; 59 60 vpci_dev->class_code = virtio_pci_get_class_id(v->vdev_id); 61 vpci_dev->trans_devid = virtio_pci_get_trans_devid(v->vdev_id); 62 /* one for config vector */ 63 vpci_dev->nvectors = v->num_queues + 1; 64 65 return 0; 66 } 67 68 static void 69 vhost_vdpa_device_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) 70 { 71 VhostVdpaDevicePCI *dev = VHOST_VDPA_DEVICE_PCI(vpci_dev); 72 73 dev->vdev.post_init = vhost_vdpa_device_pci_post_init; 74 qdev_realize(DEVICE(&dev->vdev), BUS(&vpci_dev->bus), errp); 75 } 76 77 static void vhost_vdpa_device_pci_class_init(ObjectClass *klass, void *data) 78 { 79 DeviceClass *dc = DEVICE_CLASS(klass); 80 VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); 81 82 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 83 device_class_set_props(dc, vhost_vdpa_device_pci_properties); 84 k->realize = vhost_vdpa_device_pci_realize; 85 } 86 87 static const VirtioPCIDeviceTypeInfo vhost_vdpa_device_pci_info = { 88 .base_name = TYPE_VHOST_VDPA_DEVICE_PCI, 89 .generic_name = "vhost-vdpa-device-pci", 90 .transitional_name = "vhost-vdpa-device-pci-transitional", 91 .non_transitional_name = "vhost-vdpa-device-pci-non-transitional", 92 .instance_size = sizeof(VhostVdpaDevicePCI), 93 .instance_init = vhost_vdpa_device_pci_instance_init, 94 .class_init = vhost_vdpa_device_pci_class_init, 95 }; 96 97 static void vhost_vdpa_device_pci_register(void) 98 { 99 virtio_pci_types_register(&vhost_vdpa_device_pci_info); 100 } 101 102 type_init(vhost_vdpa_device_pci_register); 103