xref: /qemu/hw/virtio/virtio-md-pci.c (revision c29dd73f74fe6020ee0755d938885919a3719194)
118129c15SDavid Hildenbrand /*
218129c15SDavid Hildenbrand  * Abstract virtio based memory device
318129c15SDavid Hildenbrand  *
418129c15SDavid Hildenbrand  * Copyright (C) 2023 Red Hat, Inc.
518129c15SDavid Hildenbrand  *
618129c15SDavid Hildenbrand  * Authors:
718129c15SDavid Hildenbrand  *  David Hildenbrand <david@redhat.com>
818129c15SDavid Hildenbrand  *
918129c15SDavid Hildenbrand  * This work is licensed under the terms of the GNU GPL, version 2.
1018129c15SDavid Hildenbrand  * See the COPYING file in the top-level directory.
1118129c15SDavid Hildenbrand  */
1218129c15SDavid Hildenbrand 
1318129c15SDavid Hildenbrand #include "qemu/osdep.h"
1418129c15SDavid Hildenbrand #include "hw/virtio/virtio-md-pci.h"
1518129c15SDavid Hildenbrand #include "hw/mem/memory-device.h"
16dbdf841bSDavid Hildenbrand #include "qapi/error.h"
17*c29dd73fSDavid Hildenbrand #include "qemu/error-report.h"
18dbdf841bSDavid Hildenbrand 
19dbdf841bSDavid Hildenbrand void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
20dbdf841bSDavid Hildenbrand {
21dbdf841bSDavid Hildenbrand     DeviceState *dev = DEVICE(vmd);
22dbdf841bSDavid Hildenbrand     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
23dbdf841bSDavid Hildenbrand     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
24dbdf841bSDavid Hildenbrand     Error *local_err = NULL;
25dbdf841bSDavid Hildenbrand 
26dbdf841bSDavid Hildenbrand     if (!bus_handler && dev->hotplugged) {
27dbdf841bSDavid Hildenbrand         /*
28dbdf841bSDavid Hildenbrand          * Without a bus hotplug handler, we cannot control the plug/unplug
29dbdf841bSDavid Hildenbrand          * order. We should never reach this point when hotplugging on x86,
30dbdf841bSDavid Hildenbrand          * however, better add a safety net.
31dbdf841bSDavid Hildenbrand          */
32dbdf841bSDavid Hildenbrand         error_setg(errp, "hotplug of virtio based memory devices not supported"
33dbdf841bSDavid Hildenbrand                    " on this bus.");
34dbdf841bSDavid Hildenbrand         return;
35dbdf841bSDavid Hildenbrand     }
36dbdf841bSDavid Hildenbrand     /*
37dbdf841bSDavid Hildenbrand      * First, see if we can plug this memory device at all. If that
38dbdf841bSDavid Hildenbrand      * succeeds, branch of to the actual hotplug handler.
39dbdf841bSDavid Hildenbrand      */
40dbdf841bSDavid Hildenbrand     memory_device_pre_plug(md, ms, NULL, &local_err);
41dbdf841bSDavid Hildenbrand     if (!local_err && bus_handler) {
42dbdf841bSDavid Hildenbrand         hotplug_handler_pre_plug(bus_handler, dev, &local_err);
43dbdf841bSDavid Hildenbrand     }
44dbdf841bSDavid Hildenbrand     error_propagate(errp, local_err);
45dbdf841bSDavid Hildenbrand }
46dbdf841bSDavid Hildenbrand 
47dbdf841bSDavid Hildenbrand void virtio_md_pci_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
48dbdf841bSDavid Hildenbrand {
49dbdf841bSDavid Hildenbrand     DeviceState *dev = DEVICE(vmd);
50dbdf841bSDavid Hildenbrand     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
51dbdf841bSDavid Hildenbrand     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
52dbdf841bSDavid Hildenbrand     Error *local_err = NULL;
53dbdf841bSDavid Hildenbrand 
54dbdf841bSDavid Hildenbrand     /*
55dbdf841bSDavid Hildenbrand      * Plug the memory device first and then branch off to the actual
56dbdf841bSDavid Hildenbrand      * hotplug handler. If that one fails, we can easily undo the memory
57dbdf841bSDavid Hildenbrand      * device bits.
58dbdf841bSDavid Hildenbrand      */
59dbdf841bSDavid Hildenbrand     memory_device_plug(md, ms);
60dbdf841bSDavid Hildenbrand     if (bus_handler) {
61dbdf841bSDavid Hildenbrand         hotplug_handler_plug(bus_handler, dev, &local_err);
62dbdf841bSDavid Hildenbrand         if (local_err) {
63dbdf841bSDavid Hildenbrand             memory_device_unplug(md, ms);
64dbdf841bSDavid Hildenbrand         }
65dbdf841bSDavid Hildenbrand     }
66dbdf841bSDavid Hildenbrand     error_propagate(errp, local_err);
67dbdf841bSDavid Hildenbrand }
68dbdf841bSDavid Hildenbrand 
69dbdf841bSDavid Hildenbrand void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
70dbdf841bSDavid Hildenbrand                                   Error **errp)
71dbdf841bSDavid Hildenbrand {
72dbdf841bSDavid Hildenbrand     /* We don't support hot unplug of virtio based memory devices */
73dbdf841bSDavid Hildenbrand     error_setg(errp, "virtio based memory devices cannot be unplugged.");
74dbdf841bSDavid Hildenbrand }
75dbdf841bSDavid Hildenbrand 
76dbdf841bSDavid Hildenbrand void virtio_md_pci_unplug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
77dbdf841bSDavid Hildenbrand {
78*c29dd73fSDavid Hildenbrand     DeviceState *dev = DEVICE(vmd);
79*c29dd73fSDavid Hildenbrand     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
80*c29dd73fSDavid Hildenbrand     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
81*c29dd73fSDavid Hildenbrand     Error *local_err = NULL;
82*c29dd73fSDavid Hildenbrand 
83*c29dd73fSDavid Hildenbrand     /* Unplug the memory device while it is still realized. */
84*c29dd73fSDavid Hildenbrand     memory_device_unplug(md, ms);
85*c29dd73fSDavid Hildenbrand 
86*c29dd73fSDavid Hildenbrand     if (bus_handler) {
87*c29dd73fSDavid Hildenbrand         hotplug_handler_unplug(bus_handler, dev, &local_err);
88*c29dd73fSDavid Hildenbrand         if (local_err) {
89*c29dd73fSDavid Hildenbrand             /* Not expected to fail ... but still try to recover. */
90*c29dd73fSDavid Hildenbrand             memory_device_plug(md, ms);
91*c29dd73fSDavid Hildenbrand             error_propagate(errp, local_err);
92*c29dd73fSDavid Hildenbrand             return;
93*c29dd73fSDavid Hildenbrand         }
94*c29dd73fSDavid Hildenbrand     } else {
95*c29dd73fSDavid Hildenbrand         /* Very unexpected, but let's just try to do the right thing. */
96*c29dd73fSDavid Hildenbrand         warn_report("Unexpected unplug of virtio based memory device");
97*c29dd73fSDavid Hildenbrand         qdev_unrealize(dev);
98*c29dd73fSDavid Hildenbrand     }
99dbdf841bSDavid Hildenbrand }
10018129c15SDavid Hildenbrand 
10118129c15SDavid Hildenbrand static const TypeInfo virtio_md_pci_info = {
10218129c15SDavid Hildenbrand     .name = TYPE_VIRTIO_MD_PCI,
10318129c15SDavid Hildenbrand     .parent = TYPE_VIRTIO_PCI,
10418129c15SDavid Hildenbrand     .instance_size = sizeof(VirtIOMDPCI),
10518129c15SDavid Hildenbrand     .class_size = sizeof(VirtIOMDPCIClass),
10618129c15SDavid Hildenbrand     .abstract = true,
10718129c15SDavid Hildenbrand     .interfaces = (InterfaceInfo[]) {
10818129c15SDavid Hildenbrand         { TYPE_MEMORY_DEVICE },
10918129c15SDavid Hildenbrand         { }
11018129c15SDavid Hildenbrand     },
11118129c15SDavid Hildenbrand };
11218129c15SDavid Hildenbrand 
11318129c15SDavid Hildenbrand static void virtio_md_pci_register(void)
11418129c15SDavid Hildenbrand {
11518129c15SDavid Hildenbrand     type_register_static(&virtio_md_pci_info);
11618129c15SDavid Hildenbrand }
11718129c15SDavid Hildenbrand type_init(virtio_md_pci_register)
118