From patchwork Fri Jul 21 19:59:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9857625 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 AE3FB601C0 for ; Fri, 21 Jul 2017 20:02:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9FC8B28636 for ; Fri, 21 Jul 2017 20:02:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 94ACC2863B; Fri, 21 Jul 2017 20:02:37 +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 DDF9A2864A for ; Fri, 21 Jul 2017 20:02:36 +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 1dYe5r-000592-RD; Fri, 21 Jul 2017 20:00:11 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dYe5q-000579-H4 for xen-devel@lists.xenproject.org; Fri, 21 Jul 2017 20:00:10 +0000 Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id 4E/47-01996-94D52795; Fri, 21 Jul 2017 20:00:09 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrOLMWRWlGSWpSXmKPExsVysyfVTdcjtij S4OEKQ4vvWyYzOTB6HP5whSWAMYo1My8pvyKBNeP41q2sBWcCK1pPzWJuYLxq28XIxSEksJlR YmnnTFYIZzmjxImddxm7GDk52AR0JXbcfM0MYosIhEo8XfAdzGYWUJLYf/YaWI2wQLTEmZcL2 EBsFgFViZNLZgHFOTh4Bawlzv+MBQlLCMhJNJy/D9bKKWAjseLyE7ByIaCS5sVTWSYwci9gZF jFqF6cWlSWWqRrrpdUlJmeUZKbmJmja2hgqpebWlycmJ6ak5hUrJecn7uJEehdBiDYwXhssvM hRkkOJiVRXk2rokghvqT8lMqMxOKM+KLSnNTiQ4wyHBxKErxLooFygkWp6akVaZk5wDCDSUtw 8CiJ8IrEAKV5iwsSc4sz0yFSpxiNOTasXv+FiePVhP/fmIRY8vLzUqXEed+BTBIAKc0ozYMbB Av/S4yyUsK8jECnCfEUpBblZpagyr9iFOdgVBLmbQCZwpOZVwK37xXQKUxApzxyKwA5pSQRIS XVwFgV3Ki5fd+MneeZT195aHXFQD9T2M672Jzz2uVDwrWL1vVuDNxR0slnrxule2b+tZs9rwR +JvFu3br2sdVcFa6Ene2bi87MMvzb96Dp6D7V/JbwTaZLOoTFDzpWnp3N6HasuVF2vhqbS+S5 peFaBfrVO717NqfMKK1fWHhg8b0VD1ZPVcy7wqPEUpyRaKjFXFScCAC9zEaeegIAAA== X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-16.tower-206.messagelabs.com!1500667208!88100387!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.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 60625 invoked from network); 21 Jul 2017 20:00:08 -0000 Received: from usa-sjc-mx-foss1.foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-16.tower-206.messagelabs.com with SMTP; 21 Jul 2017 20:00:08 -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 BF2691596; Fri, 21 Jul 2017 13:00:07 -0700 (PDT) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 001713F3E1; Fri, 21 Jul 2017 13:00:06 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Fri, 21 Jul 2017 20:59:56 +0100 Message-Id: <20170721200010.29010-9-andre.przywara@arm.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170721200010.29010-1-andre.przywara@arm.com> References: <20170721200010.29010-1-andre.przywara@arm.com> Cc: xen-devel@lists.xenproject.org Subject: [Xen-devel] [RFC PATCH v2 08/22] ARM: vGIC: move virtual IRQ priority from rank to 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 So far a virtual interrupt's priority is stored in the irq_rank structure, which covers multiple IRQs and has a single lock for this group. Generalize the already existing priority variable in struct pending_irq to not only cover LPIs, but every IRQ. Access to this value is protected by the per-IRQ lock. Signed-off-by: Andre Przywara --- xen/arch/arm/vgic-v2.c | 34 ++++++---------------------------- xen/arch/arm/vgic-v3.c | 36 ++++++++---------------------------- xen/arch/arm/vgic.c | 41 +++++++++++++++++------------------------ xen/include/asm-arm/vgic.h | 10 ---------- 4 files changed, 31 insertions(+), 90 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index cf4ab89..ed7ff3b 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -171,6 +171,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, struct vgic_irq_rank *rank; int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase); unsigned long flags; + unsigned int irq; perfc_incr(vgicd_reads); @@ -250,22 +251,10 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, goto read_as_zero; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): - { - uint32_t ipriorityr; - uint8_t rank_index; - if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - rank_index = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); - - vgic_lock_rank(v, rank, flags); - ipriorityr = ACCESS_ONCE(rank->ipriorityr[rank_index]); - vgic_unlock_rank(v, rank, flags); - *r = vreg_reg32_extract(ipriorityr, info); - + irq = gicd_reg - GICD_IPRIORITYR; /* 8 bit per IRQ, so IRQ = offset */ + *r = vgic_fetch_irq_priority(v, irq, (dabt.size == DABT_BYTE) ? 1 : 4); return 1; - } case VREG32(0x7FC): goto read_reserved; @@ -415,6 +404,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase); uint32_t tr; unsigned long flags; + unsigned int irq; perfc_incr(vgicd_writes); @@ -498,23 +488,11 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, goto write_ignore_32; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): - { - uint32_t *ipriorityr, priority; - if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - ipriorityr = &rank->ipriorityr[REG_RANK_INDEX(8, - gicd_reg - GICD_IPRIORITYR, - DABT_WORD)]; - priority = ACCESS_ONCE(*ipriorityr); - vreg_reg32_update(&priority, r, info); - ACCESS_ONCE(*ipriorityr) = priority; - vgic_unlock_rank(v, rank, flags); + irq = gicd_reg - GICD_IPRIORITYR; /* 8 bit per IRQ, so IRQ = offset */ + vgic_store_irq_priority(v, (dabt.size == DABT_BYTE) ? 1 : 4, irq, r); return 1; - } case VREG32(0x7FC): goto write_reserved; diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index ad9019e..e58e77e 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -677,6 +677,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, struct hsr_dabt dabt = info->dabt; struct vgic_irq_rank *rank; unsigned long flags; + unsigned int irq; switch ( reg ) { @@ -714,23 +715,11 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, goto read_as_zero; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): - { - uint32_t ipriorityr; - uint8_t rank_index; - if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 8, reg - GICD_IPRIORITYR, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - rank_index = REG_RANK_INDEX(8, reg - GICD_IPRIORITYR, DABT_WORD); - - vgic_lock_rank(v, rank, flags); - ipriorityr = ACCESS_ONCE(rank->ipriorityr[rank_index]); - vgic_unlock_rank(v, rank, flags); - - *r = vreg_reg32_extract(ipriorityr, info); - + irq = reg - GICD_IPRIORITYR; /* 8 bit per IRQ, so IRQ = offset */ + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_fetch_irq_priority(v, irq, (dabt.size == DABT_BYTE) ? 1 : 4); return 1; - } case VRANGE32(GICD_ICFGR, GICD_ICFGRN): { @@ -774,6 +763,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, struct vgic_irq_rank *rank; uint32_t tr; unsigned long flags; + unsigned int irq; switch ( reg ) { @@ -831,21 +821,11 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, goto write_ignore_32; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): - { - uint32_t *ipriorityr, priority; - if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 8, reg - GICD_IPRIORITYR, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - ipriorityr = &rank->ipriorityr[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR, - DABT_WORD)]; - priority = ACCESS_ONCE(*ipriorityr); - vreg_reg32_update(&priority, r, info); - ACCESS_ONCE(*ipriorityr) = priority; - vgic_unlock_rank(v, rank, flags); + irq = reg - GICD_IPRIORITYR; /* 8 bit per IRQ, so IRQ = offset */ + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + vgic_store_irq_priority(v, (dabt.size == DABT_BYTE) ? 1 : 4, irq, r); return 1; - } case VREG32(GICD_ICFGR): /* Restricted to configure SGIs */ goto write_ignore_32; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index b2c9632..ddcd99b 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -231,18 +231,6 @@ struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int virq) return v->domain->vcpu[target]; } -static int vgic_get_virq_priority(struct vcpu *v, unsigned int virq) -{ - struct vgic_irq_rank *rank; - - /* LPIs don't have a rank, also store their priority separately. */ - if ( is_lpi(virq) ) - return v->domain->arch.vgic.handler->lpi_get_priority(v->domain, virq); - - rank = vgic_rank_irq(v, virq); - return ACCESS_ONCE(rank->priority[virq & INTERRUPT_RANK_MASK]); -} - #define MAX_IRQS_PER_IPRIORITYR 4 uint32_t vgic_fetch_irq_priority(struct vcpu *v, unsigned int nrirqs, unsigned int first_irq) @@ -567,37 +555,40 @@ void vgic_clear_pending_irqs(struct vcpu *v) void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq) { - uint8_t priority; struct pending_irq *iter, *n; - unsigned long flags; + unsigned long flags, vcpu_flags; bool running; - spin_lock_irqsave(&v->arch.vgic.lock, flags); + spin_lock_irqsave(&v->arch.vgic.lock, vcpu_flags); n = irq_to_pending(v, virq); /* If an LPI has been removed, there is nothing to inject here. */ if ( unlikely(!n) ) { - spin_unlock_irqrestore(&v->arch.vgic.lock, flags); + spin_unlock_irqrestore(&v->arch.vgic.lock, vcpu_flags); return; } /* vcpu offline */ if ( test_bit(_VPF_down, &v->pause_flags) ) { - spin_unlock_irqrestore(&v->arch.vgic.lock, flags); + spin_unlock_irqrestore(&v->arch.vgic.lock, vcpu_flags); return; } + vgic_irq_lock(n, flags); + set_bit(GIC_IRQ_GUEST_QUEUED, &n->status); if ( !list_empty(&n->inflight) ) { bool update = test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) && list_empty(&n->lr_queue) && (v == current); + int lr = ACCESS_ONCE(n->lr); + vgic_irq_unlock(n, flags); if ( update ) - gic_update_one_lr(v, n->lr); + gic_update_one_lr(v, lr); #ifdef GIC_DEBUG else gdprintk(XENLOG_DEBUG, "trying to inject irq=%u into d%dv%d, when it is still lr_pending\n", @@ -606,24 +597,26 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq) goto out; } - priority = vgic_get_virq_priority(v, virq); - n->cur_priority = priority; + n->cur_priority = n->priority; /* the irq is enabled */ if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) ) - gic_raise_guest_irq(v, virq, priority); + gic_raise_guest_irq(v, virq, n->cur_priority); list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) { - if ( iter->cur_priority > priority ) + if ( iter->cur_priority > n->cur_priority ) { list_add_tail(&n->inflight, &iter->inflight); - goto out; + goto out_unlock_irq; } } list_add_tail(&n->inflight, &v->arch.vgic.inflight_irqs); + +out_unlock_irq: + vgic_irq_unlock(n, flags); out: - spin_unlock_irqrestore(&v->arch.vgic.lock, flags); + spin_unlock_irqrestore(&v->arch.vgic.lock, vcpu_flags); /* we have a new higher priority irq, inject it into the guest */ running = v->is_running; vcpu_unblock(v); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index f3791c8..59d52c6 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -113,16 +113,6 @@ struct vgic_irq_rank { uint32_t icfg[2]; /* - * Provide efficient access to the priority of an vIRQ while keeping - * the emulation simple. - * Note, this is working fine as long as Xen is using little endian. - */ - union { - uint8_t priority[32]; - uint32_t ipriorityr[8]; - }; - - /* * It's more convenient to store a target VCPU per vIRQ * than the register ITARGETSR/IROUTER itself. * Use atomic operations to read/write the vcpu fields to avoid