Add a hotplug device for machine virt. This can be used for virt
to support device hotplug. At the moment this hotplug device just
include a mmio region which shows the present status of cpus.

Signed-off-by: Shannon Zhao <zhaoshengl...@huawei.com>
---
 default-configs/arm-softmmu.mak |    2 +
 hw/acpi/Makefile.objs           |    1 +
 hw/acpi/cpu_hotplug.c           |   16 +----
 hw/acpi/ich9.c                  |   12 ++++
 hw/acpi/piix4.c                 |   12 ++++
 hw/acpi/virt-hotplug.c          |  130 +++++++++++++++++++++++++++++++++++++++
 include/hw/acpi/cpu_hotplug.h   |    6 +-
 include/hw/acpi/virt-hotplug.h  |   10 +++
 8 files changed, 172 insertions(+), 17 deletions(-)
 create mode 100644 hw/acpi/virt-hotplug.c
 create mode 100644 include/hw/acpi/virt-hotplug.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 3c89f53..bb74707 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -89,3 +89,5 @@ CONFIG_ALLWINNER_A10_PIT=y
 CONFIG_ALLWINNER_A10_PIC=y
 CONFIG_ALLWINNER_A10=y
 CONFIG_ACPI=y
+CONFIG_VIRT_HOTPLUG=y
+CONFIG_ACPI_CPU_HOTPLUG=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 511771a..4bc5a4d 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI) += acpi_interface.o
 common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
 common-obj-$(CONFIG_ACPI) += aml-build.o
+common-obj-$(CONFIG_VIRT_HOTPLUG) += virt-hotplug.o
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index b8ebfad..dbc7e94 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -36,7 +36,7 @@ static const MemoryRegionOps AcpiCpuHotplug_ops = {
     },
 };
 
-static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
+void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
                                      Error **errp)
 {
     CPUClass *k = CPU_GET_CLASS(cpu);
@@ -51,20 +51,8 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, 
CPUState *cpu,
     g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
 }
 
-void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
-                      AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
-{
-    acpi_set_cpu_present_bit(g, CPU(dev), errp);
-    if (*errp != NULL) {
-        return;
-    }
-
-    ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS;
-    acpi_update_sci(ar, irq);
-}
-
 void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
-                           AcpiCpuHotplug *gpe_cpu, uint16_t base)
+                           AcpiCpuHotplug *gpe_cpu, uint64_t base)
 {
     CPUState *cpu;
 
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 5352e19..6c4422a 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -383,6 +383,18 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs 
*pm, Error **errp)
                         NULL, pm, NULL);
 }
 
+static void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
+                      AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
+{
+    acpi_set_cpu_present_bit(g, CPU(dev), errp);
+    if (*errp != NULL) {
+        return;
+    }
+
+    ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS;
+    acpi_update_sci(ar, irq);
+}
+
 void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index d1f1179..6faca8a 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -337,6 +337,18 @@ static void piix4_pm_powerdown_req(Notifier *n, void 
*opaque)
     acpi_pm1_evt_power_down(&s->ar);
 }
 
+static void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
+                      AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
+{
+    acpi_set_cpu_present_bit(g, CPU(dev), errp);
+    if (*errp != NULL) {
+        return;
+    }
+
+    ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS;
+    acpi_update_sci(ar, irq);
+}
+
 static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
                                  DeviceState *dev, Error **errp)
 {
diff --git a/hw/acpi/virt-hotplug.c b/hw/acpi/virt-hotplug.c
new file mode 100644
index 0000000..47da078
--- /dev/null
+++ b/hw/acpi/virt-hotplug.c
@@ -0,0 +1,130 @@
+/*
+ *
+ * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD.
+ *
+ * Author: Shannon Zhao <zhaoshengl...@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/acpi/acpi.h"
+#include "sysemu/sysemu.h"
+#include "qemu/range.h"
+#include "exec/address-spaces.h"
+#include "hw/acpi/cpu_hotplug.h"
+#include "hw/hotplug.h"
+#include "hw/acpi/acpi_dev_interface.h"
+#include "hw/sysbus.h"
+#include "hw/acpi/virt-hotplug.h"
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+# define VIRT_HOTPLUG_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
+#else
+# define VIRT_HOTPLUG_DPRINTF(format, ...)     do { } while (0)
+#endif
+
+typedef struct VIRTHOTPLUGState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+    AcpiCpuHotplug gpe_cpu;
+} VIRTHOTPLUGState;
+
+#define TYPE_VIRT_HOTPLUG "VIRT_HOTPLUG"
+
+#define VIRT_HOTPLUG(obj) \
+    OBJECT_CHECK(VIRTHOTPLUGState, (obj), TYPE_VIRT_HOTPLUG)
+
+static void virt_acpi_cpu_plug_cb(AcpiCpuHotplug *g,
+                                  DeviceState *dev, Error **errp)
+{
+    acpi_set_cpu_present_bit(g, CPU(dev), errp);
+    if (*errp != NULL) {
+        return;
+    }
+
+    bool ambig;
+    Object *o = object_resolve_path_type("", "pl061", &ambig);
+    /* use gpio 2 for cpu plug event */
+    qemu_set_irq(qdev_get_gpio_in(DEVICE(o), 2), 1);
+}
+
+static void virt_device_plug_cb(HotplugHandler *hotplug_dev,
+                                 DeviceState *dev, Error **errp)
+{
+    VIRTHOTPLUGState *s = VIRT_HOTPLUG(hotplug_dev);
+
+    if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+        virt_acpi_cpu_plug_cb(&s->gpe_cpu, dev, errp);
+    } else {
+        error_setg(errp, "acpi: device plug request for not supported device"
+                   " type: %s", object_get_typename(OBJECT(dev)));
+    }
+}
+
+static int virt_hotplug_initfn(SysBusDevice *sbd)
+{
+    DeviceState *dev = DEVICE(sbd);
+    VIRTHOTPLUGState *s = VIRT_HOTPLUG(dev);
+
+    acpi_cpu_hotplug_init(get_system_memory(), OBJECT(s),
+                          &s->gpe_cpu, VIRT_CPU_HOTPLUG_MMIO_BASE);
+    return 0;
+}
+
+void virt_hotplug_init(DeviceState **virt_hotplug)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, TYPE_VIRT_HOTPLUG);
+    if (virt_hotplug) {
+        *virt_hotplug = dev;
+    }
+    qdev_init_nofail(dev);
+}
+
+static void virt_hotplug_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
+
+    k->init = virt_hotplug_initfn;
+
+    dc->desc = "VIRT_HOTPLUG";
+    dc->cannot_instantiate_with_device_add_yet = true;
+    dc->hotpluggable = false;
+    hc->plug = virt_device_plug_cb;
+}
+
+static const TypeInfo virt_hotplug_info = {
+    .name          = TYPE_VIRT_HOTPLUG,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VIRTHOTPLUGState),
+    .class_init    = virt_hotplug_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_HOTPLUG_HANDLER },
+        { TYPE_ACPI_DEVICE_IF },
+        { }
+    }
+};
+
+static void virt_hotplug_register_types(void)
+{
+    type_register_static(&virt_hotplug_info);
+}
+
+type_init(virt_hotplug_register_types)
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
index f6d358d..5cb43f4 100644
--- a/include/hw/acpi/cpu_hotplug.h
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -20,9 +20,9 @@ typedef struct AcpiCpuHotplug {
     uint8_t sts[ACPI_GPE_PROC_LEN];
 } AcpiCpuHotplug;
 
-void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
-                      AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
+void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
+                                     Error **errp);
 
 void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
-                           AcpiCpuHotplug *gpe_cpu, uint16_t base);
+                           AcpiCpuHotplug *gpe_cpu, uint64_t base);
 #endif
diff --git a/include/hw/acpi/virt-hotplug.h b/include/hw/acpi/virt-hotplug.h
new file mode 100644
index 0000000..a668d16
--- /dev/null
+++ b/include/hw/acpi/virt-hotplug.h
@@ -0,0 +1,10 @@
+#ifndef HW_ACPI_VIRT_HOTPLUG_H
+#define HW_ACPI_VIRT_HOTPLUG_H
+
+#include "qemu/typedefs.h"
+
+#define VIRT_CPU_HOTPLUG_MMIO_BASE 0x09600000
+
+void virt_hotplug_init(DeviceState **virt_hotplug);
+
+#endif
-- 
1.7.1



Reply via email to