2 * Virtio MEM PCI device
4 * Copyright (C) 2020 Red Hat, Inc.
7 * David Hildenbrand <david@redhat.com>
9 * This work is licensed under the terms of the GNU GPL, version 2.
10 * See the COPYING file in the top-level directory.
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-misc.h"
19 static void virtio_mem_pci_realize(VirtIOPCIProxy
*vpci_dev
, Error
**errp
)
21 VirtIOMEMPCI
*mem_pci
= VIRTIO_MEM_PCI(vpci_dev
);
22 DeviceState
*vdev
= DEVICE(&mem_pci
->vdev
);
24 virtio_pci_force_virtio_1(vpci_dev
);
25 qdev_realize(vdev
, BUS(&vpci_dev
->bus
), errp
);
28 static void virtio_mem_pci_set_addr(MemoryDeviceState
*md
, uint64_t addr
,
31 object_property_set_uint(OBJECT(md
), VIRTIO_MEM_ADDR_PROP
, addr
, errp
);
34 static uint64_t virtio_mem_pci_get_addr(const MemoryDeviceState
*md
)
36 return object_property_get_uint(OBJECT(md
), VIRTIO_MEM_ADDR_PROP
,
40 static MemoryRegion
*virtio_mem_pci_get_memory_region(MemoryDeviceState
*md
,
43 VirtIOMEMPCI
*pci_mem
= VIRTIO_MEM_PCI(md
);
44 VirtIOMEM
*vmem
= VIRTIO_MEM(&pci_mem
->vdev
);
45 VirtIOMEMClass
*vmc
= VIRTIO_MEM_GET_CLASS(vmem
);
47 return vmc
->get_memory_region(vmem
, errp
);
50 static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState
*md
,
53 return object_property_get_uint(OBJECT(md
), VIRTIO_MEM_SIZE_PROP
,
57 static void virtio_mem_pci_fill_device_info(const MemoryDeviceState
*md
,
58 MemoryDeviceInfo
*info
)
60 VirtioMEMDeviceInfo
*vi
= g_new0(VirtioMEMDeviceInfo
, 1);
61 VirtIOMEMPCI
*pci_mem
= VIRTIO_MEM_PCI(md
);
62 VirtIOMEM
*vmem
= VIRTIO_MEM(&pci_mem
->vdev
);
63 VirtIOMEMClass
*vpc
= VIRTIO_MEM_GET_CLASS(vmem
);
64 DeviceState
*dev
= DEVICE(md
);
68 vi
->id
= g_strdup(dev
->id
);
71 /* let the real device handle everything else */
72 vpc
->fill_device_info(vmem
, vi
);
74 info
->u
.virtio_mem
.data
= vi
;
75 info
->type
= MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM
;
78 static void virtio_mem_pci_size_change_notify(Notifier
*notifier
, void *data
)
80 VirtIOMEMPCI
*pci_mem
= container_of(notifier
, VirtIOMEMPCI
,
81 size_change_notifier
);
82 DeviceState
*dev
= DEVICE(pci_mem
);
83 const uint64_t * const size_p
= data
;
84 const char *id
= NULL
;
87 id
= g_strdup(dev
->id
);
90 qapi_event_send_memory_device_size_change(!!id
, id
, *size_p
);
93 static void virtio_mem_pci_class_init(ObjectClass
*klass
, void *data
)
95 DeviceClass
*dc
= DEVICE_CLASS(klass
);
96 VirtioPCIClass
*k
= VIRTIO_PCI_CLASS(klass
);
97 PCIDeviceClass
*pcidev_k
= PCI_DEVICE_CLASS(klass
);
98 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(klass
);
100 k
->realize
= virtio_mem_pci_realize
;
101 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
102 pcidev_k
->vendor_id
= PCI_VENDOR_ID_REDHAT_QUMRANET
;
103 pcidev_k
->device_id
= PCI_DEVICE_ID_VIRTIO_MEM
;
104 pcidev_k
->revision
= VIRTIO_PCI_ABI_VERSION
;
105 pcidev_k
->class_id
= PCI_CLASS_OTHERS
;
107 mdc
->get_addr
= virtio_mem_pci_get_addr
;
108 mdc
->set_addr
= virtio_mem_pci_set_addr
;
109 mdc
->get_plugged_size
= virtio_mem_pci_get_plugged_size
;
110 mdc
->get_memory_region
= virtio_mem_pci_get_memory_region
;
111 mdc
->fill_device_info
= virtio_mem_pci_fill_device_info
;
114 static void virtio_mem_pci_instance_init(Object
*obj
)
116 VirtIOMEMPCI
*dev
= VIRTIO_MEM_PCI(obj
);
120 virtio_instance_init_common(obj
, &dev
->vdev
, sizeof(dev
->vdev
),
123 dev
->size_change_notifier
.notify
= virtio_mem_pci_size_change_notify
;
124 vmem
= VIRTIO_MEM(&dev
->vdev
);
125 vmc
= VIRTIO_MEM_GET_CLASS(vmem
);
127 * We never remove the notifier again, as we expect both devices to
128 * disappear at the same time.
130 vmc
->add_size_change_notifier(vmem
, &dev
->size_change_notifier
);
132 object_property_add_alias(obj
, VIRTIO_MEM_BLOCK_SIZE_PROP
,
133 OBJECT(&dev
->vdev
), VIRTIO_MEM_BLOCK_SIZE_PROP
);
134 object_property_add_alias(obj
, VIRTIO_MEM_SIZE_PROP
, OBJECT(&dev
->vdev
),
135 VIRTIO_MEM_SIZE_PROP
);
136 object_property_add_alias(obj
, VIRTIO_MEM_REQUESTED_SIZE_PROP
,
138 VIRTIO_MEM_REQUESTED_SIZE_PROP
);
141 static const VirtioPCIDeviceTypeInfo virtio_mem_pci_info
= {
142 .base_name
= TYPE_VIRTIO_MEM_PCI
,
143 .generic_name
= "virtio-mem-pci",
144 .instance_size
= sizeof(VirtIOMEMPCI
),
145 .instance_init
= virtio_mem_pci_instance_init
,
146 .class_init
= virtio_mem_pci_class_init
,
147 .interfaces
= (InterfaceInfo
[]) {
148 { TYPE_MEMORY_DEVICE
},
153 static void virtio_mem_pci_register_types(void)
155 virtio_pci_types_register(&virtio_mem_pci_info
);
157 type_init(virtio_mem_pci_register_types
)