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