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-machine.h"
18 #include "qapi/qapi-events-misc.h"
20 static void virtio_mem_pci_realize(VirtIOPCIProxy
*vpci_dev
, Error
**errp
)
22 VirtIOMEMPCI
*mem_pci
= VIRTIO_MEM_PCI(vpci_dev
);
23 DeviceState
*vdev
= DEVICE(&mem_pci
->vdev
);
25 virtio_pci_force_virtio_1(vpci_dev
);
26 qdev_realize(vdev
, BUS(&vpci_dev
->bus
), errp
);
29 static void virtio_mem_pci_set_addr(MemoryDeviceState
*md
, uint64_t addr
,
32 object_property_set_uint(OBJECT(md
), VIRTIO_MEM_ADDR_PROP
, addr
, errp
);
35 static uint64_t virtio_mem_pci_get_addr(const MemoryDeviceState
*md
)
37 return object_property_get_uint(OBJECT(md
), VIRTIO_MEM_ADDR_PROP
,
41 static MemoryRegion
*virtio_mem_pci_get_memory_region(MemoryDeviceState
*md
,
44 VirtIOMEMPCI
*pci_mem
= VIRTIO_MEM_PCI(md
);
45 VirtIOMEM
*vmem
= VIRTIO_MEM(&pci_mem
->vdev
);
46 VirtIOMEMClass
*vmc
= VIRTIO_MEM_GET_CLASS(vmem
);
48 return vmc
->get_memory_region(vmem
, errp
);
51 static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState
*md
,
54 return object_property_get_uint(OBJECT(md
), VIRTIO_MEM_SIZE_PROP
,
58 static void virtio_mem_pci_fill_device_info(const MemoryDeviceState
*md
,
59 MemoryDeviceInfo
*info
)
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
);
69 vi
->id
= g_strdup(dev
->id
);
72 /* let the real device handle everything else */
73 vpc
->fill_device_info(vmem
, vi
);
75 info
->u
.virtio_mem
.data
= vi
;
76 info
->type
= MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM
;
79 static uint64_t virtio_mem_pci_get_min_alignment(const MemoryDeviceState
*md
)
81 return object_property_get_uint(OBJECT(md
), VIRTIO_MEM_BLOCK_SIZE_PROP
,
85 static void virtio_mem_pci_size_change_notify(Notifier
*notifier
, void *data
)
87 VirtIOMEMPCI
*pci_mem
= container_of(notifier
, VirtIOMEMPCI
,
88 size_change_notifier
);
89 DeviceState
*dev
= DEVICE(pci_mem
);
90 const uint64_t * const size_p
= data
;
91 const char *id
= NULL
;
94 id
= g_strdup(dev
->id
);
97 qapi_event_send_memory_device_size_change(!!id
, id
, *size_p
);
100 static void virtio_mem_pci_class_init(ObjectClass
*klass
, void *data
)
102 DeviceClass
*dc
= DEVICE_CLASS(klass
);
103 VirtioPCIClass
*k
= VIRTIO_PCI_CLASS(klass
);
104 PCIDeviceClass
*pcidev_k
= PCI_DEVICE_CLASS(klass
);
105 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(klass
);
107 k
->realize
= virtio_mem_pci_realize
;
108 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
109 pcidev_k
->vendor_id
= PCI_VENDOR_ID_REDHAT_QUMRANET
;
110 pcidev_k
->device_id
= PCI_DEVICE_ID_VIRTIO_MEM
;
111 pcidev_k
->revision
= VIRTIO_PCI_ABI_VERSION
;
112 pcidev_k
->class_id
= PCI_CLASS_OTHERS
;
114 mdc
->get_addr
= virtio_mem_pci_get_addr
;
115 mdc
->set_addr
= virtio_mem_pci_set_addr
;
116 mdc
->get_plugged_size
= virtio_mem_pci_get_plugged_size
;
117 mdc
->get_memory_region
= virtio_mem_pci_get_memory_region
;
118 mdc
->fill_device_info
= virtio_mem_pci_fill_device_info
;
119 mdc
->get_min_alignment
= virtio_mem_pci_get_min_alignment
;
122 static void virtio_mem_pci_instance_init(Object
*obj
)
124 VirtIOMEMPCI
*dev
= VIRTIO_MEM_PCI(obj
);
128 virtio_instance_init_common(obj
, &dev
->vdev
, sizeof(dev
->vdev
),
131 dev
->size_change_notifier
.notify
= virtio_mem_pci_size_change_notify
;
132 vmem
= VIRTIO_MEM(&dev
->vdev
);
133 vmc
= VIRTIO_MEM_GET_CLASS(vmem
);
135 * We never remove the notifier again, as we expect both devices to
136 * disappear at the same time.
138 vmc
->add_size_change_notifier(vmem
, &dev
->size_change_notifier
);
140 object_property_add_alias(obj
, VIRTIO_MEM_BLOCK_SIZE_PROP
,
141 OBJECT(&dev
->vdev
), VIRTIO_MEM_BLOCK_SIZE_PROP
);
142 object_property_add_alias(obj
, VIRTIO_MEM_SIZE_PROP
, OBJECT(&dev
->vdev
),
143 VIRTIO_MEM_SIZE_PROP
);
144 object_property_add_alias(obj
, VIRTIO_MEM_REQUESTED_SIZE_PROP
,
146 VIRTIO_MEM_REQUESTED_SIZE_PROP
);
149 static const VirtioPCIDeviceTypeInfo virtio_mem_pci_info
= {
150 .base_name
= TYPE_VIRTIO_MEM_PCI
,
151 .generic_name
= "virtio-mem-pci",
152 .instance_size
= sizeof(VirtIOMEMPCI
),
153 .instance_init
= virtio_mem_pci_instance_init
,
154 .class_init
= virtio_mem_pci_class_init
,
155 .interfaces
= (InterfaceInfo
[]) {
156 { TYPE_MEMORY_DEVICE
},
161 static void virtio_mem_pci_register_types(void)
163 virtio_pci_types_register(&virtio_mem_pci_info
);
165 type_init(virtio_mem_pci_register_types
)