From d38d1d4e859450535ddc6bf0c7a59f6217b1403c Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Sun, 5 Apr 2020 16:03:15 +0800
Subject: [PATCH] arm/virt: Attach ACPI CPU hotplug support to virt

Attach cpus aml building and GED support for CPU hotplug to
arm/virt, but currently we make it diabled by not add CPU
hotplug event to GED.

Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 hw/arm/virt-acpi-build.c | 15 ++++++++++++++-
 hw/arm/virt.c            |  6 ++++++
 include/hw/arm/virt.h    |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 8b68a15d76..dbe9acb148 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -806,6 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     MachineState *ms = MACHINE(vms);
     const MemMapEntry *memmap = vms->memmap;
     const int *irqmap = vms->irqmap;
+    bool cpu_aml_built = false;

     dsdt = init_aml_allocator();
     /* Reserve space for header */
@@ -817,7 +818,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
      * the RTC ACPI device at all when using UEFI.
      */
     scope = aml_scope("\\_SB");
-    acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms);
     acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
                        (irqmap[VIRT_UART] + ARM_SPI_BASE));
     acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
@@ -845,6 +845,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
                                      AML_SYSTEM_MEMORY,
                                      memmap[VIRT_PCDIMM_ACPI].base);
         }
+
+        if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
+            CPUHotplugFeatures opts = {
+                .acpi_1_compatible = false, .has_legacy_cphp = false
+            };
+            build_cpus_aml(dsdt, ms, opts, memmap[VIRT_CPU_ACPI].base,
+                           "\\_SB", NULL, AML_SYSTEM_MEMORY);
+            cpu_aml_built = true;
+        }
+    }
+
+    if (!cpu_aml_built) {
+        acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms);
     }

     acpi_dsdt_add_power_button(scope);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8638aeedb7..d09a5773df 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -140,6 +140,7 @@ static const MemMapEntry base_memmap[] = {
     [VIRT_SMMU] =               { 0x09050000, 0x00020000 },
     [VIRT_PCDIMM_ACPI] =        { 0x09070000, MEMORY_HOTPLUG_IO_LEN },
     [VIRT_ACPI_GED] =           { 0x09080000, ACPI_GED_EVT_SEL_LEN },
+    [VIRT_CPU_ACPI] =           { 0x09090000, ACPI_CPU_HOTPLUG_REG_LEN },
     [VIRT_MMIO] =               { 0x0a000000, 0x00000200 },
     [VIRT_CPUFREQ] =              { 0x0b000000, 0x00010000 },
     /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
@@ -645,11 +646,16 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
         event |= ACPI_GED_MEM_HOTPLUG_EVT;
     }

+    /* event |= ACPI_GED_CPU_HOTPLUG_EVT;
+     * Currently CPU hotplug is not enabled.
+     */
+
     dev = qdev_create(NULL, TYPE_ACPI_GED);
     qdev_prop_set_uint32(dev, "ged-event", event);

     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, vms->memmap[VIRT_CPU_ACPI].base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));

     qdev_init_nofail(dev);
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index cbdea7ff32..6880ebe07c 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -81,6 +81,7 @@ enum {
     VIRT_SECURE_MEM,
     VIRT_PCDIMM_ACPI,
     VIRT_ACPI_GED,
+    VIRT_CPU_ACPI,
     VIRT_LOWMEMMAP_LAST,
 };

--
2.19.1
