From 7cfb37c50209208f853c6fbd0df6673a95e03ef9 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Fri, 10 Apr 2020 14:16:40 +0800
Subject: [PATCH] arm/virt: Add some sanity checks in cpu_pre_plug hook

For that user will try to hotplug a CPU when preconditions
are not satisfied, check these CPU hotplug preconditions in
pre_plug hook.

Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 hw/arm/virt.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 983084c459..c6a99e683a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2086,10 +2086,30 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
     VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev);
     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
+    const CPUArchId *cpu_slot = NULL;
     MemoryRegion *sysmem = get_system_memory();
     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;
@@ -2145,6 +2165,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
     object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id,
                             "mp-affinity", NULL);

+    cpu_slot = &possible_cpus->cpus[cs->cpu_index];
+    if (cpu_slot->cpu) {
+        error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists",
+                   cs->cpu_index, cpu->mp_affinity);
+        return;
+    }
+
     numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
                       &error_fatal);

--
2.19.1
