xref: /qemu/hw/virtio/virtio-md-pci.c (revision c29dd73f74fe6020ee0755d938885919a3719194)
1 /*
2  * Abstract virtio based memory device
3  *
4  * Copyright (C) 2023 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 "hw/virtio/virtio-md-pci.h"
15 #include "hw/mem/memory-device.h"
16 #include "qapi/error.h"
17 #include "qemu/error-report.h"
18 
19 void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
20 {
21     DeviceState *dev = DEVICE(vmd);
22     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
23     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
24     Error *local_err = NULL;
25 
26     if (!bus_handler && dev->hotplugged) {
27         /*
28          * Without a bus hotplug handler, we cannot control the plug/unplug
29          * order. We should never reach this point when hotplugging on x86,
30          * however, better add a safety net.
31          */
32         error_setg(errp, "hotplug of virtio based memory devices not supported"
33                    " on this bus.");
34         return;
35     }
36     /*
37      * First, see if we can plug this memory device at all. If that
38      * succeeds, branch of to the actual hotplug handler.
39      */
40     memory_device_pre_plug(md, ms, NULL, &local_err);
41     if (!local_err && bus_handler) {
42         hotplug_handler_pre_plug(bus_handler, dev, &local_err);
43     }
44     error_propagate(errp, local_err);
45 }
46 
47 void virtio_md_pci_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
48 {
49     DeviceState *dev = DEVICE(vmd);
50     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
51     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
52     Error *local_err = NULL;
53 
54     /*
55      * Plug the memory device first and then branch off to the actual
56      * hotplug handler. If that one fails, we can easily undo the memory
57      * device bits.
58      */
59     memory_device_plug(md, ms);
60     if (bus_handler) {
61         hotplug_handler_plug(bus_handler, dev, &local_err);
62         if (local_err) {
63             memory_device_unplug(md, ms);
64         }
65     }
66     error_propagate(errp, local_err);
67 }
68 
69 void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
70                                   Error **errp)
71 {
72     /* We don't support hot unplug of virtio based memory devices */
73     error_setg(errp, "virtio based memory devices cannot be unplugged.");
74 }
75 
76 void virtio_md_pci_unplug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
77 {
78     DeviceState *dev = DEVICE(vmd);
79     HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
80     MemoryDeviceState *md = MEMORY_DEVICE(vmd);
81     Error *local_err = NULL;
82 
83     /* Unplug the memory device while it is still realized. */
84     memory_device_unplug(md, ms);
85 
86     if (bus_handler) {
87         hotplug_handler_unplug(bus_handler, dev, &local_err);
88         if (local_err) {
89             /* Not expected to fail ... but still try to recover. */
90             memory_device_plug(md, ms);
91             error_propagate(errp, local_err);
92             return;
93         }
94     } else {
95         /* Very unexpected, but let's just try to do the right thing. */
96         warn_report("Unexpected unplug of virtio based memory device");
97         qdev_unrealize(dev);
98     }
99 }
100 
101 static const TypeInfo virtio_md_pci_info = {
102     .name = TYPE_VIRTIO_MD_PCI,
103     .parent = TYPE_VIRTIO_PCI,
104     .instance_size = sizeof(VirtIOMDPCI),
105     .class_size = sizeof(VirtIOMDPCIClass),
106     .abstract = true,
107     .interfaces = (InterfaceInfo[]) {
108         { TYPE_MEMORY_DEVICE },
109         { }
110     },
111 };
112 
113 static void virtio_md_pci_register(void)
114 {
115     type_register_static(&virtio_md_pci_info);
116 }
117 type_init(virtio_md_pci_register)
118