From patchwork Thu May 4 15:31:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9712167 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 A9C7D6020B for ; Thu, 4 May 2017 15:31:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C356286B2 for ; Thu, 4 May 2017 15:31:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8EEE4286BA; Thu, 4 May 2017 15:31:41 +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 D100628697 for ; Thu, 4 May 2017 15:31:40 +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 1d6Igx-0004I2-MG; Thu, 04 May 2017 15:29:19 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d6Igw-0004HP-4N for xen-devel@lists.xenproject.org; Thu, 04 May 2017 15:29:18 +0000 Received: from [193.109.254.147] by server-8.bemta-6.messagelabs.com id 63/6C-03696-DC84B095; Thu, 04 May 2017 15:29:17 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrILMWRWlGSWpSXmKPExsVysyfVTfeMB3e kwb4bmhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8beGbNZCu5HV5z7dZO5gfGFXRcjF4eQwEZG ie03PzFCOMsZJe5vucfexcjJwSagK7Hj5mtmEFtEIFTi6YLvYDazgJLE/rPXGEFsYYFwiY9LX zB1MbJzsAioSsypAYnyClhJ/L+wjAnElhCQk2g4fx+sk1PAWmLv3t1gthBQzYcnJ9kmMHIvYG RYxahRnFpUllqka2Sml1SUmZ5RkpuYmaNraGCml5taXJyYnpqTmFSsl5yfu4kR6F0GINjBeGZ B4CFGSQ4mJVFe9VfskUJ8SfkplRmJxRnxRaU5qcWHGGU4OJQkeGe4c0cKCRalpqdWpGXmAMMM Ji3BwaMkwvsRJM1bXJCYW5yZDpE6xajL8W7ph/dMQix5+XmpUuK8G9yAigRAijJK8+BGwEL+E qOslDAvI9BRQjwFqUW5mSWo8q8YxTkYlYR5g0BW8WTmlcBtegV0BBPQEc2yHCBHlCQipKQaGG 06L5Ztq7Q2XjcvPzBk20uLN1H3H7PePH945nzLiWe2JLTOuJPGHnfHdv0UFvFsa4vHu74s2Tr l5UwujxOHpjQHLHnY8GlNcW7tHQGpR57tklzXun08G2/nf6o/fOPaR+bwRzyPJ2XOXeBtxdqW tEDC1OvOqeK9be6v/ieUG+v841rwymd1SpcSS3FGoqEWc1FxIgB+Bt+SdAIAAA== X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-8.tower-27.messagelabs.com!1493911755!90147688!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 4187 invoked from network); 4 May 2017 15:29:16 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-8.tower-27.messagelabs.com with SMTP; 4 May 2017 15:29:16 -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 BAF2C2B; Thu, 4 May 2017 08:29:15 -0700 (PDT) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0462F3F23B; Thu, 4 May 2017 08:29:14 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Thu, 4 May 2017 16:31:18 +0100 Message-Id: <20170504153123.1204-6-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 05/10] ARM: vGIC: move priority 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 priority for newly triggered IRQs in the rank structure. To get eventually rid of this structure, move this value into the struct pending_irq. This one already contains a priority value, but we have to keep the two apart, as the priority for guest visible IRQs must not change while they are in a VCPU. This patch introduces a framework to get some per-IRQ information for a number of interrupts and collate them into one register. Similarily there is the opposite function to spread values from one register into multiple pending_irq's. Signed-off-by: Andre Przywara --- xen/arch/arm/vgic-v2.c | 33 +++++++++-------------------- xen/arch/arm/vgic-v3.c | 33 ++++++++++------------------- xen/arch/arm/vgic.c | 53 ++++++++++++++++++++++++++++++++++------------ xen/include/asm-arm/vgic.h | 17 ++++++--------- 4 files changed, 67 insertions(+), 69 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index dc9f95b..5c59fb4 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; - 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; - - vgic_lock_rank(v, rank, flags); - ipriorityr = rank->ipriorityr[REG_RANK_INDEX(8, - gicd_reg - GICD_IPRIORITYR, - DABT_WORD)]; - vgic_unlock_rank(v, rank, flags); - *r = vgic_reg32_extract(ipriorityr, info); - + irq = gicd_reg - GICD_IPRIORITYR; + *r = vgic_reg32_extract(gather_irq_info_priority(v, irq), info); 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); @@ -499,17 +489,14 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { - uint32_t *ipriorityr; + uint32_t ipriorityr; 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)]; - vgic_reg32_update(ipriorityr, r, info); - vgic_unlock_rank(v, rank, flags); + irq = gicd_reg - GICD_IPRIORITYR; + + ipriorityr = gather_irq_info_priority(v, irq); + vgic_reg32_update(&ipriorityr, r, info); + scatter_irq_info_priority(v, irq, ipriorityr); return 1; } diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index d10757a..10db939 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -476,6 +476,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 ) { @@ -513,22 +514,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; - 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; - - vgic_lock_rank(v, rank, flags); - ipriorityr = rank->ipriorityr[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR, - DABT_WORD)]; - vgic_unlock_rank(v, rank, flags); - - *r = vgic_reg32_extract(ipriorityr, info); - + irq = reg - GICD_IPRIORITYR; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_priority(v, irq), info); return 1; - } case VRANGE32(GICD_ICFGR, GICD_ICFGRN): { @@ -572,6 +562,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 ) { @@ -630,16 +621,14 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { - uint32_t *ipriorityr; + uint32_t ipriorityr; 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)]; - vgic_reg32_update(ipriorityr, r, info); - vgic_unlock_rank(v, rank, flags); + irq = reg - GICD_IPRIORITYR; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + ipriorityr = gather_irq_info_priority(v, irq); + vgic_reg32_update(&ipriorityr, r, info); + scatter_irq_info_priority(v, irq, ipriorityr); return 1; } diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 44363bb..68eef47 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -225,19 +225,49 @@ 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) +static uint8_t extract_priority(struct pending_irq *p) { - struct vgic_irq_rank *rank = vgic_rank_irq(v, virq); - unsigned long flags; - int priority; + return p->new_priority; +} + +static void set_priority(struct pending_irq *p, uint8_t prio) +{ + p->new_priority = prio; +} + - vgic_lock_rank(v, rank, flags); - priority = rank->priority[virq & INTERRUPT_RANK_MASK]; - vgic_unlock_rank(v, rank, flags); +#define DEFINE_GATHER_IRQ_INFO(name, get_val, shift) \ +uint32_t gather_irq_info_##name(struct vcpu *v, unsigned int irq) \ +{ \ + uint32_t ret = 0, i; \ + for ( i = 0; i < (32 / shift); i++ ) \ + { \ + struct pending_irq *p = irq_to_pending(v, irq + i); \ + spin_lock(&p->lock); \ + ret |= get_val(p) << (shift * i); \ + spin_unlock(&p->lock); \ + } \ + return ret; \ +} - return priority; +#define DEFINE_SCATTER_IRQ_INFO(name, set_val, shift) \ +void scatter_irq_info_##name(struct vcpu *v, unsigned int irq, \ + unsigned int value) \ +{ \ + unsigned int i; \ + for ( i = 0; i < (32 / shift); i++ ) \ + { \ + struct pending_irq *p = irq_to_pending(v, irq + i); \ + spin_lock(&p->lock); \ + set_val(p, (value >> (shift * i)) & ((1 << shift) - 1)); \ + spin_unlock(&p->lock); \ + } \ } +/* 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) + bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq) { unsigned long flags; @@ -471,13 +501,10 @@ 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 = irq_to_pending(v, virq); unsigned long flags; bool running; - priority = vgic_get_virq_priority(v, virq); - spin_lock_irqsave(&v->arch.vgic.lock, flags); /* vcpu offline */ @@ -497,7 +524,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq) goto out; } - n->priority = priority; + n->priority = n->new_priority; /* the irq is enabled */ if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) ) @@ -505,7 +532,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq) list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) { - if ( iter->priority > priority ) + if ( iter->priority > n->priority ) { list_add_tail(&n->inflight, &iter->inflight); spin_unlock(&n->lock); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index e7322fc..38a5e76 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -71,7 +71,8 @@ struct pending_irq unsigned int irq; #define GIC_INVALID_LR (uint8_t)~0 uint8_t lr; - uint8_t priority; + uint8_t priority; /* the priority of the currently inflight IRQ */ + uint8_t new_priority; /* the priority of newly triggered IRQs */ /* inflight is used to append instances of pending_irq to * vgic.inflight_irqs */ struct list_head inflight; @@ -104,16 +105,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 @@ -179,6 +170,10 @@ static inline int REG_RANK_NR(int b, uint32_t n) } } +uint32_t gather_irq_info_priority(struct vcpu *v, unsigned int irq); +void scatter_irq_info_priority(struct vcpu *v, unsigned int irq, + unsigned int value); + #define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8))) /*