From patchwork Mon Oct 22 06:52:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 1624221 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id EFA58E00A6 for ; Mon, 22 Oct 2012 07:07:42 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TQC3b-0000aY-9u; Mon, 22 Oct 2012 07:04:16 +0000 Received: from mail-vb0-f49.google.com ([209.85.212.49]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TQBsB-0000DD-Ah for linux-arm-kernel@lists.infradead.org; Mon, 22 Oct 2012 06:52:29 +0000 Received: by mail-vb0-f49.google.com with SMTP id fo1so2547461vbb.36 for ; Sun, 21 Oct 2012 23:52:27 -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=29T/PlfgaoB6UeafdZXzJsEIBy4dBV2sTBQYVjeDSrg=; b=EaVh+2VgybNb2MiPGDnWw4Z38hXZQIUyqnhTMelPf8wZsVt02ySymvpJC1CroAKIVB dFMxe+AkpnEEmTDPWQTchsmD7Bvt98o0iW2zQ9B8IPE0VzvrVW0FbXLwQU+ctGgIDrDM foXcq+I/IVL/B0nuTQUebnXoA5BS0kcglirGUBD5ahASHRu1v5vCssS6vRQsITFC5Tfd 9NpWEeAVybf6Cfoyl5Aj+d7gZYtBC3TPOHp+D9V6vUdKwRwrUHLJ2HOxU+hZRQbzEOQF fBtAyzt9pOE6X6M/naE91AcceXC/OITCNhOiDRYYt2VDaGe3A8GCkH1zHFDco+nFXflb IakQ== Received: by 10.58.64.196 with SMTP id q4mr14369401ves.3.1350888747038; Sun, 21 Oct 2012 23:52:27 -0700 (PDT) Received: from [127.0.1.1] (pool-72-80-83-148.nycmny.fios.verizon.net. [72.80.83.148]) by mx.google.com with ESMTPS id qj8sm8986098veb.2.2012.10.21.23.52.26 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 21 Oct 2012 23:52:26 -0700 (PDT) Subject: [PATCH v3 12/13] ARM: KVM: vgic: reduce the number of vcpu kick To: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu From: Christoffer Dall Date: Mon, 22 Oct 2012 02:52:36 -0400 Message-ID: <20121022065236.18672.65199.stgit@ubuntu> In-Reply-To: <20121022065104.18672.52989.stgit@ubuntu> References: <20121022065104.18672.52989.stgit@ubuntu> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnGEdbG3lgxgeAuZarhcSwJczSf21VNzYkFE1f3hPil0Xj/PchN+rnYkcLZSNpUiUq3yrMU X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.49 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Marc Zyngier X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Marc Zyngier If we have level interrupts already programmed to fire on a vcpu, there is no reason to kick it after injecting a new interrupt, as we're guaranteed that we'll exit when the level interrupt will be EOId (VGIC_LR_EOI is set). The exit will force a reload of the VGIC, injecting the new interrupts. Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/include/asm/kvm_vgic.h | 10 ++++++++++ arch/arm/kvm/arm.c | 10 +++++++++- arch/arm/kvm/vgic.c | 10 ++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h index 1287f75..447ec7a 100644 --- a/arch/arm/include/asm/kvm_vgic.h +++ b/arch/arm/include/asm/kvm_vgic.h @@ -215,6 +215,9 @@ struct vgic_cpu { u32 vgic_elrsr[2]; /* Saved only */ u32 vgic_apr; u32 vgic_lr[64]; /* A15 has only 4... */ + + /* Number of level-triggered interrupt in progress */ + atomic_t irq_active_count; #endif }; @@ -254,6 +257,8 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, #define irqchip_in_kernel(k) (!!((k)->arch.vgic.vctrl_base)) #define vgic_initialized(k) ((k)->arch.vgic.ready) +#define vgic_active_irq(v) (atomic_read(&(v)->arch.vgic_cpu.irq_active_count) == 0) + #else static inline int kvm_vgic_hyp_init(void) { @@ -305,6 +310,11 @@ static inline bool kvm_vgic_initialized(struct kvm *kvm) { return true; } + +static inline int vgic_active_irq(struct kvm_vcpu *vcpu) +{ + return 0; +} #endif #endif diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index d367831..cab9cb7 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -94,7 +94,15 @@ int kvm_arch_hardware_enable(void *garbage) int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) { - return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; + if (kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE) { + if (vgic_active_irq(vcpu) && + cmpxchg(&vcpu->mode, EXITING_GUEST_MODE, IN_GUEST_MODE) == EXITING_GUEST_MODE) + return 0; + + return 1; + } + + return 0; } void kvm_arch_hardware_disable(void *garbage) diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index 415ddb8..146de1d 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -705,8 +705,10 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) kvm_debug("LR%d piggyback for IRQ%d %x\n", lr, irq, vgic_cpu->vgic_lr[lr]); BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); vgic_cpu->vgic_lr[lr] |= VGIC_LR_PENDING_BIT; - if (is_level) + if (is_level) { vgic_cpu->vgic_lr[lr] |= VGIC_LR_EOI; + atomic_inc(&vgic_cpu->irq_active_count); + } return true; } @@ -718,8 +720,10 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id); vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq); - if (is_level) + if (is_level) { vgic_cpu->vgic_lr[lr] |= VGIC_LR_EOI; + atomic_inc(&vgic_cpu->irq_active_count); + } vgic_cpu->vgic_irq_lr_map[irq] = lr; clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); @@ -1011,6 +1015,8 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data) vgic_bitmap_set_irq_val(&dist->irq_active, vcpu->vcpu_id, irq, 0); + atomic_dec(&vgic_cpu->irq_active_count); + smp_mb(); vgic_cpu->vgic_lr[lr] &= ~VGIC_LR_EOI; writel_relaxed(vgic_cpu->vgic_lr[lr], dist->vctrl_base + GICH_LR0 + (lr << 2));