From patchwork Tue Jul 28 13:22:26 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 51596 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f70.google.com (mail-la0-f70.google.com [209.85.215.70]) by patches.linaro.org (Postfix) with ESMTPS id 7142E20323 for ; Tue, 28 Jul 2015 13:22:35 +0000 (UTC) Received: by laef2 with SMTP id f2sf38067134lae.0 for ; Tue, 28 Jul 2015 06:22:34 -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: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=0KnI7BH6cCLf/zZFh7kj1UBQEMwfFy0dg9DFo6rBxRQ=; b=gPwcL5GfEtK/IQtJjsd+B0XzZ2vsCXOV22VhuyV4BMJ3/gY729eCr7OHy6n+s5Sf09 lZBB1XQC3We/bFVP41mBDi8SCZMARbe1HCfH5i/UYqtc7dQM+sU4z0D3pcHNpHoULLYJ n7oOMw/Hqlqh3FdExsZLWPS8565cLLW6PFufxtmEJBOVOI7/r0866tElVVFypmcAGThe WKmwl8c+RA8/hiGv39FMyh0bEUFl2sfj/hyPn9AljaFFdImJ9nRvnGVwaptWAcy2aAkv A2Rf6DNzoAPiXIa00nW9ER+ccdGHpNZhh+p6U+o2TLBtmqgc29my6Ab4A0aVi/kTUGl4 t/Vg== X-Gm-Message-State: ALoCoQm3t3hJL2RID8bhNf4aOsx1RJigmGUTYKLj/1ObMctG6CIWtZHA0aLuJYMNkm3HqZXoEldX X-Received: by 10.112.171.41 with SMTP id ar9mr14177918lbc.24.1438089754538; Tue, 28 Jul 2015 06:22:34 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.120.198 with SMTP id le6ls720128lab.56.gmail; Tue, 28 Jul 2015 06:22:34 -0700 (PDT) X-Received: by 10.112.52.2 with SMTP id p2mr32365742lbo.8.1438089754262; Tue, 28 Jul 2015 06:22:34 -0700 (PDT) Received: from mail-lb0-f177.google.com (mail-lb0-f177.google.com. [209.85.217.177]) by mx.google.com with ESMTPS id r5si18349756lbp.16.2015.07.28.06.22.34 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2015 06:22:34 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) client-ip=209.85.217.177; Received: by lblf12 with SMTP id f12so74499176lbl.2 for ; Tue, 28 Jul 2015 06:22:34 -0700 (PDT) X-Received: by 10.112.166.2 with SMTP id zc2mr32618281lbb.29.1438089754029; Tue, 28 Jul 2015 06:22:34 -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.112.7.198 with SMTP id l6csp2138421lba; Tue, 28 Jul 2015 06:22:33 -0700 (PDT) X-Received: by 10.152.245.168 with SMTP id xp8mr32766030lac.109.1438089750529; Tue, 28 Jul 2015 06:22:30 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id o5si18340431lae.1.2015.07.28.06.22.29 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 28 Jul 2015 06:22:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1ZK4pw-0001Ro-FU; Tue, 28 Jul 2015 14:22:28 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, "Edgar E. Iglesias" Subject: [PATCH 3/5] hw/intc/arm_gic: Fix handling of GICC_APR, GICC_NSAPR registers Date: Tue, 28 Jul 2015 14:22:26 +0100 Message-Id: <1438089748-5528-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1438089748-5528-1-git-send-email-peter.maydell@linaro.org> References: <1438089748-5528-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@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.217.177 as permitted sender) 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: , A GICv2 has both GICC_APR and GICC_NSAPR registers, with the latter holding the active priority bits for Group 1 interrupts (usually Nonsecure interrupts), and the Nonsecure view of the GICC_APR is the second half of the GICC_NSAPR registers. Turn our half-hearted implementation of APR into a proper implementation of both APR and NSAPR: * Add the underlying state for NSAPR * Make sure APR aren't visible for pre-GICv2 * Implement reading of NSAPR * Make non-secure reads of APR behave correctly * Implement writing to APR and NSAPR Signed-off-by: Peter Maydell --- hw/intc/arm_gic.c | 114 ++++++++++++++++++++++++++++++++++++++- hw/intc/arm_gic_common.c | 5 +- include/hw/intc/arm_gic_common.h | 1 + 3 files changed, 116 insertions(+), 4 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 9814bb9..ed7faf5 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -954,6 +954,68 @@ static const MemoryRegionOps gic_dist_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static inline uint32_t gic_apr_ns_view(GICState *s, int cpu, int regno) +{ + /* Return the Nonsecure view of GICC_APR. This is the + * second half of GICC_NSAPR. + */ + switch (GIC_MIN_BPR) { + case 0: + if (regno < 2) { + return s->nsapr[regno + 2][cpu]; + } + break; + case 1: + if (regno == 0) { + return s->nsapr[regno + 1][cpu]; + } + break; + case 2: + if (regno == 0) { + return extract32(s->nsapr[0][cpu], 16, 16); + } + break; + case 3: + if (regno == 0) { + return extract32(s->nsapr[0][cpu], 8, 8); + } + break; + default: + g_assert_not_reached(); + } + return 0; +} + +static inline void gic_apr_write_ns_view(GICState *s, int cpu, int regno, + uint32_t value) +{ + /* Write the Nonsecure view of GICC_APR. */ + switch (GIC_MIN_BPR) { + case 0: + if (regno < 2) { + s->nsapr[regno + 2][cpu] = value; + } + break; + case 1: + if (regno == 0) { + s->nsapr[regno + 1][cpu] = value; + } + break; + case 2: + if (regno == 0) { + s->nsapr[0][cpu] = deposit32(s->nsapr[0][cpu], 16, 16, value); + } + break; + case 3: + if (regno == 0) { + s->nsapr[0][cpu] = deposit32(s->nsapr[0][cpu], 8, 8, value); + } + break; + default: + g_assert_not_reached(); + } +} + static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, uint64_t *data, MemTxAttrs attrs) { @@ -994,8 +1056,31 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, } break; case 0xd0: case 0xd4: case 0xd8: case 0xdc: - *data = s->apr[(offset - 0xd0) / 4][cpu]; + { + int regno = (offset - 0xd0) / 4; + + if (regno >= GIC_NR_APRS || s->revision != 2) { + *data = 0; + } else if (s->security_extn && !attrs.secure) { + /* NS view of GICC_APR is the top half of GIC_NSAPR */ + *data = gic_apr_ns_view(s, regno, cpu); + } else { + *data = s->apr[regno][cpu]; + } break; + } + case 0xe0: case 0xe4: case 0xe8: case 0xec: + { + int regno = (offset - 0xe0) / 4; + + if (regno >= GIC_NR_APRS || s->revision != 2 || !gic_has_groups(s) || + (s->security_extn && !attrs.secure)) { + *data = 0; + } else { + *data = s->nsapr[regno][cpu]; + } + break; + } default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_read: Bad offset %x\n", (int)offset); @@ -1033,8 +1118,33 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, } break; case 0xd0: case 0xd4: case 0xd8: case 0xdc: - qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n"); + { + int regno = (offset - 0xd0) / 4; + + if (regno >= GIC_NR_APRS || s->revision != 2) { + return MEMTX_OK; + } + if (s->security_extn && !attrs.secure) { + /* NS view of GICC_APR is the top half of GIC_NSAPR */ + gic_apr_write_ns_view(s, regno, cpu, value); + } else { + s->apr[regno][cpu] = value; + } + break; + } + case 0xe0: case 0xe4: case 0xe8: case 0xec: + { + int regno = (offset - 0xe0) / 4; + + if (regno >= GIC_NR_APRS || s->revision != 2) { + return MEMTX_OK; + } + if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) { + return MEMTX_OK; + } + s->nsapr[regno][cpu] = value; break; + } default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_write: Bad offset %x\n", (int)offset); diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index a64d071..ea412ae 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 = 10, - .minimum_version_id = 10, + .version_id = 11, + .minimum_version_id = 11, .pre_save = gic_pre_save, .post_load = gic_post_load, .fields = (VMStateField[]) { @@ -80,6 +80,7 @@ static const VMStateDescription vmstate_gic = { VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU), VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU), VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU), + VMSTATE_UINT32_2DARRAY(nsapr, GICState, GIC_NR_APRS, GIC_NCPU), VMSTATE_END_OF_LIST() } }; diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 899db3d..f7d33a5 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -106,6 +106,7 @@ typedef struct GICState { * the GIC. */ uint32_t apr[GIC_NR_APRS][GIC_NCPU]; + uint32_t nsapr[GIC_NR_APRS][GIC_NCPU]; uint32_t num_cpu;