From d1e80681712103f079bdcabcc6f68f975917e28e Mon Sep 17 00:00:00 2001
From: Jie Tang <tangjie18@huawei.com>
Date: Tue, 19 May 2020 10:55:27 +0800
Subject: [PATCH 09/16] cpu_hotplug: aarch64 use vm.hotplug_vcpu_device to
 hotplug vcpu.

aarch64 only support "device_add" qmp command, suggest using
vm.hotplug_vcpu_device instead of vm.hotplug_vcpu, this modify also need
to change vm configuration before start up.

Signed-off-by: Jie Tang <tangjie18@huawei.com>
---
 qemu/tests/cpu_hotplug.py | 68 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/qemu/tests/cpu_hotplug.py b/qemu/tests/cpu_hotplug.py
index 3b1a3e1f..5d565a99 100644
--- a/qemu/tests/cpu_hotplug.py
+++ b/qemu/tests/cpu_hotplug.py
@@ -1,12 +1,15 @@
 import os
 import logging
 import re
+import platform
 
+from avocado.utils import cpu as conn
 from virttest import error_context
 from virttest import utils_test
 from virttest import utils_misc
 from virttest import cpu
-
+from virttest import utils_qemu
+from virttest.utils_version import VersionInterval
 
 @error_context.context_aware
 def run(test, params, env):
@@ -28,13 +31,55 @@ def run(test, params, env):
     :param params: Dictionary with test parameters.
     :param env: Dictionary with the test environment.
     """
-    error_context.context("boot the vm, with '-smp X,maxcpus=Y' option,"
-                          "thus allow hotplug vcpu", logging.info)
+    # aarch64 use vm.hotplug_vcpu_device instead of vm.hotplug_vcpu
+    if platform.machine() == 'aarch64':
+        machine_type = params["machine_type"].split(':', 1)[1]
+        params["vcpu_maxcpus"] = 512
+    else:
+        machine_type = params["machine_type"]
+
+    qemu_binary = utils_misc.get_qemu_binary(params)
+    machine_info = utils_qemu.get_machines_info(qemu_binary)[machine_type]
+    machine_info = re.search(r'\(alias of (\S+)\)', machine_info)
+    current_machine = machine_info.group(1) if machine_info else machine_type
+    supported_maxcpus = (params.get_numeric("vcpu_maxcpus") or
+                         utils_qemu.get_maxcpus_hard_limit(qemu_binary,
+                                                           current_machine))
+
+    if not params.get_boolean("allow_pcpu_overcommit"):
+        supported_maxcpus = min(supported_maxcpus, cpu.online_cpus_count())
+
+    logging.info("Define the CPU topology of guest")
+    vcpu_devices = []
+    if (conn.get_cpu_vendor_name() == "amd" and
+            params.get_numeric("vcpu_threads") != 1):
+        test.cancel("AMD cpu does not support multi threads")
+    elif machine_type.startswith("pseries"):
+        host_kernel_ver = os.uname()[2].split("-")[0]
+        if params.get_numeric("vcpu_threads") == 8:
+            supported_maxcpus -= divmod(supported_maxcpus, 8)[1]
+            vcpu_devices = ["vcpu%d" % c for c in
+                            range(1, supported_maxcpus // 8)]
+        # The maximum value of vcpu_id in 'linux-3.x' is 2048, so
+        # (vcpu_id * ms->smp.threads / spapr->vsmt) <= 256, need to adjust it
+        elif (supported_maxcpus > 256 and
+              host_kernel_ver not in VersionInterval("[4, )")):
+            supported_maxcpus = 256
+    vcpu_devices = vcpu_devices or ["vcpu%d" % vcpu for vcpu in
+                                    range(1, supported_maxcpus)]
+
+    params["vcpu_maxcpus"] = str(supported_maxcpus)
+    params["vcpu_devices"] = " ".join(vcpu_devices)
+    params["start_vm"] = "yes"
+    params["smp"] = 1
+
     vm = env.get_vm(params["main_vm"])
+    vm.create(params=params)
     vm.verify_alive()
+    vm.wait_for_login()
 
-    timeout = int(params.get("login_timeout", 360))
-    session = vm.wait_for_login(timeout=timeout)
+    error_context.context("boot the vm, with '-smp X,maxcpus=Y' option,"
+                          "thus allow hotplug vcpu", logging.info)
 
     n_cpus_add = int(params.get("n_cpus_add", 1))
     maxcpus = int(params.get("maxcpus", 160))
@@ -53,9 +98,16 @@ def run(test, params, env):
     if not cpu.check_if_vm_vcpu_match(current_cpus, vm):
         test.error("CPU quantity mismatch cmd before hotplug !")
 
-    for cpuid in range(current_cpus, total_cpus):
-        error_context.context("hot-pluging vCPU %s" % cpuid, logging.info)
-        vm.hotplug_vcpu(cpu_id=cpuid, plug_command=cpu_hotplug_cmd)
+    if platform.machine() == 'aarch64':
+        vcpu_devices = []
+        vcpu_devices = vcpu_devices or ["vcpu%d" % vcpu for vcpu in
+                                        range(current_cpus, total_cpus)]
+        for vcpu_device in vcpu_devices:
+            vm.hotplug_vcpu_device(vcpu_device)
+    else:
+        for cpuid in range(current_cpus, total_cpus):
+            error_context.context("hot-pluging vCPU %s" % cpuid, logging.info)
+            vm.hotplug_vcpu(cpu_id=cpuid, plug_command=cpu_hotplug_cmd)
 
     output = vm.monitor.send_args_cmd("info cpus")
     logging.debug("Output of info CPUs:\n%s", output)
-- 
2.23.0

