From patchwork Mon Jun 8 17:03:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 6567041 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 114FF9F3D1 for ; Mon, 8 Jun 2015 17:04:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 082AD2039C for ; Mon, 8 Jun 2015 17:04:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 80DC2204DE for ; Mon, 8 Jun 2015 17:04:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753041AbbFHREk (ORCPT ); Mon, 8 Jun 2015 13:04:40 -0400 Received: from foss.arm.com ([217.140.101.70]:48946 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751583AbbFHREc (ORCPT ); Mon, 8 Jun 2015 13:04:32 -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 37953653; Mon, 8 Jun 2015 10:04:41 -0700 (PDT) Received: from approximate.cambridge.arm.com (approximate.cambridge.arm.com [10.1.209.148]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id F15F53F52A; Mon, 8 Jun 2015 10:04:30 -0700 (PDT) From: Marc Zyngier To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Cc: Christoffer Dall , Eric Auger , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Andre Przywara Subject: [PATCH 04/10] KVM: arm/arm64: vgic: Allow HW irq to be encoded in LR Date: Mon, 8 Jun 2015 18:03:59 +0100 Message-Id: <1433783045-8002-5-git-send-email-marc.zyngier@arm.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1433783045-8002-1-git-send-email-marc.zyngier@arm.com> References: <1433783045-8002-1-git-send-email-marc.zyngier@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Now that struct vgic_lr supports the LR_HW bit and carries a hwirq field, we can encode that information into the list registers. This patch provides implementations for both GICv2 and GICv3. Signed-off-by: Marc Zyngier --- include/linux/irqchip/arm-gic-v3.h | 3 +++ include/linux/irqchip/arm-gic.h | 3 ++- virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index ffbc034..cf637d6 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -268,9 +268,12 @@ #define ICH_LR_EOI (1UL << 41) #define ICH_LR_GROUP (1UL << 60) +#define ICH_LR_HW (1UL << 61) #define ICH_LR_STATE (3UL << 62) #define ICH_LR_PENDING_BIT (1UL << 62) #define ICH_LR_ACTIVE_BIT (1UL << 63) +#define ICH_LR_PHYS_ID_SHIFT 32 +#define ICH_LR_PHYS_ID_MASK (0x3ffUL << ICH_LR_PHYS_ID_SHIFT) #define ICH_MISR_EOI (1 << 0) #define ICH_MISR_U (1 << 1) diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 9de976b..ca88dad 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -71,11 +71,12 @@ #define GICH_LR_VIRTUALID (0x3ff << 0) #define GICH_LR_PHYSID_CPUID_SHIFT (10) -#define GICH_LR_PHYSID_CPUID (7 << GICH_LR_PHYSID_CPUID_SHIFT) +#define GICH_LR_PHYSID_CPUID (0x3ff << GICH_LR_PHYSID_CPUID_SHIFT) #define GICH_LR_STATE (3 << 28) #define GICH_LR_PENDING_BIT (1 << 28) #define GICH_LR_ACTIVE_BIT (1 << 29) #define GICH_LR_EOI (1 << 19) +#define GICH_LR_HW (1 << 31) #define GICH_VMCR_CTRL_SHIFT 0 #define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT) diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index f9b9c7c..8d7b04d 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -48,6 +48,10 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) lr_desc.state |= LR_STATE_ACTIVE; if (val & GICH_LR_EOI) lr_desc.state |= LR_EOI_INT; + if (val & GICH_LR_HW) { + lr_desc.state |= LR_HW; + lr_desc.hwirq = (val & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT; + } return lr_desc; } @@ -55,7 +59,9 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, struct vgic_lr lr_desc) { - u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq; + u32 lr_val; + + lr_val = lr_desc.irq; if (lr_desc.state & LR_STATE_PENDING) lr_val |= GICH_LR_PENDING_BIT; @@ -64,6 +70,14 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, if (lr_desc.state & LR_EOI_INT) lr_val |= GICH_LR_EOI; + if (lr_desc.state & LR_HW) { + lr_val |= GICH_LR_HW; + lr_val |= (u32)lr_desc.hwirq << GICH_LR_PHYSID_CPUID_SHIFT; + } + + if (lr_desc.irq < VGIC_NR_SGIS) + lr_val |= (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT); + vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; } diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index dff0602..afbf925 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c @@ -67,6 +67,10 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr) lr_desc.state |= LR_STATE_ACTIVE; if (val & ICH_LR_EOI) lr_desc.state |= LR_EOI_INT; + if (val & ICH_LR_HW) { + lr_desc.state |= LR_HW; + lr_desc.hwirq = (val >> ICH_LR_PHYS_ID_SHIFT) & GENMASK(9, 0); + } return lr_desc; } @@ -84,10 +88,17 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, * Eventually we want to make this configurable, so we may revisit * this in the future. */ - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) + switch (vcpu->kvm->arch.vgic.vgic_model) { + case KVM_DEV_TYPE_ARM_VGIC_V3: lr_val |= ICH_LR_GROUP; - else - lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; + break; + case KVM_DEV_TYPE_ARM_VGIC_V2: + if (lr_desc.irq < VGIC_NR_SGIS) + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; + break; + default: + BUG(); + } if (lr_desc.state & LR_STATE_PENDING) lr_val |= ICH_LR_PENDING_BIT; @@ -95,6 +106,10 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, lr_val |= ICH_LR_ACTIVE_BIT; if (lr_desc.state & LR_EOI_INT) lr_val |= ICH_LR_EOI; + if (lr_desc.state & LR_HW) { + lr_val |= ICH_LR_HW; + lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT; + } vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; }