From patchwork Fri Jan 8 06:55:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bharata B Rao X-Patchwork-Id: 564631 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id EA2111402A0 for ; Fri, 8 Jan 2016 17:59:18 +1100 (AEDT) Received: from localhost ([::1]:34227 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aHR13-0006zy-3D for incoming@patchwork.ozlabs.org; Fri, 08 Jan 2016 01:59:17 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52397) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aHQxW-00081j-Mn for qemu-devel@nongnu.org; Fri, 08 Jan 2016 01:55:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aHQxS-00089w-Gx for qemu-devel@nongnu.org; Fri, 08 Jan 2016 01:55:38 -0500 Received: from e28smtp07.in.ibm.com ([125.16.236.7]:35462) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aHQxR-00088C-IE for qemu-devel@nongnu.org; Fri, 08 Jan 2016 01:55:34 -0500 Received: from localhost by e28smtp07.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 8 Jan 2016 12:25:29 +0530 Received: from d28dlp03.in.ibm.com (9.184.220.128) by e28smtp07.in.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 8 Jan 2016 12:25:28 +0530 X-IBM-Helo: d28dlp03.in.ibm.com X-IBM-MailFrom: bharata@linux.vnet.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org;qemu-ppc@nongnu.org Received: from d28relay04.in.ibm.com (d28relay04.in.ibm.com [9.184.220.61]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 4FACE125801E; Fri, 8 Jan 2016 12:26:12 +0530 (IST) Received: from d28av05.in.ibm.com (d28av05.in.ibm.com [9.184.220.67]) by d28relay04.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u086tMsC50921482; Fri, 8 Jan 2016 12:25:23 +0530 Received: from d28av05.in.ibm.com (localhost [127.0.0.1]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u086tLBY023815; Fri, 8 Jan 2016 12:25:21 +0530 Received: from bharata.in.ibm.com ([9.124.35.235]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u086tKYZ023739; Fri, 8 Jan 2016 12:25:21 +0530 From: Bharata B Rao To: qemu-devel@nongnu.org Date: Fri, 8 Jan 2016 12:25:13 +0530 Message-Id: <1452236119-24452-6-git-send-email-bharata@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1452236119-24452-1-git-send-email-bharata@linux.vnet.ibm.com> References: <1452236119-24452-1-git-send-email-bharata@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16010806-0025-0000-0000-0000091FC49E X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 125.16.236.7 Cc: Zhu Guihua , ehabkost@redhat.com, aik@ozlabs.ru, Bharata B Rao , mdroth@linux.vnet.ibm.com, agraf@suse.de, Chen Fan , pbonzini@redhat.com, qemu-ppc@nongnu.org, tyreld@linux.vnet.ibm.com, nfont@linux.vnet.ibm.com, Gu Zheng , imammedo@redhat.com, afaerber@suse.de, david@gibson.dropbear.id.au Subject: [Qemu-devel] [PATCH v6 05/11] cpu: Reclaim vCPU objects X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Gu Zheng 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 Signed-off-by: Gu Zheng Signed-off-by: Zhu Guihua Signed-off-by: Bharata B Rao [- 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: David Gibson --- cpus.c | 38 +++++++++++++++++++++++++++++++++++ include/qom/cpu.h | 10 +++++++++ include/sysemu/kvm.h | 1 + kvm-all.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++- kvm-stub.c | 5 +++++ 5 files changed, 110 insertions(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index ea29584..12374af 100644 --- a/cpus.c +++ b/cpus.c @@ -953,6 +953,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.\n"); + exit(EXIT_FAILURE); + } +} + +static void qemu_tcg_destroy_vcpu(CPUState *cpu) +{ +} + static void flush_queued_work(CPUState *cpu) { struct qemu_work_item *wi; @@ -1053,6 +1065,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_iothread(); + return NULL; + } } return NULL; @@ -1108,6 +1125,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(); @@ -1145,6 +1163,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } } qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus)); + 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; @@ -1301,6 +1329,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 @@ -1508,6 +1543,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 51a1323..67e05b0 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -223,6 +223,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. * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this * CPU and return to its top level loop. @@ -274,6 +275,7 @@ struct CPUState { bool created; bool stop; bool stopped; + bool exit; bool crash_occurred; bool exit_request; uint32_t interrupt_request; @@ -696,6 +698,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 7741f91..7324fa9 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -218,6 +218,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 bd9e764..b6f64ec 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -62,6 +62,12 @@ #define KVM_MSI_HASHTAB_SIZE 256 +struct KVMParkedVcpu { + unsigned long vcpu_id; + int kvm_fd; + QLIST_ENTRY(KVMParkedVcpu) node; +}; + struct KVMState { AccelState parent_obj; @@ -95,6 +101,7 @@ struct KVMState QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE]; #endif KVMMemoryListener memory_listener; + QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus; }; KVMState *kvm_state; @@ -238,6 +245,53 @@ static int kvm_set_user_memory_region(KVMMemoryListener *kml, 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; @@ -246,7 +300,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; @@ -1509,6 +1563,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 dc97a5e..0b39456 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -32,6 +32,11 @@ bool kvm_allowed; bool kvm_readonly_mem_allowed; bool kvm_ioeventfd_any_length_allowed; +int kvm_destroy_vcpu(CPUState *cpu) +{ + return -ENOSYS; +} + int kvm_init_vcpu(CPUState *cpu) { return -ENOSYS;