qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

virtio-mem-pci.c (5480B)


      1 /*
      2  * Virtio MEM PCI device
      3  *
      4  * Copyright (C) 2020 Red Hat, Inc.
      5  *
      6  * Authors:
      7  *  David Hildenbrand <david@redhat.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2.
     10  * See the COPYING file in the top-level directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "virtio-mem-pci.h"
     15 #include "hw/mem/memory-device.h"
     16 #include "qapi/error.h"
     17 #include "qapi/qapi-events-machine.h"
     18 #include "qapi/qapi-events-misc.h"
     19 
     20 static void virtio_mem_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     21 {
     22     VirtIOMEMPCI *mem_pci = VIRTIO_MEM_PCI(vpci_dev);
     23     DeviceState *vdev = DEVICE(&mem_pci->vdev);
     24 
     25     virtio_pci_force_virtio_1(vpci_dev);
     26     qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
     27 }
     28 
     29 static void virtio_mem_pci_set_addr(MemoryDeviceState *md, uint64_t addr,
     30                                     Error **errp)
     31 {
     32     object_property_set_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, addr, errp);
     33 }
     34 
     35 static uint64_t virtio_mem_pci_get_addr(const MemoryDeviceState *md)
     36 {
     37     return object_property_get_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP,
     38                                     &error_abort);
     39 }
     40 
     41 static MemoryRegion *virtio_mem_pci_get_memory_region(MemoryDeviceState *md,
     42                                                       Error **errp)
     43 {
     44     VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);
     45     VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);
     46     VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
     47 
     48     return vmc->get_memory_region(vmem, errp);
     49 }
     50 
     51 static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState *md,
     52                                                 Error **errp)
     53 {
     54     return object_property_get_uint(OBJECT(md), VIRTIO_MEM_SIZE_PROP,
     55                                     errp);
     56 }
     57 
     58 static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,
     59                                             MemoryDeviceInfo *info)
     60 {
     61     VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);
     62     VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);
     63     VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);
     64     VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
     65     DeviceState *dev = DEVICE(md);
     66 
     67     if (dev->id) {
     68         vi->has_id = true;
     69         vi->id = g_strdup(dev->id);
     70     }
     71 
     72     /* let the real device handle everything else */
     73     vpc->fill_device_info(vmem, vi);
     74 
     75     info->u.virtio_mem.data = vi;
     76     info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;
     77 }
     78 
     79 static uint64_t virtio_mem_pci_get_min_alignment(const MemoryDeviceState *md)
     80 {
     81     return object_property_get_uint(OBJECT(md), VIRTIO_MEM_BLOCK_SIZE_PROP,
     82                                     &error_abort);
     83 }
     84 
     85 static void virtio_mem_pci_size_change_notify(Notifier *notifier, void *data)
     86 {
     87     VirtIOMEMPCI *pci_mem = container_of(notifier, VirtIOMEMPCI,
     88                                          size_change_notifier);
     89     DeviceState *dev = DEVICE(pci_mem);
     90     char *qom_path = object_get_canonical_path(OBJECT(dev));
     91     const uint64_t * const size_p = data;
     92 
     93     qapi_event_send_memory_device_size_change(!!dev->id, dev->id, *size_p,
     94                                               qom_path);
     95     g_free(qom_path);
     96 }
     97 
     98 static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
     99 {
    100     DeviceClass *dc = DEVICE_CLASS(klass);
    101     VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
    102     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
    103     MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(klass);
    104 
    105     k->realize = virtio_mem_pci_realize;
    106     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    107     pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
    108     pcidev_k->class_id = PCI_CLASS_OTHERS;
    109 
    110     mdc->get_addr = virtio_mem_pci_get_addr;
    111     mdc->set_addr = virtio_mem_pci_set_addr;
    112     mdc->get_plugged_size = virtio_mem_pci_get_plugged_size;
    113     mdc->get_memory_region = virtio_mem_pci_get_memory_region;
    114     mdc->fill_device_info = virtio_mem_pci_fill_device_info;
    115     mdc->get_min_alignment = virtio_mem_pci_get_min_alignment;
    116 }
    117 
    118 static void virtio_mem_pci_instance_init(Object *obj)
    119 {
    120     VirtIOMEMPCI *dev = VIRTIO_MEM_PCI(obj);
    121     VirtIOMEMClass *vmc;
    122     VirtIOMEM *vmem;
    123 
    124     virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
    125                                 TYPE_VIRTIO_MEM);
    126 
    127     dev->size_change_notifier.notify = virtio_mem_pci_size_change_notify;
    128     vmem = VIRTIO_MEM(&dev->vdev);
    129     vmc = VIRTIO_MEM_GET_CLASS(vmem);
    130     /*
    131      * We never remove the notifier again, as we expect both devices to
    132      * disappear at the same time.
    133      */
    134     vmc->add_size_change_notifier(vmem, &dev->size_change_notifier);
    135 
    136     object_property_add_alias(obj, VIRTIO_MEM_BLOCK_SIZE_PROP,
    137                               OBJECT(&dev->vdev), VIRTIO_MEM_BLOCK_SIZE_PROP);
    138     object_property_add_alias(obj, VIRTIO_MEM_SIZE_PROP, OBJECT(&dev->vdev),
    139                               VIRTIO_MEM_SIZE_PROP);
    140     object_property_add_alias(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP,
    141                               OBJECT(&dev->vdev),
    142                               VIRTIO_MEM_REQUESTED_SIZE_PROP);
    143 }
    144 
    145 static const VirtioPCIDeviceTypeInfo virtio_mem_pci_info = {
    146     .base_name = TYPE_VIRTIO_MEM_PCI,
    147     .generic_name = "virtio-mem-pci",
    148     .instance_size = sizeof(VirtIOMEMPCI),
    149     .instance_init = virtio_mem_pci_instance_init,
    150     .class_init = virtio_mem_pci_class_init,
    151     .interfaces = (InterfaceInfo[]) {
    152         { TYPE_MEMORY_DEVICE },
    153         { }
    154     },
    155 };
    156 
    157 static void virtio_mem_pci_register_types(void)
    158 {
    159     virtio_pci_types_register(&virtio_mem_pci_info);
    160 }
    161 type_init(virtio_mem_pci_register_types)