From patchwork Thu May 4 15:31:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9712169 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9348E6020B for ; Thu, 4 May 2017 15:31:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8588528697 for ; Thu, 4 May 2017 15:31:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 77494286C1; Thu, 4 May 2017 15:31:42 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B3BFF28697 for ; Thu, 4 May 2017 15:31:41 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d6Ih3-0004Pl-BM; Thu, 04 May 2017 15:29:25 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d6Ih1-0004Ly-Me for xen-devel@lists.xenproject.org; Thu, 04 May 2017 15:29:23 +0000 Received: from [85.158.143.35] by server-1.bemta-6.messagelabs.com id 9F/0E-03869-2D84B095; Thu, 04 May 2017 15:29:22 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrKLMWRWlGSWpSXmKPExsVysyfVTfe8B3e kQdMtRYvvWyYzOTB6HP5whSWAMYo1My8pvyKBNeP8xoWMBc0JFW0nHjA2MO7x7GLk5BAS2Mgo carbvYuRC8heziix7kYTO0iCTUBXYsfN18wgtohAqMTTBd/BbGYBJYn9Z68xdjFycAgLxEic/ yoKEmYRUJV4euQBI4jNK2Al0bRtGROILSEgJ9Fw/j5YK6eAtcTevbuZIfZaSXx4cpJtAiP3Ak aGVYwaxalFZalFuobGeklFmekZJbmJmTm6hgZmermpxcWJ6ak5iUnFesn5uZsYgd5lAIIdjF+ WBRxilORgUhLlVX/FHinEl5SfUpmRWJwRX1Sak1p8iFGGg0NJgneGO3ekkGBRanpqRVpmDjDM YNISHDxKIrydbkBp3uKCxNzizHSI1ClGRSlxXmuQPgGQREZpHlwbLLQvMcpKCfMyAh0ixFOQW pSbWYIq/4pRnINRSZiXCxgpQjyZeSVw018BLWYCWtwsywGyuCQRISXVwFj30Pjz9+82kUtfau w4PFtmlr/NbF5Z19Tw8joz7c+rdXdtr+dUeCRqahClt8iV4Y1BqfuPScl3fikmmdqIJCbJana cbdjed+No8O/Fd1w43gkpz/p396Ivc//tMOH929luLrBnSou98Ssu/IqTtTTrod9M14v+NDvs ZNjx+eaujWc2JEvsPK/EUpyRaKjFXFScCAAgwuJDaAIAAA== X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-15.tower-21.messagelabs.com!1493911758!66611552!1 X-Originating-IP: [217.140.101.70] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 17754 invoked from network); 4 May 2017 15:29:19 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-15.tower-21.messagelabs.com with SMTP; 4 May 2017 15:29:19 -0000 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 6EDDB2B; Thu, 4 May 2017 08:29:18 -0700 (PDT) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AB9B03F23B; Thu, 4 May 2017 08:29:17 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Thu, 4 May 2017 16:31:20 +0100 Message-Id: <20170504153123.1204-8-andre.przywara@arm.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170504153123.1204-1-andre.przywara@arm.com> References: <20170504153123.1204-1-andre.przywara@arm.com> Cc: xen-devel@lists.xenproject.org Subject: [Xen-devel] [RFC PATCH 07/10] ARM: vGIC: move enable status from irq_rank to struct pending_irq X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Currently we store the enable bit of an interrupt in the rank structure. Remove it from there and let the MMIO emulation use the already existing GIC_IRQ_GUEST_ENABLED in the status bits of struct pending_irq. Signed-off-by: Andre Przywara --- xen/arch/arm/vgic-v2.c | 38 ++++++++++++-------------------- xen/arch/arm/vgic-v3.c | 55 ++++++++++++++++++++++------------------------ xen/arch/arm/vgic.c | 27 +++++++++++++---------- xen/include/asm-arm/vgic.h | 7 +++--- 4 files changed, 58 insertions(+), 69 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index 795173c..22c679c 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -224,20 +224,15 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; /* Read the pending status of an IRQ via GICD is not supported */ @@ -430,24 +425,19 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_setbits(&rank->ienable, r, info); - vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + tr = gather_irq_info_enabled(v, irq); + vgic_reg32_setbits(&tr, r, info); + vgic_enable_irqs(v, irq, tr); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_clearbits(&rank->ienable, r, info); - vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + tr = gather_irq_info_enabled(v, irq); + vgic_reg32_clearbits(&tr, r, info); + vgic_disable_irqs(v, irq, tr); return 1; case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index 7989989..01764c9 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -474,8 +474,6 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, register_t *r) { struct hsr_dabt dabt = info->dabt; - struct vgic_irq_rank *rank; - unsigned long flags; unsigned int irq; switch ( reg ) @@ -487,20 +485,16 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; /* Read the pending status of an IRQ via GICD/GICR is not supported */ @@ -550,9 +544,6 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, register_t r) { struct hsr_dabt dabt = info->dabt; - struct vgic_irq_rank *rank; - uint32_t tr; - unsigned long flags; unsigned int irq; switch ( reg ) @@ -562,26 +553,32 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, goto write_ignore_32; case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): + { + uint32_t new_reg, tr; + if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_setbits(&rank->ienable, r, info); - vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + new_reg = gather_irq_info_enabled(v, irq); + tr = new_reg; + vgic_reg32_setbits(&new_reg, r, info); + vgic_enable_irqs(v, irq, new_reg & (~tr)); return 1; + } case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): + { + uint32_t new_reg, tr; + if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_clearbits(&rank->ienable, r, info); - vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + new_reg = gather_irq_info_enabled(v, irq); + tr = new_reg; + vgic_reg32_clearbits(&new_reg, r, info); + vgic_disable_irqs(v, irq, (~new_reg) & tr); return 1; + } case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 02c1d12..a23079a 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -235,6 +235,11 @@ static void set_priority(struct pending_irq *p, uint8_t prio) p->new_priority = prio; } +unsigned int extract_enabled(struct pending_irq *p) +{ + return test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) ? 1 : 0; +} + unsigned int extract_config(struct pending_irq *p) { return test_bit(GIC_IRQ_GUEST_EDGE, &p->status) ? 2 : 0; @@ -280,6 +285,7 @@ void scatter_irq_info_##name(struct vcpu *v, unsigned int irq, \ /* grep fodder: gather_irq_info_priority, scatter_irq_info_priority below */ DEFINE_GATHER_IRQ_INFO(priority, extract_priority, 8) DEFINE_SCATTER_IRQ_INFO(priority, set_priority, 8) +DEFINE_GATHER_IRQ_INFO(enabled, extract_enabled, 1) DEFINE_GATHER_IRQ_INFO(config, extract_config, 2) DEFINE_SCATTER_IRQ_INFO(config, set_config, 2) @@ -347,21 +353,19 @@ void arch_move_irqs(struct vcpu *v) } } -void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) +void vgic_disable_irqs(struct vcpu *v, unsigned int irq, uint32_t r) { const unsigned long mask = r; struct pending_irq *p; - unsigned int irq; unsigned long flags; int i = 0; struct vcpu *v_target; while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { - irq = i + (32 * n); - v_target = vgic_get_target_vcpu(v, irq); - p = irq_to_pending(v_target, irq); + v_target = vgic_get_target_vcpu(v, irq + i); + p = irq_to_pending(v_target, irq + i); clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status); - gic_remove_from_queues(v_target, irq); + gic_remove_from_queues(v_target, irq + i); if ( p->desc != NULL ) { spin_lock_irqsave(&p->desc->lock, flags); @@ -372,22 +376,21 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) } } -void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) +void vgic_enable_irqs(struct vcpu *v, unsigned int irq, uint32_t r) { const unsigned long mask = r; struct pending_irq *p; - unsigned int irq, int_type; + unsigned int int_type; unsigned long flags; int i = 0; struct vcpu *v_target; struct domain *d = v->domain; while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { - irq = i + (32 * n); - v_target = vgic_get_target_vcpu(v, irq); + v_target = vgic_get_target_vcpu(v, irq + i); spin_lock_irqsave(&v_target->arch.vgic.lock, flags); - p = irq_to_pending(v_target, irq); + p = irq_to_pending(v_target, irq + i); spin_lock(&p->lock); set_bit(GIC_IRQ_GUEST_ENABLED, &p->status); @@ -406,7 +409,7 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) * The irq cannot be a PPI, we only support delivery of SPIs * to guests. */ - ASSERT(irq >= 32); + ASSERT(irq + i >= 32); if ( irq_type_set_by_domain(d) ) gic_set_irq_type(p->desc, int_type); p->desc->handler->enable(p->desc); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 931a672..fe09fb8 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -104,8 +104,6 @@ struct vgic_irq_rank { uint8_t index; - uint32_t ienable; - /* * It's more convenient to store a target VCPU per vIRQ * than the register ITARGETSR/IROUTER itself. @@ -178,6 +176,7 @@ void scatter_irq_info_priority(struct vcpu *v, unsigned int irq, uint32_t gather_irq_info_config(struct vcpu *v, unsigned int irq); void scatter_irq_info_config(struct vcpu *v, unsigned int irq, unsigned int value); +uint32_t gather_irq_info_enabled(struct vcpu *v, unsigned int irq); #define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8))) @@ -311,8 +310,8 @@ extern struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq); extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s); extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq); extern bool vgic_emulate(struct cpu_user_regs *regs, union hsr hsr); -extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n); -extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n); +extern void vgic_disable_irqs(struct vcpu *v, unsigned int irq, uint32_t r); +extern void vgic_enable_irqs(struct vcpu *v, unsigned int irq, uint32_t r); extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops); int vgic_v2_init(struct domain *d, int *mmio_count); int vgic_v3_init(struct domain *d, int *mmio_count);