qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v2] x86/cpu: initialize the CPU concurrently


From: Zhenyu Ye
Subject: [RFC PATCH v2] x86/cpu: initialize the CPU concurrently
Date: Mon, 21 Dec 2020 19:36:18 +0800
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.3.0

Providing a optional mechanism to wait for all VCPU threads be
created out of qemu_init_vcpu(), then we can initialize the cpu
concurrently on the x86 architecture.

This reduces the time of creating virtual machines. For example, when
the haxm is used as the accelerator, cpus_accel->create_vcpu_thread()
will cause at least 200ms for each cpu, extremely prolong the boot
time.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: eillon <yezhenyu2@huawei.com>
---
 hw/i386/x86.c         |  3 +++
 include/hw/core/cpu.h | 13 +++++++++++++
 softmmu/cpus.c        | 21 +++++++++++++++++++--
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 6329f90ef9..09afff724a 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -108,6 +108,8 @@ void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, 
Error **errp)
     if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
         goto out;
     }
+
+    CPU(cpu)->async_init = true;
     qdev_realize(DEVICE(cpu), NULL, errp);

 out:
@@ -137,6 +139,7 @@ void x86_cpus_init(X86MachineState *x86ms, int 
default_cpu_version)
     for (i = 0; i < ms->smp.cpus; i++) {
         x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal);
     }
+    qemu_wait_all_vcpu_threads_init();
 }

 void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 8e7552910d..55c2c17d93 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -467,6 +467,12 @@ struct CPUState {

     /* track IOMMUs whose translations we've cached in the TCG TLB */
     GArray *iommu_notifiers;
+
+    /*
+     * If true, qemu_init_vcpu() will not wait for the VCPU thread to be 
created
+     * before returning.
+     */
+    bool async_init;
 };

 typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
@@ -977,6 +983,13 @@ void start_exclusive(void);
  */
 void end_exclusive(void);

+/**
+ * qemu_wait_all_vcpu_threads_init:
+ *
+ * Wait for all VCPU threads to be created.
+ */
+void qemu_wait_all_vcpu_threads_init(void);
+
 /**
  * qemu_init_vcpu:
  * @cpu: The vCPU to initialize.
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 1dc20b9dc3..d76853d356 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -601,6 +601,23 @@ void cpus_register_accel(const CpusAccel *ca)
     cpus_accel = ca;
 }

+static void qemu_wait_vcpu_thread_init(CPUState *cpu)
+{
+    while (!cpu->created) {
+        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
+    }
+}
+
+void qemu_wait_all_vcpu_threads_init(void)
+{
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        printf("***** cpuid: %d\n", cpu->cpu_index);
+        qemu_wait_vcpu_thread_init(cpu);
+    }
+}
+
 void qemu_init_vcpu(CPUState *cpu)
 {
     MachineState *ms = MACHINE(qdev_get_machine());
@@ -622,8 +639,8 @@ void qemu_init_vcpu(CPUState *cpu)
     g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL);
     cpus_accel->create_vcpu_thread(cpu);

-    while (!cpu->created) {
-        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
+    if (!cpu->async_init) {
+        qemu_wait_vcpu_thread_init(cpu);
     }
 }

-- 
2.22.0.windows.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]