Commit a0a49813 authored by David Hildenbrand's avatar David Hildenbrand Committed by Michael S. Tsirkin
Browse files

pc: Support for virtio-pmem-pci



Override the device hotplug handler to properly handle the memory device
part via virtio-pmem-pci callbacks from the machine hotplug handler and
forward to the actual PCI bus hotplug handler.

As PCI hotplug has not been properly factored out into hotplug handlers,
most magic is performed in the (un)realize functions. Also some PCI host
buses don't have a PCI hotplug handler at all yet, just to be sure that
we alway have a hotplug handler on x86, add a simple error check.

Unlocking virtio-pmem will unlock virtio-pmem-pci.

Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
[ Disable virtio-pmem hotunplug ]
Signed-off-by: default avatarPankaj Gupta <pagupta@redhat.com>
Message-Id: <20190619094907.10131-8-pagupta@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent cae02c34
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ config PC
    # For ACPI builder:
    select SERIAL_ISA
    select ACPI_VMGENID
    select VIRTIO_PMEM_SUPPORTED

config PC_PCI
    bool
+71 −1
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@
#include "hw/i386/intel_iommu.h"
#include "hw/net/ne2000-isa.h"
#include "standard-headers/asm-x86/bootparam.h"
#include "hw/virtio/virtio-pmem-pci.h"
#include "hw/mem/memory-device.h"

/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -2395,6 +2397,65 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
    numa_cpu_pre_plug(cpu_slot, dev, errp);
}

static void pc_virtio_pmem_pci_pre_plug(HotplugHandler *hotplug_dev,
                                        DeviceState *dev, Error **errp)
{
    HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev);
    Error *local_err = NULL;

    if (!hotplug_dev2) {
        /*
         * Without a bus hotplug handler, we cannot control the plug/unplug
         * order. This should never be the case on x86, however better add
         * a safety net.
         */
        error_setg(errp, "virtio-pmem-pci not supported on this bus.");
        return;
    }
    /*
     * First, see if we can plug this memory device at all. If that
     * succeeds, branch of to the actual hotplug handler.
     */
    memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL,
                           &local_err);
    if (!local_err) {
        hotplug_handler_pre_plug(hotplug_dev2, dev, &local_err);
    }
    error_propagate(errp, local_err);
}

static void pc_virtio_pmem_pci_plug(HotplugHandler *hotplug_dev,
                                    DeviceState *dev, Error **errp)
{
    HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev);
    Error *local_err = NULL;

    /*
     * Plug the memory device first and then branch off to the actual
     * hotplug handler. If that one fails, we can easily undo the memory
     * device bits.
     */
    memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
    hotplug_handler_plug(hotplug_dev2, dev, &local_err);
    if (local_err) {
        memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
    }
    error_propagate(errp, local_err);
}

static void pc_virtio_pmem_pci_unplug_request(HotplugHandler *hotplug_dev,
                                              DeviceState *dev, Error **errp)
{
    /* We don't support virtio pmem hot unplug */
    error_setg(errp, "virtio pmem device unplug not supported.");
}

static void pc_virtio_pmem_pci_unplug(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
{
    /* We don't support virtio pmem hot unplug */
}

static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
                                          DeviceState *dev, Error **errp)
{
@@ -2402,6 +2463,8 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
        pc_memory_pre_plug(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
        pc_cpu_pre_plug(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) {
        pc_virtio_pmem_pci_pre_plug(hotplug_dev, dev, errp);
    }
}

@@ -2412,6 +2475,8 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
        pc_memory_plug(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
        pc_cpu_plug(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) {
        pc_virtio_pmem_pci_plug(hotplug_dev, dev, errp);
    }
}

@@ -2422,6 +2487,8 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
        pc_memory_unplug_request(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
        pc_cpu_unplug_request_cb(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) {
        pc_virtio_pmem_pci_unplug_request(hotplug_dev, dev, errp);
    } else {
        error_setg(errp, "acpi: device unplug request for not supported device"
                   " type: %s", object_get_typename(OBJECT(dev)));
@@ -2435,6 +2502,8 @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
        pc_memory_unplug(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
        pc_cpu_unplug_cb(hotplug_dev, dev, errp);
    } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) {
        pc_virtio_pmem_pci_unplug(hotplug_dev, dev, errp);
    } else {
        error_setg(errp, "acpi: device unplug for not supported device"
                   " type: %s", object_get_typename(OBJECT(dev)));
@@ -2445,7 +2514,8 @@ static HotplugHandler *pc_get_hotplug_handler(MachineState *machine,
                                             DeviceState *dev)
{
    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
        object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
        object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
        object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) {
        return HOTPLUG_HANDLER(machine);
    }