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" 16*dbdf841bSDavid Hildenbrand #include "qapi/error.h" 17*dbdf841bSDavid Hildenbrand 18*dbdf841bSDavid Hildenbrand void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp) 19*dbdf841bSDavid Hildenbrand { 20*dbdf841bSDavid Hildenbrand DeviceState *dev = DEVICE(vmd); 21*dbdf841bSDavid Hildenbrand HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev); 22*dbdf841bSDavid Hildenbrand MemoryDeviceState *md = MEMORY_DEVICE(vmd); 23*dbdf841bSDavid Hildenbrand Error *local_err = NULL; 24*dbdf841bSDavid Hildenbrand 25*dbdf841bSDavid Hildenbrand if (!bus_handler && dev->hotplugged) { 26*dbdf841bSDavid Hildenbrand /* 27*dbdf841bSDavid Hildenbrand * Without a bus hotplug handler, we cannot control the plug/unplug 28*dbdf841bSDavid Hildenbrand * order. We should never reach this point when hotplugging on x86, 29*dbdf841bSDavid Hildenbrand * however, better add a safety net. 30*dbdf841bSDavid Hildenbrand */ 31*dbdf841bSDavid Hildenbrand error_setg(errp, "hotplug of virtio based memory devices not supported" 32*dbdf841bSDavid Hildenbrand " on this bus."); 33*dbdf841bSDavid Hildenbrand return; 34*dbdf841bSDavid Hildenbrand } 35*dbdf841bSDavid Hildenbrand /* 36*dbdf841bSDavid Hildenbrand * First, see if we can plug this memory device at all. If that 37*dbdf841bSDavid Hildenbrand * succeeds, branch of to the actual hotplug handler. 38*dbdf841bSDavid Hildenbrand */ 39*dbdf841bSDavid Hildenbrand memory_device_pre_plug(md, ms, NULL, &local_err); 40*dbdf841bSDavid Hildenbrand if (!local_err && bus_handler) { 41*dbdf841bSDavid Hildenbrand hotplug_handler_pre_plug(bus_handler, dev, &local_err); 42*dbdf841bSDavid Hildenbrand } 43*dbdf841bSDavid Hildenbrand error_propagate(errp, local_err); 44*dbdf841bSDavid Hildenbrand } 45*dbdf841bSDavid Hildenbrand 46*dbdf841bSDavid Hildenbrand void virtio_md_pci_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp) 47*dbdf841bSDavid Hildenbrand { 48*dbdf841bSDavid Hildenbrand DeviceState *dev = DEVICE(vmd); 49*dbdf841bSDavid Hildenbrand HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev); 50*dbdf841bSDavid Hildenbrand MemoryDeviceState *md = MEMORY_DEVICE(vmd); 51*dbdf841bSDavid Hildenbrand Error *local_err = NULL; 52*dbdf841bSDavid Hildenbrand 53*dbdf841bSDavid Hildenbrand /* 54*dbdf841bSDavid Hildenbrand * Plug the memory device first and then branch off to the actual 55*dbdf841bSDavid Hildenbrand * hotplug handler. If that one fails, we can easily undo the memory 56*dbdf841bSDavid Hildenbrand * device bits. 57*dbdf841bSDavid Hildenbrand */ 58*dbdf841bSDavid Hildenbrand memory_device_plug(md, ms); 59*dbdf841bSDavid Hildenbrand if (bus_handler) { 60*dbdf841bSDavid Hildenbrand hotplug_handler_plug(bus_handler, dev, &local_err); 61*dbdf841bSDavid Hildenbrand if (local_err) { 62*dbdf841bSDavid Hildenbrand memory_device_unplug(md, ms); 63*dbdf841bSDavid Hildenbrand } 64*dbdf841bSDavid Hildenbrand } 65*dbdf841bSDavid Hildenbrand error_propagate(errp, local_err); 66*dbdf841bSDavid Hildenbrand } 67*dbdf841bSDavid Hildenbrand 68*dbdf841bSDavid Hildenbrand void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms, 69*dbdf841bSDavid Hildenbrand Error **errp) 70*dbdf841bSDavid Hildenbrand { 71*dbdf841bSDavid Hildenbrand /* We don't support hot unplug of virtio based memory devices */ 72*dbdf841bSDavid Hildenbrand error_setg(errp, "virtio based memory devices cannot be unplugged."); 73*dbdf841bSDavid Hildenbrand } 74*dbdf841bSDavid Hildenbrand 75*dbdf841bSDavid Hildenbrand void virtio_md_pci_unplug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp) 76*dbdf841bSDavid Hildenbrand { 77*dbdf841bSDavid Hildenbrand /* We don't support hot unplug of virtio based memory devices */ 78*dbdf841bSDavid Hildenbrand } 7918129c15SDavid Hildenbrand 8018129c15SDavid Hildenbrand static const TypeInfo virtio_md_pci_info = { 8118129c15SDavid Hildenbrand .name = TYPE_VIRTIO_MD_PCI, 8218129c15SDavid Hildenbrand .parent = TYPE_VIRTIO_PCI, 8318129c15SDavid Hildenbrand .instance_size = sizeof(VirtIOMDPCI), 8418129c15SDavid Hildenbrand .class_size = sizeof(VirtIOMDPCIClass), 8518129c15SDavid Hildenbrand .abstract = true, 8618129c15SDavid Hildenbrand .interfaces = (InterfaceInfo[]) { 8718129c15SDavid Hildenbrand { TYPE_MEMORY_DEVICE }, 8818129c15SDavid Hildenbrand { } 8918129c15SDavid Hildenbrand }, 9018129c15SDavid Hildenbrand }; 9118129c15SDavid Hildenbrand 9218129c15SDavid Hildenbrand static void virtio_md_pci_register(void) 9318129c15SDavid Hildenbrand { 9418129c15SDavid Hildenbrand type_register_static(&virtio_md_pci_info); 9518129c15SDavid Hildenbrand } 9618129c15SDavid Hildenbrand type_init(virtio_md_pci_register) 97