From patchwork Fri Aug 23 20:10:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 19515 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f199.google.com (mail-ve0-f199.google.com [209.85.128.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 4E32F248E6 for ; Fri, 23 Aug 2013 20:10:45 +0000 (UTC) Received: by mail-ve0-f199.google.com with SMTP id m1sf861809ves.6 for ; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-gm-message-state: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=iTCNFHlHogTDiw/vfrdfdZC8JN+kOYLJsNYDAkJcjSo=; b=fYEpMbae8Ta/+4aaZdmy37fJ1c8RwbqMd2yDgefRtJB252gFCJ9aiuEK8yJyI4pcT6 XnEOO8Q5A7+llP1SR1Tr9XrP1MSHigdliemReA0/DO25FTXsw4c+Ycy52QDL4UkOXPWH KAj3MmhmQDLNXe2VQSGsxCvgohAu05d8PYc8krUzSr4i/vytRLnIp2m3jXXUn78gB+lp 6siRSsdtERJwN9EsafGC1IyZ8KueTuvl4f9/YT7z1aue1jhOXUJ2+iyqDw3moXeULlA8 aZkN5XAt2yv1VulXJMoC6DwD5p3vSZnBZ18IgXWXh3JMWgdkxHv99oBeXpCb60RP77sv CbXA== X-Received: by 10.236.116.135 with SMTP id g7mr437593yhh.53.1377288644680; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.47.113 with SMTP id c17ls1801825qen.30.gmail; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) X-Received: by 10.58.198.13 with SMTP id iy13mr955203vec.11.1377288644585; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) Received: from mail-ve0-f181.google.com (mail-ve0-f181.google.com [209.85.128.181]) by mx.google.com with ESMTPS id tg9si465168vcb.107.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 23 Aug 2013 13:10:44 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.181 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.181; Received: by mail-ve0-f181.google.com with SMTP id jz10so754650veb.40 for ; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) X-Gm-Message-State: ALoCoQmHfanHwHbqKFgqwzLCASgmMS3SC0DZTNhaY4cNw1ktIlXz4a0v6CWvSFBXYccx8/yCf5sD X-Received: by 10.58.196.132 with SMTP id im4mr912444vec.28.1377288644485; Fri, 23 Aug 2013 13:10:44 -0700 (PDT) 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.220.174.196 with SMTP id u4csp113358vcz; Fri, 23 Aug 2013 13:10:43 -0700 (PDT) X-Received: by 10.66.196.110 with SMTP id il14mr714259pac.130.1377288639151; Fri, 23 Aug 2013 13:10:39 -0700 (PDT) Received: from mail-pb0-f43.google.com (mail-pb0-f43.google.com [209.85.160.43]) by mx.google.com with ESMTPS id hg4si750373pbc.255.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 23 Aug 2013 13:10:39 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.43 is neither permitted nor denied by best guess record for domain of christoffer.dall@linaro.org) client-ip=209.85.160.43; Received: by mail-pb0-f43.google.com with SMTP id md4so1078306pbc.2 for ; Fri, 23 Aug 2013 13:10:38 -0700 (PDT) X-Received: by 10.68.239.168 with SMTP id vt8mr1468863pbc.125.1377288638654; Fri, 23 Aug 2013 13:10:38 -0700 (PDT) Received: from localhost.localdomain (c-67-169-183-77.hsd1.ca.comcast.net. [67.169.183.77]) by mx.google.com with ESMTPSA id py4sm1590135pbc.14.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 23 Aug 2013 13:10:37 -0700 (PDT) From: Christoffer Dall To: qemu-devel@nongnu.org Cc: linaro-kernel@lists.linaro.org, patches@linaro.org, kvmarm@lists.cs.columbia.edu, Christoffer Dall Subject: [PATCH 3/5] hw: arm_gic: Keep track of SGI sources Date: Fri, 23 Aug 2013 13:10:22 -0700 Message-Id: <1377288624-7418-4-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1377288624-7418-1-git-send-email-christoffer.dall@linaro.org> References: <1377288624-7418-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.128.181 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 --- hw/intc/arm_gic.c | 38 ++++++++++++++++++++++++++++++-------- hw/intc/arm_gic_common.c | 1 + hw/intc/gic_internal.h | 3 +++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index a7bb528..4da534f 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -97,6 +97,20 @@ void gic_set_pending_private(GICState *s, int cpu, int irq) gic_update(s); } +static void gic_clear_pending(GICState *s, int irq, int cm, uint8_t src) +{ + unsigned cpu; + + GIC_CLEAR_PENDING(irq, cm); + if (irq < GIC_NR_SGIS) { + cpu = (unsigned)ffs(cm) - 1; + while (cpu < NCPU) { + s->sgi_source[irq][cpu] &= ~(1 << src); + cpu = (unsigned)ffs(cm) - 1; + } + } +} + /* Process a change in an external IRQ input. */ static void gic_set_irq(void *opaque, int irq, int level) { @@ -163,7 +177,8 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu) s->last_active[new_irq][cpu] = s->running_irq[cpu]; /* 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, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm); + gic_clear_pending(s, new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm, + GIC_SGI_SRC(new_irq, cpu)); gic_set_running_irq(s, cpu, new_irq); DPRINTF("ACK %d\n", new_irq); return new_irq; @@ -428,12 +443,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, irq = (offset - 0x280) * 8 + GIC_BASE_IRQ; if (irq >= s->num_irq) goto bad_reg; - for (i = 0; i < 8; i++) { - /* ??? This currently clears the pending bit for all CPUs, even - for per-CPU interrupts. It's unclear whether this is the - corect behavior. */ - if (value & (1 << i)) { - GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK); + for (i = 0; i < 8; i++, irq++) { + if (irq > GIC_NR_SGIS && value & (1 << i)) { + gic_clear_pending(s, irq, 1 << cpu, 0); } } } else if (offset < 0x400) { @@ -506,6 +518,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset, int cpu; int irq; int mask; + unsigned target_cpu; cpu = gic_get_current_cpu(s); irq = value & 0x3ff; @@ -525,6 +538,11 @@ static void gic_dist_writel(void *opaque, hwaddr offset, break; } GIC_SET_PENDING(irq, mask); + target_cpu = (unsigned)ffs(mask) - 1; + while (target_cpu < NCPU) { + s->sgi_source[irq][target_cpu] |= (1 << cpu); + target_cpu = (unsigned)ffs(mask) - 1; + } gic_update(s); return; } @@ -542,6 +560,8 @@ static const MemoryRegionOps gic_dist_ops = { static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) { + int value; + switch (offset) { case 0x00: /* Control */ return s->cpu_enabled[cpu]; @@ -551,7 +571,9 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) /* ??? Not implemented. */ return 0; case 0x0c: /* Acknowledge */ - return gic_acknowledge_irq(s, cpu); + value = gic_acknowledge_irq(s, cpu); + value |= (GIC_SGI_SRC(value, cpu) & 0x7) << 10; + return value; case 0x14: /* Running Priority */ return s->running_priority[cpu]; case 0x18: /* Highest Pending Interrupt */ diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 709b5c2..7a1c9e5 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -71,6 +71,7 @@ static const VMStateDescription vmstate_gic = { VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU), VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU), + VMSTATE_UINT8_2DARRAY(sgi_source, GICState, GIC_NR_SGIS, NCPU), VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU), VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU), VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU), diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index d835aa1..6f04885 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -27,6 +27,7 @@ #define GIC_MAXIRQ 1020 /* First 32 are private to each CPU (SGIs and PPIs). */ #define GIC_INTERNAL 32 +#define GIC_NR_SGIS 16 /* Maximum number of possible CPU interfaces, determined by GIC architecture */ #define NCPU 8 @@ -64,6 +65,7 @@ *__x = val; \ } while (0) #define GIC_TARGET(irq) s->irq_target[irq] +#define GIC_SGI_SRC(irq, cpu) (((irq) < GIC_NR_SGIS) ? ffs(s->sgi_source[irq][cpu]) - 1 : 0) typedef struct gic_irq_state { /* The enable bits are only banked for per-cpu interrupts. */ @@ -89,6 +91,7 @@ typedef struct GICState { uint8_t priority1[GIC_INTERNAL][NCPU]; uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; uint16_t last_active[GIC_MAXIRQ][NCPU]; + uint8_t sgi_source[GIC_NR_SGIS][NCPU]; uint16_t priority_mask[NCPU]; uint16_t running_irq[NCPU];