diff options
author | Gu Zheng <guz.fnst@cn.fujitsu.com> | 2016-05-12 09:18:13 +0530 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2016-05-30 14:03:59 +1000 |
commit | 4c055ab54fae39b6329c57bcb5334d59b920463e (patch) | |
tree | d1bb4c50138f6283bda97737937c32733f943414 /cpus.c | |
parent | 9dfeca7c6b1d3a8f36531bbbac0322a9907bcd86 (diff) |
cpu: Reclaim vCPU objects
In order to deal well with the kvm vcpus (which can not be removed without any
protection), we do not close KVM vcpu fd, just record and mark it as stopped
into a list, so that we can reuse it for the appending cpu hot-add request if
possible. It is also the approach that kvm guys suggested:
https://www.mail-archive.com/kvm@vger.kernel.org/msg102839.html
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
Signed-off-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
[- Explicit CPU_REMOVE() from qemu_kvm/tcg_destroy_vcpu()
isn't needed as it is done from cpu_exec_exit()
- Use iothread mutex instead of global mutex during
destroy
- Don't cleanup vCPU object from vCPU thread context
but leave it to the callers (device_add/device_del)]
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'cpus.c')
-rw-r--r-- | cpus.c | 39 |
1 files changed, 37 insertions, 2 deletions
@@ -972,6 +972,18 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) qemu_cpu_kick(cpu); } +static void qemu_kvm_destroy_vcpu(CPUState *cpu) +{ + if (kvm_destroy_vcpu(cpu) < 0) { + error_report("kvm_destroy_vcpu failed"); + exit(EXIT_FAILURE); + } +} + +static void qemu_tcg_destroy_vcpu(CPUState *cpu) +{ +} + static void flush_queued_work(CPUState *cpu) { struct qemu_work_item *wi; @@ -1061,7 +1073,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) cpu->created = true; qemu_cond_signal(&qemu_cpu_cond); - while (1) { + do { if (cpu_can_run(cpu)) { r = kvm_cpu_exec(cpu); if (r == EXCP_DEBUG) { @@ -1069,8 +1081,10 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) } } qemu_kvm_wait_io_event(cpu); - } + } while (!cpu->unplug || cpu_can_run(cpu)); + qemu_kvm_destroy_vcpu(cpu); + qemu_mutex_unlock_iothread(); return NULL; } @@ -1124,6 +1138,7 @@ static void tcg_exec_all(void); static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *cpu = arg; + CPUState *remove_cpu = NULL; rcu_register_thread(); @@ -1161,6 +1176,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } } qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus)); + CPU_FOREACH(cpu) { + if (cpu->unplug && !cpu_can_run(cpu)) { + remove_cpu = cpu; + break; + } + } + if (remove_cpu) { + qemu_tcg_destroy_vcpu(remove_cpu); + remove_cpu = NULL; + } } return NULL; @@ -1317,6 +1342,13 @@ void resume_all_vcpus(void) } } +void cpu_remove(CPUState *cpu) +{ + cpu->stop = true; + cpu->unplug = true; + qemu_cpu_kick(cpu); +} + /* For temporary buffers for forming a name */ #define VCPU_THREAD_NAME_SIZE 16 @@ -1533,6 +1565,9 @@ static void tcg_exec_all(void) break; } } else if (cpu->stop || cpu->stopped) { + if (cpu->unplug) { + next_cpu = CPU_NEXT(cpu); + } break; } } |