From patchwork Sat Dec 21 06:09:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 22702 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f71.google.com (mail-qe0-f71.google.com [209.85.128.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9D04F20822 for ; Sat, 21 Dec 2013 06:10:08 +0000 (UTC) Received: by mail-qe0-f71.google.com with SMTP id b10sf3716150qen.2 for ; Fri, 20 Dec 2013 22:10:07 -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=dS9GbohnVDgXr7LCV5N74CnjGil8wbuiR/N6XUKR0Z4=; b=Vcbq5N0N2Leie+SCuNKHNdNmsFFSQuAa6WCV92sdEikf1YEG2BBIwqEoS63EkFcSRF xuMWazoUZ5Zj6uhbRPBefB+ounAN+uomRXCVJbbXd9ARABy5FbvKbsxH8ZByciNNh+rd z7fD2wbnwFdQ7kWPtVGbgV0RQgMeN663xdL45zsxTMj6m/B5LWYit+Dp7o5SwkjnYmo+ OQJxM98wyQN5DQeiIQArG2H2XSE+bVlh5+iP7eA/lr4ye1RXMcGrEjuQbS0kEhi+4uw5 UZYC8vDeHYkEYvafvfFaFQADAlds6qicbHgc+G8RbCFxch8GQkuh4wimW+NtYyBXJbBR NRrA== X-Gm-Message-State: ALoCoQlILVlfOCsz1ENyDUI+le4aZ/EQlwct8VNipQy8M/m4UAy8CJ894BeKbUWWeXcxeAXqAs98 X-Received: by 10.224.162.212 with SMTP id w20mr4434253qax.5.1387606207810; Fri, 20 Dec 2013 22:10:07 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.76.72 with SMTP id i8ls1011208qew.59.gmail; Fri, 20 Dec 2013 22:10:07 -0800 (PST) X-Received: by 10.221.47.193 with SMTP id ut1mr7459014vcb.8.1387606207679; Fri, 20 Dec 2013 22:10:07 -0800 (PST) Received: from mail-vb0-f48.google.com (mail-vb0-f48.google.com [209.85.212.48]) by mx.google.com with ESMTPS id tw10si2316441vec.6.2013.12.20.22.10.07 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 20 Dec 2013 22:10:07 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.48 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.48; Received: by mail-vb0-f48.google.com with SMTP id f13so1835110vbg.7 for ; Fri, 20 Dec 2013 22:10:07 -0800 (PST) X-Received: by 10.58.233.98 with SMTP id tv2mr7491281vec.11.1387606207587; Fri, 20 Dec 2013 22:10:07 -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.59.13.131 with SMTP id ey3csp109305ved; Fri, 20 Dec 2013 22:10:06 -0800 (PST) X-Received: by 10.66.141.231 with SMTP id rr7mr12910200pab.41.1387606206387; Fri, 20 Dec 2013 22:10:06 -0800 (PST) Received: from mail-pd0-f178.google.com (mail-pd0-f178.google.com [209.85.192.178]) by mx.google.com with ESMTPS id s7si2360846pae.69.2013.12.20.22.10.06 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 20 Dec 2013 22:10:06 -0800 (PST) Received-SPF: neutral (google.com: 209.85.192.178 is neither permitted nor denied by best guess record for domain of christoffer.dall@linaro.org) client-ip=209.85.192.178; Received: by mail-pd0-f178.google.com with SMTP id y10so3385663pdj.9 for ; Fri, 20 Dec 2013 22:10:06 -0800 (PST) X-Received: by 10.66.179.143 with SMTP id dg15mr13377815pac.52.1387606205993; Fri, 20 Dec 2013 22:10:05 -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 ae5sm24345852pac.18.2013.12.20.22.10.02 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 20 Dec 2013 22:10:04 -0800 (PST) From: Christoffer Dall To: qemu-devel@nongnu.org Cc: kvmarm@lists.cs.columbia.edu, patches@linaro.org, Christoffer Dall Subject: [RFC PATCH v4 4/8] hw: arm_gic: Keep track of SGI sources Date: Fri, 20 Dec 2013 22:09:35 -0800 Message-Id: <1387606179-22709-5-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 1.8.5 In-Reply-To: <1387606179-22709-1-git-send-email-christoffer.dall@linaro.org> References: <1387606179-22709-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.48 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: , Right now the arm gic emulation doesn't keep track of the source of an SGI (which apparently Linux guests don't use, or they're fine with assuming CPU 0 always). Add the necessary matrix on the GICState structure and maintain the data when setting and clearing the pending state of an IRQ. Note that we always choose to present the source as the lowest-numbered CPU in case multiple cores have signalled the same SGI number to a core on the system. Signed-off-by: Christoffer Dall --- Changes [v3 -> v4]: - Assert that we are not messing with SGI state in gic_set_irq - Move bugfix of GICD_SPENDR to pending fixes patch - Get rid of the idea of git_clear_pending and handle clearing of source bits directly in gic_acknowledge_irq - Don't loop through CPUs to clear SGI sources - Return source CPU directly from gic_acknowledge_irq - Rename sgi_source to sgi_pending - Add comment (courtesey of Peter) to sgi_pending struct member. Changes [v2 -> v3]: - Changed ffs(x) - 1 to ctz32 - Changed cpu type to int in gic_clear_pending to avoid cast - Really try to fix the endless loop bug - Change gic_clear_pending to only clear the pending bit of SGIs if all CPUs do not have that IRQ pending from any CPUs. - Wrap long line in gic_internal.h - Fix bug allowing setting SGIs through the GICD_SPENDR Changes [v1 -> v2]: - Fixed endless loop bug - Bump version_id and minimum_version_id on vmstate struct hw/intc/arm_gic.c | 56 ++++++++++++++++++++++++++++------------ hw/intc/arm_gic_common.c | 5 ++-- include/hw/intc/arm_gic_common.h | 7 +++++ 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index dd76e1d..d0ccb2a 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -154,6 +154,8 @@ static void gic_set_irq(void *opaque, int irq, int level) target = cm; } + assert(irq >= GIC_NR_SGIS); + if (level == GIC_TEST_LEVEL(irq, cm)) { return; } @@ -180,35 +182,50 @@ static void gic_set_running_irq(GICState *s, int cpu, int irq) uint32_t gic_acknowledge_irq(GICState *s, int cpu) { - int new_irq; + int ret, irq, src; int cm = 1 << cpu; - new_irq = s->current_pending[cpu]; - if (new_irq == 1023 - || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) { + irq = s->current_pending[cpu]; + if (irq == 1023 + || GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) { DPRINTF("ACK no pending IRQ\n"); return 1023; } - s->last_active[new_irq][cpu] = s->running_irq[cpu]; + s->last_active[irq][cpu] = s->running_irq[cpu]; - cm = GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm; - GIC_CLEAR_SW_PENDING(new_irq, cm); + cm = GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm; + GIC_CLEAR_SW_PENDING(irq, cm); if (s->revision == REV_11MPCORE) { /* Clear pending flags for both level and edge triggered interrupts. * Level triggered IRQs will be reasserted once they become inactive. */ - GIC_CLEAR_PENDING(new_irq, cm); + GIC_CLEAR_PENDING(irq, cm); + ret = irq; } else { - /* Clear pending flags for edge-triggered and non-asserted - * level-triggered interrupts - */ - if (GIC_TEST_EDGE_TRIGGER(new_irq) || !GIC_TEST_LEVEL(new_irq, cpu)) { - GIC_CLEAR_PENDING(new_irq, cm); + if (irq < GIC_NR_SGIS) { + /* Lookup the source CPU for the SGI and clear this in the + * sgi_pending map. Return the src and clear the overall pending + * state on this CPU if the SGI is not pending from any CPUs. + */ + assert(s->sgi_pending[irq][cpu] != 0); + src = ctz32(s->sgi_pending[irq][cpu]); + s->sgi_pending[irq][cpu] &= ~(1 << src); + if (s->sgi_pending[irq][cpu] == 0) + GIC_CLEAR_PENDING(irq, cm); + ret = irq | ((src & 0x7) << 10); + } else { + /* Clear pending flags for edge-triggered and non-asserted + * level-triggered interrupts + */ + if (GIC_TEST_EDGE_TRIGGER(irq) || !GIC_TEST_LEVEL(irq, cpu)) { + GIC_CLEAR_PENDING(irq, cm); + } + ret = irq; } } - gic_set_running_irq(s, cpu, new_irq); - DPRINTF("ACK %d\n", new_irq); - return new_irq; + gic_set_running_irq(s, cpu, irq); + DPRINTF("ACK %d\n", irq); + return ret; } void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val) @@ -574,6 +591,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset, int cpu; int irq; int mask; + int target_cpu; cpu = gic_get_current_cpu(s); irq = value & 0x3ff; @@ -593,6 +611,12 @@ static void gic_dist_writel(void *opaque, hwaddr offset, break; } GIC_SET_PENDING(irq, mask); + target_cpu = ctz32(mask); + while (target_cpu < GIC_NCPU) { + s->sgi_pending[irq][target_cpu] |= (1 << cpu); + mask &= ~(1 << target_cpu); + target_cpu = ctz32(mask); + } gic_update(s); return; } diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 8c7621a..4647f0d 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -59,8 +59,8 @@ static const VMStateDescription vmstate_gic_irq_state = { static const VMStateDescription vmstate_gic = { .name = "arm_gic", - .version_id = 4, - .minimum_version_id = 4, + .version_id = 5, + .minimum_version_id = 5, .pre_save = gic_pre_save, .post_load = gic_post_load, .fields = (VMStateField[]) { @@ -72,6 +72,7 @@ static const VMStateDescription vmstate_gic = { VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU), VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU), + VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU), VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU), VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU), VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU), diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 126e122..59a005e 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -56,6 +56,13 @@ typedef struct GICState { uint8_t priority1[GIC_INTERNAL][GIC_NCPU]; uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; uint16_t last_active[GIC_MAXIRQ][GIC_NCPU]; + /* For each SGI on the target CPU, we store 8 bits + * indicating which source CPUs have made this SGI + * pending on the target CPU. These correspond to + * the bytes in the GIC_SPENDSGIR* registers as + * read by the target CPU. + */ + uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU]; uint16_t priority_mask[GIC_NCPU]; uint16_t running_irq[GIC_NCPU];