From: Bharata B Rao <bharata@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: Zhu Guihua <zhugh.fnst@cn.fujitsu.com>,
aik@ozlabs.ru, Bharata B Rao <bharata@linux.vnet.ibm.com>,
mdroth@linux.vnet.ibm.com, agraf@suse.de,
Chen Fan <chen.fan.fnst@cn.fujitsu.com>,
qemu-ppc@nongnu.org, tyreld@linux.vnet.ibm.com,
nfont@linux.vnet.ibm.com, Gu Zheng <guz.fnst@cn.fujitsu.com>,
imammedo@redhat.com, afaerber@suse.de,
david@gibson.dropbear.id.au
Subject: [Qemu-devel] [RFC PATCH v3 17/24] cpus: Reclaim vCPU objects
Date: Fri, 24 Apr 2015 12:17:39 +0530 [thread overview]
Message-ID: <1429858066-12088-18-git-send-email-bharata@linux.vnet.ibm.com> (raw)
In-Reply-To: <1429858066-12088-1-git-send-email-bharata@linux.vnet.ibm.com>
From: Gu Zheng <guz.fnst@cn.fujitsu.com>
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
This patch also adds a QOM API object_has_no_children(Object *obj)
that checks whether a given object has any child objects. This API
is needed to release CPU core and socket objects when a vCPU is destroyed.
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>
[Added core and socket removal bits]
---
cpus.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/qom/cpu.h | 11 +++++++++
include/sysemu/kvm.h | 1 +
kvm-all.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
kvm-stub.c | 5 ++++
5 files changed, 140 insertions(+), 1 deletion(-)
diff --git a/cpus.c b/cpus.c
index 0fac143..325f8a6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -858,6 +858,47 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
qemu_cpu_kick(cpu);
}
+static void qemu_destroy_cpu_core(Object *core)
+{
+ Object *socket = core->parent;
+
+ object_unparent(core);
+ if (socket && object_has_no_children(socket)) {
+ object_unparent(socket);
+ }
+}
+
+static void qemu_kvm_destroy_vcpu(CPUState *cpu)
+{
+ Object *thread = OBJECT(cpu);
+ Object *core = thread->parent;
+
+ CPU_REMOVE(cpu);
+
+ if (kvm_destroy_vcpu(cpu) < 0) {
+ error_report("kvm_destroy_vcpu failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ object_unparent(thread);
+ if (core && object_has_no_children(core)) {
+ qemu_destroy_cpu_core(core);
+ }
+}
+
+static void qemu_tcg_destroy_vcpu(CPUState *cpu)
+{
+ Object *thread = OBJECT(cpu);
+ Object *core = thread->parent;
+
+ CPU_REMOVE(cpu);
+ object_unparent(OBJECT(cpu));
+
+ if (core && object_has_no_children(core)) {
+ qemu_destroy_cpu_core(core);
+ }
+}
+
static void flush_queued_work(CPUState *cpu)
{
struct qemu_work_item *wi;
@@ -950,6 +991,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;
@@ -1003,6 +1049,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);
@@ -1039,6 +1086,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;
@@ -1196,6 +1253,13 @@ void resume_all_vcpus(void)
}
}
+void cpu_remove(CPUState *cpu)
+{
+ cpu->stop = true;
+ cpu->exit = true;
+ qemu_cpu_kick(cpu);
+}
+
/* For temporary buffers for forming a name */
#define VCPU_THREAD_NAME_SIZE 16
@@ -1390,6 +1454,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/qom/cpu.h b/include/qom/cpu.h
index 5241cf4..1bfc3d4 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -206,6 +206,7 @@ struct kvm_run;
* @halted: Nonzero if the CPU is in suspended state.
* @stop: Indicates a pending stop request.
* @stopped: Indicates the CPU has been artificially stopped.
+ * @exit: Indicates the CPU has exited due to an unplug operation.
* @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
* CPU and return to its top level loop.
* @singlestep_enabled: Flags for single-stepping.
@@ -249,6 +250,7 @@ struct CPUState {
bool created;
bool stop;
bool stopped;
+ bool exit;
volatile sig_atomic_t exit_request;
uint32_t interrupt_request;
int singlestep_enabled;
@@ -306,6 +308,7 @@ struct CPUState {
QTAILQ_HEAD(CPUTailQ, CPUState);
extern struct CPUTailQ cpus;
#define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
+#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node)
#define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
#define CPU_FOREACH_SAFE(cpu, next_cpu) \
QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
@@ -610,6 +613,14 @@ void cpu_exit(CPUState *cpu);
*/
void cpu_resume(CPUState *cpu);
+ /**
+ * cpu_remove:
+ * @cpu: The CPU to remove.
+ *
+ * Requests the CPU to be removed.
+ */
+void cpu_remove(CPUState *cpu);
+
/**
* qemu_init_vcpu:
* @cpu: The vCPU to initialize.
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 05a79c2..46e7853 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) {
diff --git a/kvm-stub.c b/kvm-stub.c
index 7ba90c5..79ac626 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -30,6 +30,11 @@ bool kvm_gsi_direct_mapping;
bool kvm_allowed;
bool kvm_readonly_mem_allowed;
+int kvm_destroy_vcpu(CPUState *cpu)
+{
+ return -ENOSYS;
+}
+
int kvm_init_vcpu(CPUState *cpu)
{
return -ENOSYS;
--
2.1.0
next prev parent reply other threads:[~2015-04-24 6:53 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-24 6:47 [Qemu-devel] [RFC PATCH v3 00/24] CPU and Memory hotplug for PowerPC sPAPR guests Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 01/24] spapr: enable PHB/CPU/LMB hotplug for pseries-2.3 Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 02/24] spapr: Add DRC dt entries for CPUs Bharata B Rao
2015-05-04 11:46 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 03/24] spapr: Consider max_cpus during xics initialization Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 04/24] spapr: Support ibm, lrdr-capacity device tree property Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 05/24] spapr: Reorganize CPU dt generation code Bharata B Rao
2015-04-26 11:47 ` Bharata B Rao
2015-04-27 5:36 ` Bharata B Rao
2015-05-04 12:01 ` David Gibson
2015-05-04 11:59 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 06/24] spapr: Consolidate cpu init code into a routine Bharata B Rao
2015-05-04 16:10 ` Thomas Huth
2015-05-06 4:28 ` Bharata B Rao
2015-05-06 6:32 ` Thomas Huth
2015-05-06 8:45 ` Bharata B Rao
2015-05-06 9:37 ` Thomas Huth
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 07/24] cpu: Prepare Socket container type Bharata B Rao
2015-05-05 1:47 ` David Gibson
2015-05-06 4:36 ` Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 08/24] ppc: Prepare CPU socket/core abstraction Bharata B Rao
2015-05-04 15:15 ` Thomas Huth
2015-05-06 4:40 ` Bharata B Rao
2015-05-06 6:52 ` Thomas Huth
2015-05-05 6:46 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 09/24] spapr: Add CPU hotplug handler Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 10/24] ppc: Update cpu_model in MachineState Bharata B Rao
2015-05-05 6:49 ` David Gibson
2015-05-06 4:49 ` Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 11/24] ppc: Create sockets and cores for CPUs Bharata B Rao
2015-05-05 6:52 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 12/24] spapr: CPU hotplug support Bharata B Rao
2015-05-04 15:53 ` Thomas Huth
2015-05-06 5:37 ` Bharata B Rao
2015-05-05 6:59 ` David Gibson
2015-05-06 6:14 ` Bharata B Rao
2015-05-07 1:03 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 13/24] cpus: Add Error argument to cpu_exec_init() Bharata B Rao
2015-05-05 7:01 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 14/24] cpus: Convert cpu_index into a bitmap Bharata B Rao
2015-05-05 7:10 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 15/24] ppc: Move cpu_exec_init() call to realize function Bharata B Rao
2015-05-05 7:12 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 16/24] qom: Introduce object_has_no_children() API Bharata B Rao
2015-05-05 7:13 ` David Gibson
2015-04-24 6:47 ` Bharata B Rao [this message]
2015-05-05 7:20 ` [Qemu-devel] [RFC PATCH v3 17/24] cpus: Reclaim vCPU objects David Gibson
2015-05-06 6:37 ` Bharata B Rao
2015-05-07 1:06 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 18/24] xics_kvm: Don't enable KVM_CAP_IRQ_XICS if already enabled Bharata B Rao
2015-05-05 7:22 ` David Gibson
2015-05-06 5:42 ` Bharata B Rao
2015-05-07 1:07 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 19/24] xics_kvm: Add cpu_destroy method to XICS Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 20/24] spapr: CPU hot unplug support Bharata B Rao
2015-05-05 7:28 ` David Gibson
2015-05-06 7:55 ` Bharata B Rao
2015-05-07 1:09 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 21/24] spapr: Initialize hotplug memory address space Bharata B Rao
2015-05-05 7:33 ` David Gibson
2015-05-06 7:58 ` Bharata B Rao
2015-05-05 8:48 ` Igor Mammedov
2015-05-06 8:23 ` Bharata B Rao
2015-05-07 1:12 ` David Gibson
2015-05-07 5:01 ` Bharata B Rao
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 22/24] numa: API to lookup NUMA node by address Bharata B Rao
2015-05-05 7:35 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 23/24] spapr: Support ibm, dynamic-reconfiguration-memory Bharata B Rao
2015-05-05 7:40 ` David Gibson
2015-05-06 8:27 ` Bharata B Rao
2015-05-07 1:13 ` David Gibson
2015-04-24 6:47 ` [Qemu-devel] [RFC PATCH v3 24/24] spapr: Memory hotplug support Bharata B Rao
2015-05-05 7:45 ` David Gibson
2015-05-06 8:30 ` Bharata B Rao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1429858066-12088-18-git-send-email-bharata@linux.vnet.ibm.com \
--to=bharata@linux.vnet.ibm.com \
--cc=afaerber@suse.de \
--cc=agraf@suse.de \
--cc=aik@ozlabs.ru \
--cc=chen.fan.fnst@cn.fujitsu.com \
--cc=david@gibson.dropbear.id.au \
--cc=guz.fnst@cn.fujitsu.com \
--cc=imammedo@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=nfont@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=tyreld@linux.vnet.ibm.com \
--cc=zhugh.fnst@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).