From patchwork Thu Oct 30 22:12:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Bellows X-Patchwork-Id: 39951 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f69.google.com (mail-la0-f69.google.com [209.85.215.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id AECFB202FE for ; Fri, 31 Oct 2014 18:06:45 +0000 (UTC) Received: by mail-la0-f69.google.com with SMTP id q1sf4469546lam.0 for ; Fri, 31 Oct 2014 11:06:44 -0700 (PDT) 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:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=oQawT37YmUiMDvSueYQVU3kvjSQ1Rq4sNweV8kuAB8o=; b=QVfi2l7UZHKGjR8Pa8nf49zVIs18pifYltRbIvKhNtoGFauYyvw+ZtzqMrVYfdRfNn C5D08PTok5wNQ+H2he1Jy0Z/AZiUKR26GN5/MLkOSDrw0+Z8rtU5+CI6KO24YVrrjAli J6AoxMl3jkc2/SAxR9iSeVl61JlS5qEDRPnL1Od+qmR+wULmriauyJVcUpvL2qG31TL+ wYVe3lG4K7beZ3SabXiB4fB9EAh93WrpTWnJRjRkj7R3m9N9B2ZljWijS5e7QM3IBsZz XyXaMSlQ1WvVuAxlkVnZcg5gfeiPVjrjYu1LKyYPc0ZlA8dBZCPutIjnJ97NR1TWb+md kk4g== X-Gm-Message-State: ALoCoQkRWByxJH8jfoPZARFTg8Q1xTqVuiZWp5kxCD9OPInTlowW+Om7c/49nt61eV4kmLJ6jKnE X-Received: by 10.112.137.202 with SMTP id qk10mr706341lbb.11.1414778804552; Fri, 31 Oct 2014 11:06:44 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.206.8 with SMTP id lk8ls428281lac.17.gmail; Fri, 31 Oct 2014 11:06:44 -0700 (PDT) X-Received: by 10.112.162.41 with SMTP id xx9mr27872937lbb.21.1414778804013; Fri, 31 Oct 2014 11:06:44 -0700 (PDT) Received: from mail-la0-f53.google.com (mail-la0-f53.google.com. [209.85.215.53]) by mx.google.com with ESMTPS id wx5si17936322lbb.123.2014.10.31.11.06.43 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 11:06:43 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) client-ip=209.85.215.53; Received: by mail-la0-f53.google.com with SMTP id mc6so6569310lab.26 for ; Fri, 31 Oct 2014 11:06:43 -0700 (PDT) X-Received: by 10.112.14.69 with SMTP id n5mr28130040lbc.34.1414778803751; Fri, 31 Oct 2014 11:06:43 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.84.229 with SMTP id c5csp240880lbz; Fri, 31 Oct 2014 11:06:42 -0700 (PDT) X-Received: by 10.224.45.201 with SMTP id g9mr15663600qaf.86.1414778802142; Fri, 31 Oct 2014 11:06:42 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id g11si16728578qgg.113.2014.10.31.11.06.41 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 31 Oct 2014 11:06:42 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:40443 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XkGav-0005X1-2r for patch@linaro.org; Fri, 31 Oct 2014 14:06:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57418) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XkE4x-0004Vq-J4 for qemu-devel@nongnu.org; Fri, 31 Oct 2014 11:26:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xjxxa-00068c-SK for qemu-devel@nongnu.org; Thu, 30 Oct 2014 18:12:57 -0400 Received: from mail-pa0-f53.google.com ([209.85.220.53]:63500) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xjxxa-00067q-IJ for qemu-devel@nongnu.org; Thu, 30 Oct 2014 18:12:50 -0400 Received: by mail-pa0-f53.google.com with SMTP id kx10so6349195pab.12 for ; Thu, 30 Oct 2014 15:12:49 -0700 (PDT) X-Received: by 10.70.48.10 with SMTP id h10mr20423764pdn.2.1414707169875; Thu, 30 Oct 2014 15:12:49 -0700 (PDT) Received: from gbellows-linaro.qualcomm.com (rrcs-67-52-129-61.west.biz.rr.com. [67.52.129.61]) by mx.google.com with ESMTPSA id h3sm7270163pdl.22.2014.10.30.15.12.48 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 30 Oct 2014 15:12:48 -0700 (PDT) From: Greg Bellows To: qemu-devel@nongnu.org, peter.maydell@linaro.org, serge.fdrv@gmail.com, edgar.iglesias@gmail.com, aggelerf@ethz.ch, christoffer.dall@linaro.org Date: Thu, 30 Oct 2014 17:12:04 -0500 Message-Id: <1414707132-24588-9-git-send-email-greg.bellows@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1414707132-24588-1-git-send-email-greg.bellows@linaro.org> References: <1414707132-24588-1-git-send-email-greg.bellows@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.220.53 Cc: daniel.thompson@linaro.org Subject: [Qemu-devel] [PATCH v2 08/16] hw/intc/arm_gic: Make ICCICR/GICC_CTLR banked X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: greg.bellows@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Fabian Aggeler ICCICR/GICC_CTLR is banked in GICv1 implementations with Security Extensions or in GICv2 in independent from Security Extensions. This makes it possible to enable forwarding of interrupts from the CPU interfaces to the connected processors for Group0 and Group1. We also allow to set additional bits like AckCtl and FIQEn by changing the type from bool to uint32. Since the field does not only store the enable bit anymore and since we are touching the vmstate, we use the opportunity to rename the field to cpu_control. Signed-off-by: Fabian Aggeler --- v1 -> v2 - Rework gic_set_cpu_control() and gic_get_cpu_control() to close gap on handling GICv1 wihtout security extensions. - Fix use of incorrect control index in update. --- hw/intc/arm_gic.c | 82 +++++++++++++++++++++++++++++++++++++--- hw/intc/arm_gic_common.c | 5 ++- hw/intc/arm_gic_kvm.c | 8 ++-- hw/intc/armv7m_nvic.c | 2 +- hw/intc/gic_internal.h | 14 +++++++ include/hw/intc/arm_gic_common.h | 2 +- 6 files changed, 100 insertions(+), 13 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 1db15aa..3c0414f 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -66,7 +66,7 @@ void gic_update(GICState *s) for (cpu = 0; cpu < NUM_CPU(s); cpu++) { cm = 1 << cpu; s->current_pending[cpu] = 1023; - if (!s->enabled || !s->cpu_enabled[cpu]) { + if (!s->enabled || !(s->cpu_control[cpu][1] & 1)) { qemu_irq_lower(s->parent_irq[cpu]); return; } @@ -240,6 +240,80 @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val) } } +uint32_t gic_get_cpu_control(GICState *s, int cpu) +{ + uint32_t ret; + + if (!s->security_extn) { + if (s->revision == 1) { + ret = s->cpu_control[cpu][1]; + ret &= 0x1; /* Mask of reserved bits */ + } else { + ret = s->cpu_control[cpu][0]; + ret &= GICC_CTLR_S_MASK; /* Mask of reserved bits */ + } + } else { + if (ns_access()) { + ret = s->cpu_control[cpu][1]; + ret &= GICC_CTLR_NS_MASK; /* Mask of reserved bits */ + if (s->revision == 1) { + ret &= 0x1; /* Mask of reserved bits */ + } + } else { + ret = s->cpu_control[cpu][0]; + ret &= GICC_CTLR_S_MASK; /* Mask of reserved bits */ + } + } + + return ret; +} + +void gic_set_cpu_control(GICState *s, int cpu, uint32_t value) +{ + if (!s->security_extn) { + if (s->revision == 1) { + s->cpu_control[cpu][1] = value & 0x1; + DPRINTF("CPU Interface %d %sabled\n", cpu, + s->cpu_control[cpu][1] ? "En" : "Dis"); + } else { + /* Write to Secure instance of the register */ + s->cpu_control[cpu][0] = value & GICC_CTLR_S_MASK; + /* Synchronize EnableGrp1 alias of Non-secure copy */ + s->cpu_control[cpu][1] &= ~GICC_CTLR_NS_EN_GRP1; + s->cpu_control[cpu][1] |= + (value & GICC_CTLR_S_EN_GRP1) ? GICC_CTLR_NS_EN_GRP1 : 0; + DPRINTF("CPU Interface %d: Group0 Interrupts %sabled, " + "Group1 Interrupts %sabled\n", cpu, + (s->cpu_control[cpu][0] & GICC_CTLR_S_EN_GRP0) ? "En" : "Dis", + (s->cpu_control[cpu][0] & GICC_CTLR_S_EN_GRP1) ? "En" : "Dis"); + } + } else { + if (ns_access()) { + if (s->revision == 1) { + s->cpu_control[cpu][1] = value & 0x1; + DPRINTF("CPU Interface %d %sabled\n", cpu, + s->cpu_control[cpu][1] ? "En" : "Dis"); + } else { + /* Write to Non-secure instance of the register */ + s->cpu_control[cpu][1] = value & GICC_CTLR_NS_MASK; + /* Synchronize EnableGrp1 alias of Secure copy */ + s->cpu_control[cpu][0] &= ~GICC_CTLR_S_EN_GRP1; + s->cpu_control[cpu][0] |= + (value & GICC_CTLR_NS_EN_GRP1) ? GICC_CTLR_S_EN_GRP1 : 0; + } + DPRINTF("CPU Interface %d: Group1 Interrupts %sabled\n", cpu, + (s->cpu_control[cpu][1] & GICC_CTLR_NS_EN_GRP1) ? "En" : "Dis"); + } else { + /* Write to Secure instance of the register */ + s->cpu_control[cpu][0] = value & GICC_CTLR_S_MASK; + /* Synchronize EnableGrp1 alias of Non-secure copy */ + s->cpu_control[cpu][1] &= ~GICC_CTLR_NS_EN_GRP1; + s->cpu_control[cpu][1] |= + (value & GICC_CTLR_S_EN_GRP1) ? GICC_CTLR_NS_EN_GRP1 : 0; + } + } +} + void gic_complete_irq(GICState *s, int cpu, int irq) { int update = 0; @@ -762,7 +836,7 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) { switch (offset) { case 0x00: /* Control */ - return s->cpu_enabled[cpu]; + return gic_get_cpu_control(s, cpu); case 0x04: /* Priority mask */ return s->priority_mask[cpu]; case 0x08: /* Binary Point */ @@ -788,9 +862,7 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) { switch (offset) { case 0x00: /* Control */ - s->cpu_enabled[cpu] = (value & 1); - DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled[cpu] ? "En" : "Dis"); - break; + return gic_set_cpu_control(s, cpu, value); case 0x04: /* Priority mask */ s->priority_mask[cpu] = (value & 0xff); break; diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index c44050d..e225f2b 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -65,7 +65,7 @@ static const VMStateDescription vmstate_gic = { .post_load = gic_post_load, .fields = (VMStateField[]) { VMSTATE_UINT8_ARRAY(enabled_grp, GICState, GIC_NR_GROUP), - VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU), + VMSTATE_UINT32_2DARRAY(cpu_control, GICState, GIC_NCPU, GIC_NR_GROUP), VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1, vmstate_gic_irq_state, gic_irq_state), VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ), @@ -127,7 +127,8 @@ static void arm_gic_common_reset(DeviceState *dev) s->current_pending[i] = 1023; s->running_irq[i] = 1023; s->running_priority[i] = 0x100; - s->cpu_enabled[i] = false; + s->cpu_control[i][0] = false; + s->cpu_control[i][1] = false; } for (i = 0; i < GIC_NR_SGIS; i++) { GIC_SET_ENABLED(i, ALL_CPU_MASK); diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index 5038885..9a6a2bb 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -379,8 +379,8 @@ static void kvm_arm_gic_put(GICState *s) */ for (cpu = 0; cpu < s->num_cpu; cpu++) { - /* s->cpu_enabled[cpu] -> GICC_CTLR */ - reg = s->cpu_enabled[cpu]; + /* s->cpu_enabled[cpu][0] -> GICC_CTLR */ + reg = s->cpu_control[cpu]; kvm_gicc_access(s, 0x00, cpu, ®, true); /* s->priority_mask[cpu] -> GICC_PMR */ @@ -478,9 +478,9 @@ static void kvm_arm_gic_get(GICState *s) */ for (cpu = 0; cpu < s->num_cpu; cpu++) { - /* GICC_CTLR -> s->cpu_enabled[cpu] */ + /* GICC_CTLR -> s->cpu_control[cpu][0] */ kvm_gicc_access(s, 0x00, cpu, ®, false); - s->cpu_enabled[cpu] = (reg & 1); + s->cpu_control[cpu][0] = reg; /* GICC_PMR -> s->priority_mask[cpu] */ kvm_gicc_access(s, 0x04, cpu, ®, false); diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index d0543d4..7f4a55c 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -465,7 +465,7 @@ static void armv7m_nvic_reset(DeviceState *dev) * as enabled by default, and with a priority mask which allows * all interrupts through. */ - s->gic.cpu_enabled[0] = true; + s->gic.cpu_control[0][0] = true; s->gic.priority_mask[0] = 0x100; /* The NVIC as a whole is always enabled. */ s->gic.enabled = true; diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index f01955a..e360de6 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -54,6 +54,17 @@ #define GIC_SET_GROUP1(irq, cm) (s->irq_state[irq].group |= (cm)) #define GIC_TEST_GROUP0(irq, cm) ((s->irq_state[irq].group & (cm)) == 0) +#define GICC_CTLR_S_EN_GRP0 (1U << 0) +#define GICC_CTLR_S_EN_GRP1 (1U << 1) +#define GICC_CTLR_S_ACK_CTL (1U << 2) +#define GICC_CTLR_S_FIQ_EN (1U << 3) +#define GICC_CTLR_S_CBPR (1U << 4) /* GICv1: SBPR */ + +#define GICC_CTLR_S_MASK 0x7ff + +#define GICC_CTLR_NS_EN_GRP1 (1U << 0) +#define GICC_CTLR_NS_MASK (1 | 3 << 5 | 1 << 9) + /* The special cases for the revision property: */ #define REV_11MPCORE 0 @@ -65,6 +76,9 @@ void gic_complete_irq(GICState *s, int cpu, int irq); void gic_update(GICState *s); void gic_init_irqs_and_distributor(GICState *s); void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val); +uint32_t gic_get_cpu_control(GICState *s, int cpu); +void gic_set_cpu_control(GICState *s, int cpu, uint32_t value); + static inline bool gic_test_pending(GICState *s, int irq, int cm) { diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 16e193d..1daa672 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -58,7 +58,7 @@ typedef struct GICState { uint8_t enabled; uint8_t enabled_grp[GIC_NR_GROUP]; /* EnableGrp0 and EnableGrp1 */ }; - bool cpu_enabled[GIC_NCPU]; + uint32_t cpu_control[GIC_NCPU][GIC_NR_GROUP]; gic_irq_state irq_state[GIC_MAXIRQ]; uint8_t irq_target[GIC_MAXIRQ];