From patchwork Fri Oct 19 09:36:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Thierry X-Patchwork-Id: 10648921 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F06261750 for ; Fri, 19 Oct 2018 09:36:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0A1928A4A for ; Fri, 19 Oct 2018 09:36:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D4F6728A97; Fri, 19 Oct 2018 09:36:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7546128A4A for ; Fri, 19 Oct 2018 09:36:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727017AbeJSRmF (ORCPT ); Fri, 19 Oct 2018 13:42:05 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:49584 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727011AbeJSRmF (ORCPT ); Fri, 19 Oct 2018 13:42:05 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B52D480D; Fri, 19 Oct 2018 02:36:47 -0700 (PDT) Received: from e112298-lin.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id CA1963F5D3; Fri, 19 Oct 2018 02:36:46 -0700 (PDT) From: Julien Thierry To: kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, will.deacon@arm.com, Julien Thierry Subject: [PATCH kvmtool 2/2] kvm-cpu: Pause vCPU in signal handler Date: Fri, 19 Oct 2018 10:36:31 +0100 Message-Id: <1539941791-40118-3-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1539941791-40118-1-git-send-email-julien.thierry@arm.com> References: <1539941791-40118-1-git-send-email-julien.thierry@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, the handling a pause signal only sets a state that will be checked at the begining of the CPU run loop. At the checking point the vCPU sends the notification that it is actually paused allowing the pause requester to confirm all vCPUs are paused. Receiving the pause signal during a KVM_RUN ioctl will make KVM exit to userspace. However, there is a small window between that check on cpu->paused and the execution of KVM_RUN where the signal has been received but the vCPU does not go back through the notification and starts KVM_RUN. Since there is no guarantee the vCPU will come back to userspace, the pause requester might deadlock. Perform the pause directly from the signal handler. This relies on a vCPU thread never receiving a pause signal while being pause, but such scenario would have caused a deadlock for the pause requester anyway. Signed-off-by: Julien Thierry --- kvm-cpu.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kvm-cpu.c b/kvm-cpu.c index 4107841..7dec088 100644 --- a/kvm-cpu.c +++ b/kvm-cpu.c @@ -51,7 +51,19 @@ static void kvm_cpu_signal_handler(int signum) if (current_kvm_cpu && current_kvm_cpu->is_running) current_kvm_cpu->is_running = false; } else if (signum == SIGKVMPAUSE) { + if (current_kvm_cpu->paused) + die("Pause signaled for already paused CPU\n"); + + /* pause_lock is held by kvm__pause() */ current_kvm_cpu->paused = 1; + + /* + * This is a blocking function and uses locks. It is safe + * to call it for this signal as a second pause event should + * not be send to this thread until it acquires and releases + * the pause_lock. + */ + kvm__notify_paused(); } /* For SIGKVMTASK cpu->task is already set */ @@ -148,9 +160,6 @@ int kvm_cpu__start(struct kvm_cpu *cpu) kvm_cpu__enable_singlestep(cpu); while (cpu->is_running) { - if (cpu->paused) - kvm__notify_paused(); - if (cpu->needs_nmi) { kvm_cpu__arch_nmi(cpu); cpu->needs_nmi = 0;