From patchwork Tue Dec 17 05:29:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 22560 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f197.google.com (mail-vc0-f197.google.com [209.85.220.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 53155202E2 for ; Tue, 17 Dec 2013 05:30:37 +0000 (UTC) Received: by mail-vc0-f197.google.com with SMTP id id10sf10574923vcb.8 for ; Mon, 16 Dec 2013 21:30:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=nFLIIzBEoYeNJZGsD/W80Z2tKNqwaIquORlR1+1XVLg=; b=GRHlRzdjDEH7coJRaDOiGbqOtkQCvx90Kbh3mBxINiNVCIsPeg0QtVYaVqRuST7K2z Hol1eYioiNjm5uy1/JYMq5aE3vf3ndWPClBz7ylS1xYQZyai6S1SUY75WXsxLeINucFL +LYqTa5qCdROKO8HaMTWxX8Wnfe35AWGYoXhY0Swn/gVyEoysaRh2G+gUGilWV3FDv9+ AIiNj6/4b+SSDA3LJZD9stbB/3AXfKpWud47RAp9wNIWcGk4+tIpD7chpJcyBond7U0W OK2MQ9vKxYffMmmyjj4q8CCDMsRm/KXEBGhKir66k+N6/+XIR2M58o0OiPYmShbk/pgN vEvw== X-Gm-Message-State: ALoCoQnZJrP38oEGexTKQ7+n+Q7idVwGx6LrJhGIVbD4cInLgGur7OvR3jC+yaXRanSGXSqZmGCv X-Received: by 10.236.204.42 with SMTP id g30mr24956yho.54.1387258237090; Mon, 16 Dec 2013 21:30:37 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.128.41 with SMTP id nl9ls2410474qeb.56.gmail; Mon, 16 Dec 2013 21:30:36 -0800 (PST) X-Received: by 10.220.98.201 with SMTP id r9mr5594073vcn.34.1387258236957; Mon, 16 Dec 2013 21:30:36 -0800 (PST) Received: from mail-vb0-f50.google.com (mail-vb0-f50.google.com [209.85.212.50]) by mx.google.com with ESMTPS id qw3si4555785vcb.139.2013.12.16.21.30.36 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 16 Dec 2013 21:30:36 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.50 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.50; Received: by mail-vb0-f50.google.com with SMTP id w18so3882781vbj.9 for ; Mon, 16 Dec 2013 21:30:36 -0800 (PST) X-Received: by 10.58.232.228 with SMTP id tr4mr5641285vec.34.1387258236880; Mon, 16 Dec 2013 21:30:36 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp44489vcz; Mon, 16 Dec 2013 21:30:35 -0800 (PST) X-Received: by 10.66.197.164 with SMTP id iv4mr25112088pac.18.1387258235488; Mon, 16 Dec 2013 21:30:35 -0800 (PST) Received: from mail-pb0-f53.google.com (mail-pb0-f53.google.com [209.85.160.53]) by mx.google.com with ESMTPS id ye6si10742032pbc.260.2013.12.16.21.30.35 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 16 Dec 2013 21:30:35 -0800 (PST) Received-SPF: neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of christoffer.dall@linaro.org) client-ip=209.85.160.53; Received: by mail-pb0-f53.google.com with SMTP id ma3so6480887pbc.12 for ; Mon, 16 Dec 2013 21:30:35 -0800 (PST) X-Received: by 10.68.197.73 with SMTP id is9mr24774562pbc.75.1387258235089; Mon, 16 Dec 2013 21:30:35 -0800 (PST) Received: from localhost.localdomain (c-67-169-181-221.hsd1.ca.comcast.net. [67.169.181.221]) by mx.google.com with ESMTPSA id vn10sm30771688pbc.21.2013.12.16.21.30.33 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 16 Dec 2013 21:30:34 -0800 (PST) From: Christoffer Dall To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: linaro-kernel@lists.linaro.org, patches@linaro.org, Christoffer Dall Subject: [PATCH v5 08/10] KVM: arm-vgic: Support unqueueing of LRs to the dist Date: Mon, 16 Dec 2013 21:29:59 -0800 Message-Id: <1387258201-8738-9-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 1.8.5 In-Reply-To: <1387258201-8738-1-git-send-email-christoffer.dall@linaro.org> References: <1387258201-8738-1-git-send-email-christoffer.dall@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: christoffer.dall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.50 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , To properly access the VGIC state from user space it is very unpractical to have to loop through all the LRs in all register access functions. Instead, support moving all pending state from LRs to the distributor, but leave active state LRs alone. Note that to accurately present the active and pending state to VCPUs reading these distributor registers from a live VM, we would have to stop all other VPUs than the calling VCPU and ask each CPU to unqueue their LR state onto the distributor and add fields to track active state on the distributor side as well. We don't have any users of such functionality yet and there are other inaccuracies of the GIC emulation, so don't provide accurate synchronized access to this state just yet. However, when the time comes, having this function should help. Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 5 deletions(-) Changelog[v5]: - Reworked vgic_unqueue_irqs slightly again to also consider the ACTIVE+PENDING case. Changelog[v4]: - Reworked vgic_unqueue_irqs to explicitly check for the active bit and to not use __test_and_clear_bit. Changelog[v3]: - New patch in series diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 88599b5..d08ba28 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -589,6 +589,80 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu, return false; } +#define LR_CPUID(lr) \ + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) +#define LR_IRQID(lr) \ + ((lr) & GICH_LR_VIRTUALID) + +static void vgic_retire_lr(int lr_nr, int irq, struct vgic_cpu *vgic_cpu) +{ + clear_bit(lr_nr, vgic_cpu->lr_used); + vgic_cpu->vgic_lr[lr_nr] &= ~GICH_LR_STATE; + vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; +} + +/** + * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor + * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs + * + * Move any pending IRQs that have already been assigned to LRs back to the + * emulated distributor state so that the complete emulated state can be read + * from the main emulation structures without investigating the LRs. + * + * Note that IRQs in the active state in the LRs get their pending state moved + * to the distributor but the active state stays in the LRs, because we don't + * track the active state on the distributor side. + */ +static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu) +{ + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + int vcpu_id = vcpu->vcpu_id; + int i, irq, source_cpu; + u32 *lr; + + for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) { + lr = &vgic_cpu->vgic_lr[i]; + irq = LR_IRQID(*lr); + source_cpu = LR_CPUID(*lr); + + /* + * There are three options for the state bits: + * + * 01: pending + * 10: active + * 11: pending and active + * + * If the LR holds only an active interrupt (not pending) then + * just leave it alone. + */ + if ((*lr & GICH_LR_STATE) == GICH_LR_ACTIVE_BIT) + continue; + + /* + * Reestablish the pending state on the distributor and the + * CPU interface. It may have already been pending, but that + * is fine, then we are only setting a few bits that were + * already set. + */ + vgic_dist_irq_set(vcpu, irq); + if (irq < VGIC_NR_SGIS) + dist->irq_sgi_sources[vcpu_id][irq] |= 1 << source_cpu; + *lr &= ~GICH_LR_PENDING_BIT; + + /* + * If there's no state left on the LR (it could still be + * active), then the LR does not hold any useful info and can + * be marked as free for other use. + */ + if (!(*lr & GICH_LR_STATE)) + vgic_retire_lr(i, irq, vgic_cpu); + + /* Finally update the VGIC state. */ + vgic_update_state(vcpu->kvm); + } +} + static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, phys_addr_t offset) @@ -848,8 +922,6 @@ static void vgic_update_state(struct kvm *kvm) } } -#define LR_CPUID(lr) \ - (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) #define MK_LR_PEND(src, irq) \ (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) @@ -871,9 +943,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu) int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; if (!vgic_irq_is_enabled(vcpu, irq)) { - vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; - clear_bit(lr, vgic_cpu->lr_used); - vgic_cpu->vgic_lr[lr] &= ~GICH_LR_STATE; + vgic_retire_lr(lr, irq, vgic_cpu); if (vgic_irq_is_active(vcpu, irq)) vgic_irq_clear_active(vcpu, irq); } @@ -1675,6 +1745,14 @@ static int vgic_attr_regs_access(struct kvm_device *dev, } } + /* + * Move all pending IRQs from the LRs on all VCPUs so the pending + * state can be properly represented in the register state accessible + * through this API. + */ + kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) + vgic_unqueue_irqs(tmp_vcpu); + offset -= r->base; r->handle_mmio(vcpu, &mmio, offset);