From patchwork Tue Jul 3 09:02:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 1149631 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id ABD2EDFF72 for ; Tue, 3 Jul 2012 09:02:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754656Ab2GCJCP (ORCPT ); Tue, 3 Jul 2012 05:02:15 -0400 Received: from mail-qa0-f53.google.com ([209.85.216.53]:63328 "EHLO mail-qa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754534Ab2GCJCO (ORCPT ); Tue, 3 Jul 2012 05:02:14 -0400 Received: by mail-qa0-f53.google.com with SMTP id s11so2427443qaa.19 for ; Tue, 03 Jul 2012 02:02:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=UQUqVAgL5ZbltkH2o7lda1ffZ+Ygae3LNB059xvHejA=; b=e/y29OKxpKRPl4UFvUKLrJXgm8/8evK3R6GAZE8r3uBTPRwxqJ/r1TGjDUD8WW1ccR zwVZh2Cl20J+mlJENpS3pT2pkcfSM0orMejsJYHKeTA2F0LsWEr7gpm/KKb67r510nR/ 4EvfJ7VzPUPiC9gHB4ZK0EW7hGtZuvu+munJVwsKXiBD/q819C6uhj7tah/NscpdngVf PxMfJUulpgiVwoa9q7jzOZRlm1ruyWBfvrPqz0Y+3uUJCMAFHvmPdGwselEoA9E83+6Y s72s5xwkiWcXO9W+u/49K3+Xs6uE5sgBp6AiEo/Jmu+mYIdrjhd+99If/wHPVv0ojxHn WQiQ== Received: by 10.229.135.75 with SMTP id m11mr8375029qct.66.1341306133911; Tue, 03 Jul 2012 02:02:13 -0700 (PDT) Received: from [127.0.1.1] (fireball.cs.columbia.edu. [128.59.13.10]) by mx.google.com with ESMTPS id ds8sm28632267qab.18.2012.07.03.02.02.13 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 03 Jul 2012 02:02:13 -0700 (PDT) Subject: [PATCH v9 16/16] ARM: KVM: Guest wait-for-interrupts (WFI) support To: android-virt@lists.cs.columbia.edu, kvm@vger.kernel.org From: Christoffer Dall Cc: tech@virtualopensystems.com Date: Tue, 03 Jul 2012 05:02:12 -0400 Message-ID: <20120703090212.27746.39517.stgit@ubuntu> In-Reply-To: <20120703085841.27746.82730.stgit@ubuntu> References: <20120703085841.27746.82730.stgit@ubuntu> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQl+3sQv5Jjedzl7+xbINhXdwX7To7ZtESEBo1tJfe0TEjECq/DyYJ3RRHZ9GhfDMpY75m6f Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Christoffer Dall When the guest executes a WFI instruction the operation is trapped to KVM, which emulates the instruction in software. There is no correlation between a guest executing a WFI instruction and actually putting the hardware into a low-power mode, since a KVM guest is essentially a process and the WFI instruction can be seen as 'sleep' call from this process. Therefore, we flag the VCPU to be in wait_for_interrupts mode and call the main KVM function kvm_vcpu_block() function. This function will put the thread on a wait-queue and call schedule. When an interrupt comes in through KVM_IRQ_LINE (see previous patch) we signal the VCPU thread and unflag the VCPU to no longer wait for interrupts. All calls to kvm_arch_vcpu_ioctl_run() result in a call to kvm_vcpu_block() as long as the VCPU is in wfi-mode. Signed-off-by: Christoffer Dall --- arch/arm/kvm/arm.c | 15 ++++++++++++++- arch/arm/kvm/emulate.c | 12 ++++++++++++ arch/arm/kvm/trace.h | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index b18f68f..f3b206a 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -306,9 +306,17 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, return -EINVAL; } +/** + * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled + * @v: The VCPU pointer + * + * If the guest CPU is not waiting for interrupts (or waiting and + * an interrupt is pending) then it is by definition runnable. + */ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) { - return 0; + return !!v->arch.irq_lines || + !v->arch.wait_for_interrupts; } int kvm_arch_vcpu_in_guest_mode(struct kvm_vcpu *v) @@ -538,6 +546,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) */ cond_resched(); + if (vcpu->arch.wait_for_interrupts) + kvm_vcpu_block(vcpu); + update_vttbr(vcpu->kvm); /* @@ -635,6 +646,8 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level) * trigger a world-switch round on the running physical CPU to set the * virtual IRQ/FIQ fields in the HCR appropriately. */ + if (irq_level->level) + vcpu->arch.wait_for_interrupts = 0; kvm_vcpu_kick(vcpu); return 0; diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 99432d8..564add2 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -505,9 +505,21 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) return emulate_cp15(vcpu, ¶ms); } +/** + * kvm_handle_wfi - handle a wait-for-interrupts instruction executed by a guest + * @vcpu: the vcpu pointer + * @run: the kvm_run structure pointer + * + * Simply sets the wait_for_interrupts flag on the vcpu structure, which will + * halt execution of world-switches and schedule other host processes until + * there is an incoming IRQ or FIQ to the VM. + */ int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run) { + trace_kvm_wfi(vcpu->arch.regs.pc); vcpu->stat.wfi_exits++; + if (!vcpu->arch.irq_lines) + vcpu->arch.wait_for_interrupts = 1; return 0; } diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h index 325106c..28ed1a1 100644 --- a/arch/arm/kvm/trace.h +++ b/arch/arm/kvm/trace.h @@ -90,6 +90,22 @@ TRACE_EVENT(kvm_emulate_cp15_imp, __entry->CRm, __entry->Op2) ); +TRACE_EVENT(kvm_wfi, + TP_PROTO(unsigned long vcpu_pc), + TP_ARGS(vcpu_pc), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_pc ) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + ), + + TP_printk("guest executed wfi at: 0x%08lx", __entry->vcpu_pc) +); + + #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH