From e3a1af72fca5bbcc840fba44d512bbe69ec55ca9 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Tue, 12 May 2020 15:05:06 +0800
Subject: [PATCH] arm/virt: Support CPU cold plug

This adds CPU cold plug support to arm virt machine board.
CPU cold plug means adding CPU by using "-device xx-arm-cpu"
when we bring up Qemu.

Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
---
 hw/arm/virt.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 112a6ae7cb..4c7279392f 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2093,25 +2093,12 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
     int smp_cores = ms->smp.cores;
     int smp_threads = ms->smp.threads;
 
-    /* Some hotplug capability checks */
-
     if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
         error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
                    ms->cpu_type);
         return;
     }
 
-    if (dev->hotplugged && !vms->acpi_dev) {
-        error_setg(errp, "CPU hotplug is disabled: missing acpi device.");
-        return;
-    }
-
-    if (dev->hotplugged && !vms->cpu_hotplug_enabled) {
-        error_setg(errp, "CPU hotplug is disabled: "
-                         "should use AArch64 CPU and GICv3.");
-        return;
-    }
-
     /* if cpu idx is not set, set it based on socket/core/thread properties */
     if (cs->cpu_index == UNASSIGNED_CPU_INDEX) {
         int max_socket = ms->smp.max_cpus / smp_threads / smp_cores;
@@ -2137,6 +2124,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
         cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo);
     }
 
+    /* Some hotplug capability checks */
+    if (cs->cpu_index >= ms->smp.cpus) {
+        if (!vms->acpi_dev) {
+            error_setg(errp, "CPU cold/hot plug is disabled: "
+                             "missing acpi device.");
+            return;
+        }
+        if (!vms->cpu_hotplug_enabled) {
+            error_setg(errp, "CPU cold/hot plug is disabled: "
+                             "should use AArch64 CPU and GICv3.");
+            return;
+        }
+    }
+
     /* if 'address' properties socket-id/core-id/thread-id are not set, set them
      * so that machine_query_hotpluggable_cpus would show correct values
      */
@@ -2237,7 +2238,8 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
     ARMGICv3CommonClass *agcc;
     Error *local_err = NULL;
 
-    if (dev->hotplugged) {
+    /* For CPU that is cold/hot plugged */
+    if (ncpu >= ms->smp.cpus) {
         /* Realize GIC related parts of CPU */
         assert(vms->gic_version == 3);
         gicv3 = ARM_GICV3_COMMON(vms->gic);
@@ -2250,10 +2252,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
         cpu_hotplug_register_reset(ncpu);
         cpu_hotplug_reset_manually(ncpu);
         cpu_synchronize_post_reset(cs);
+    }
 
-        if (kvm_enabled()) {
-            resume_all_vcpus();
-        }
+    if (dev->hotplugged && kvm_enabled()) {
+        resume_all_vcpus();
     }
 
     if (vms->acpi_dev) {
-- 
2.19.1

