[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 11/11] cpus: reclaim allocated vCPU objects
From: |
Zhu Guihua |
Subject: |
[Qemu-devel] [PATCH v2 11/11] cpus: reclaim allocated vCPU objects |
Date: |
Wed, 14 Jan 2015 15:45:04 +0800 |
From: Gu Zheng <address@hidden>
After ACPI get a signal to eject a vCPU, the vCPU must be
removed from CPU list,before the vCPU really removed, then
release the all related 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/address@hidden/msg102839.html
Signed-off-by: Chen Fan <address@hidden>
Signed-off-by: Gu Zheng <address@hidden>
Signed-off-by: Zhu Guihua <address@hidden>
---
cpus.c | 37 ++++++++++++++++++++++++++++++++++
include/sysemu/kvm.h | 1 +
kvm-all.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/cpus.c b/cpus.c
index 1c25054..b5b0c91 100644
--- a/cpus.c
+++ b/cpus.c
@@ -871,6 +871,24 @@ 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)
+{
+ CPU_REMOVE(cpu);
+
+ if (kvm_destroy_vcpu(cpu) < 0) {
+ error_report("kvm_destroy_vcpu failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ object_unparent(OBJECT(cpu));
+}
+
+static void qemu_tcg_destroy_vcpu(CPUState *cpu)
+{
+ CPU_REMOVE(cpu);
+ object_unparent(OBJECT(cpu));
+}
+
static void flush_queued_work(CPUState *cpu)
{
struct qemu_work_item *wi;
@@ -963,6 +981,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
}
}
qemu_kvm_wait_io_event(cpu);
+ if (cpu->exit && !cpu_can_run(cpu)) {
+ qemu_kvm_destroy_vcpu(cpu);
+ qemu_mutex_unlock(&qemu_global_mutex);
+ return NULL;
+ }
}
return NULL;
@@ -1016,6 +1039,7 @@ static void tcg_exec_all(void);
static void *qemu_tcg_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
+ CPUState *remove_cpu = NULL;
qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread);
@@ -1049,6 +1073,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
}
}
qemu_tcg_wait_io_event();
+ CPU_FOREACH(cpu) {
+ if (cpu->exit && !cpu_can_run(cpu)) {
+ remove_cpu = cpu;
+ break;
+ }
+ }
+ if (remove_cpu) {
+ qemu_tcg_destroy_vcpu(remove_cpu);
+ remove_cpu = NULL;
+ }
}
return NULL;
@@ -1406,6 +1440,9 @@ static void tcg_exec_all(void)
break;
}
} else if (cpu->stop || cpu->stopped) {
+ if (cpu->exit) {
+ next_cpu = CPU_NEXT(cpu);
+ }
break;
}
}
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 30cb84d..560caef 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -188,6 +188,7 @@ int kvm_has_intx_set_mask(void);
int kvm_init_vcpu(CPUState *cpu);
int kvm_cpu_exec(CPUState *cpu);
+int kvm_destroy_vcpu(CPUState *cpu);
#ifdef NEED_CPU_H
diff --git a/kvm-all.c b/kvm-all.c
index 2f21a4e..6ea3d70 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -71,6 +71,12 @@ typedef struct KVMSlot
typedef struct kvm_dirty_log KVMDirtyLog;
+struct KVMParkedVcpu {
+ unsigned long vcpu_id;
+ int kvm_fd;
+ QLIST_ENTRY(KVMParkedVcpu) node;
+};
+
struct KVMState
{
AccelState parent_obj;
@@ -107,6 +113,7 @@ struct KVMState
QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE];
bool direct_msi;
#endif
+ QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
};
#define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm")
@@ -247,6 +254,53 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot
*slot)
return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
}
+int kvm_destroy_vcpu(CPUState *cpu)
+{
+ KVMState *s = kvm_state;
+ long mmap_size;
+ struct KVMParkedVcpu *vcpu = NULL;
+ int ret = 0;
+
+ DPRINTF("kvm_destroy_vcpu\n");
+
+ mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
+ if (mmap_size < 0) {
+ ret = mmap_size;
+ DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
+ goto err;
+ }
+
+ ret = munmap(cpu->kvm_run, mmap_size);
+ if (ret < 0) {
+ goto err;
+ }
+
+ vcpu = g_malloc0(sizeof(*vcpu));
+ vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
+ vcpu->kvm_fd = cpu->kvm_fd;
+ QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
+err:
+ return ret;
+}
+
+static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
+{
+ struct KVMParkedVcpu *cpu;
+
+ QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
+ if (cpu->vcpu_id == vcpu_id) {
+ int kvm_fd;
+
+ QLIST_REMOVE(cpu, node);
+ kvm_fd = cpu->kvm_fd;
+ g_free(cpu);
+ return kvm_fd;
+ }
+ }
+
+ return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
+}
+
int kvm_init_vcpu(CPUState *cpu)
{
KVMState *s = kvm_state;
@@ -255,7 +309,7 @@ int kvm_init_vcpu(CPUState *cpu)
DPRINTF("kvm_init_vcpu\n");
- ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)kvm_arch_vcpu_id(cpu));
+ ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu));
if (ret < 0) {
DPRINTF("kvm_create_vcpu failed\n");
goto err;
@@ -1448,6 +1502,7 @@ static int kvm_init(MachineState *ms)
#ifdef KVM_CAP_SET_GUEST_DEBUG
QTAILQ_INIT(&s->kvm_sw_breakpoints);
#endif
+ QLIST_INIT(&s->kvm_parked_vcpus);
s->vmfd = -1;
s->fd = qemu_open("/dev/kvm", O_RDWR);
if (s->fd == -1) {
--
1.9.3
- [Qemu-devel] [PATCH v2 02/11] acpi/cpu: add cpu hot unplug request callback function, (continued)
- [Qemu-devel] [PATCH v2 02/11] acpi/cpu: add cpu hot unplug request callback function, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 01/11] x86: add x86_cpu_unrealizefn() for cpu apic remove, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 03/11] acpi/piix4: add cpu hot unplug request callback support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 04/11] acpi/ich9: add cpu hot unplug request callback support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 05/11] pc: add cpu hot unplug request callback support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 06/11] acpi/cpu: add cpu hot unplug callback function, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 07/11] acpi/piix4: add cpu hot unplug callback support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 08/11] acpi/ich9: add cpu hot unplug support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 09/11] pc: add cpu hot unplug callback support, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 10/11] cpu hotplug: implement function cpu_status_write() for vcpu ejection, Zhu Guihua, 2015/01/14
- [Qemu-devel] [PATCH v2 11/11] cpus: reclaim allocated vCPU objects,
Zhu Guihua <=
- Message not available
- Re: [Qemu-devel] [PATCH v2 00/11] cpu: add i386 cpu hot remove support, Alexandre DERUMIER, 2015/01/23
- Re: [Qemu-devel] [PATCH v2 00/11] cpu: add i386 cpu hot remove support, Zhu Guihua, 2015/01/25
- Message not available
- Re: [Qemu-devel] [PATCH v2 00/11] cpu: add i386 cpu hot remove support, Alexandre DERUMIER, 2015/01/26
- Re: [Qemu-devel] [PATCH v2 00/11] cpu: add i386 cpu hot remove support, Zhu Guihua, 2015/01/26
- Re: [Qemu-devel] [PATCH v2 00/11] cpu: add i386 cpu hot remove support, Bharata B Rao, 2015/01/27