From patchwork Thu May 26 14:45:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 68683 Delivered-To: patches@linaro.org Received: by 10.140.92.199 with SMTP id b65csp443177qge; Thu, 26 May 2016 07:46:00 -0700 (PDT) X-Received: by 10.194.120.135 with SMTP id lc7mr9659747wjb.34.1464273960224; Thu, 26 May 2016 07:46:00 -0700 (PDT) Return-Path: Received: from mail-wm0-x231.google.com (mail-wm0-x231.google.com. [2a00:1450:400c:c09::231]) by mx.google.com with ESMTPS id b69si5156687wmf.119.2016.05.26.07.46.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 26 May 2016 07:46:00 -0700 (PDT) Received-SPF: pass (google.com: domain of jens.wiklander@linaro.org designates 2a00:1450:400c:c09::231 as permitted sender) client-ip=2a00:1450:400c:c09::231; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 2a00:1450:400c:c09::231 as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: by mail-wm0-x231.google.com with SMTP id a136so30772697wme.0 for ; Thu, 26 May 2016 07:46:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=ddX2r14JlW1l3UVR0N3HJJBvDIkaE5oUwEYt2NA8rI8=; b=kCGjw56Ur7KlLU9X7jNltcgbDn1n4dleBN+J1ZXq3Kfc5sqRIJbYqscN4hrzc9ECAs TB3fF3cTVgDUMmzXOtZxeNMp9WMT3fNIikV+tVRqHkbnI0O+fxkMxMzphq05yOjTfjaX /HkkXDWM9z+U0H1CLJAUp2iVtnd6JZftmdfFY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=ddX2r14JlW1l3UVR0N3HJJBvDIkaE5oUwEYt2NA8rI8=; b=AmjxNdRS7xsF1NcnLaYU9rMkWPJdsMiAGuYwRwiJShNJ2bPLfRSi6NchMYzxWKbMA5 ks2uZhX+DR31pVwx+qLAdgFU1hO0HQqUOogEDsbwYL0z1P+DqoU9Zc4ulNYxb6bgX7pL /rZXyNznka3kHVUgePPQ8nPCIAPbqrVkU7C7dH9IKJQke7gdKjpKPCfIDcQzSimQslJE t7goTmSPYxTHacCMFwr8CamgHFRvs2KF/w+VEp9qtOGUXqvm+T+0Y3b3ZtwYHLEVXbJg GGU0Py7DuLdUx02WGVU850XChtZzrJ0NSJ8ewdb4R1lkuLh/XWqD2QQ53CfpotmyCTUM +JDg== X-Gm-Message-State: ALyK8tITDG/4/cZ3grIahsGT56MZ7KL/5qVGzWheWU5qR371n5yHtSJUb482O0VqWfs8mHyLR7w= X-Received: by 10.194.158.69 with SMTP id ws5mr9946070wjb.17.1464273959804; Thu, 26 May 2016 07:45:59 -0700 (PDT) Return-Path: Received: from ermac.urgonet (h-84-45.a175.priv.bahnhof.se. [79.136.84.45]) by smtp.gmail.com with ESMTPSA id m3sm14689640wjc.27.2016.05.26.07.45.58 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 26 May 2016 07:45:58 -0700 (PDT) From: Jens Wiklander To: qemu-arm@nongnu.org, qemu-devel@nongnu.org, peter.maydell@linaro.org Cc: Jens Wiklander Subject: [PATCH] hw/intc/gic: RAZ/WI non-sec access to sec interrupts Date: Thu, 26 May 2016 16:45:45 +0200 Message-Id: <1464273945-2055-1-git-send-email-jens.wiklander@linaro.org> X-Mailer: git-send-email 1.9.1 Treat non-secure accesses to registers and bits in registers of secure interrupts as RAZ/WI. Signed-off-by: Jens Wiklander --- hw/intc/arm_gic.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) -- 1.9.1 diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 06a22e0..b30cc91 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -661,6 +661,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs) goto bad_reg; res = 0; for (i = 0; i < 8; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (GIC_TEST_ENABLED(irq + i, cm)) { res |= (1 << i); } @@ -677,6 +682,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs) res = 0; mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK; for (i = 0; i < 8; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (gic_test_pending(s, irq + i, mask)) { res |= (1 << i); } @@ -689,6 +699,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs) res = 0; mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK; for (i = 0; i < 8; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (GIC_TEST_ACTIVE(irq + i, mask)) { res |= (1 << i); } @@ -722,6 +737,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs) goto bad_reg; res = 0; for (i = 0; i < 4; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (GIC_TEST_MODEL(irq + i)) res |= (1 << (i * 2)); if (GIC_TEST_EDGE_TRIGGER(irq + i)) @@ -742,7 +762,12 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs) /* GICD_SPENDSGIRn */ } - res = s->sgi_pending[irq][cpu]; + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq, 1 << cpu)) { + res = 0; /* Ignore Non-secure access of Group0 IRQ */ + } else { + res = s->sgi_pending[irq][cpu]; + } } else if (offset < 0xfd0) { goto bad_reg; } else if (offset < 0x1000) { @@ -862,6 +887,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i); int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK; + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (!GIC_TEST_ENABLED(irq + i, cm)) { DPRINTF("Enabled IRQ %d\n", irq + i); trace_gic_enable_irq(irq + i); @@ -889,6 +919,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, if (value & (1 << i)) { int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK; + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (GIC_TEST_ENABLED(irq + i, cm)) { DPRINTF("Disabled IRQ %d\n", irq + i); trace_gic_disable_irq(irq + i); @@ -907,6 +942,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, for (i = 0; i < 8; i++) { if (value & (1 << i)) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i)); } } @@ -920,6 +960,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, } for (i = 0; i < 8; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + /* ??? This currently clears the pending bit for all CPUs, even for per-CPU interrupts. It's unclear whether this is the corect behavior. */ @@ -960,6 +1005,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, if (irq < GIC_NR_SGIS) value |= 0xaa; for (i = 0; i < 4; i++) { + if (s->security_extn && !attrs.secure && + !GIC_TEST_GROUP(irq + i, 1 << cpu)) { + continue; /* Ignore Non-secure access of Group0 IRQ */ + } + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { if (value & (1 << (i * 2))) { GIC_SET_MODEL(irq + i); @@ -983,9 +1033,12 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, } irq = (offset - 0xf10); - s->sgi_pending[irq][cpu] &= ~value; - if (s->sgi_pending[irq][cpu] == 0) { - GIC_CLEAR_PENDING(irq, 1 << cpu); + if (!s->security_extn || attrs.secure || + GIC_TEST_GROUP(irq, 1 << cpu)) { + s->sgi_pending[irq][cpu] &= ~value; + if (s->sgi_pending[irq][cpu] == 0) { + GIC_CLEAR_PENDING(irq, 1 << cpu); + } } } else if (offset < 0xf30) { /* GICD_SPENDSGIRn */ @@ -994,8 +1047,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, } irq = (offset - 0xf20); - GIC_SET_PENDING(irq, 1 << cpu); - s->sgi_pending[irq][cpu] |= value; + if (!s->security_extn || attrs.secure || + GIC_TEST_GROUP(irq, 1 << cpu)) { + GIC_SET_PENDING(irq, 1 << cpu); + s->sgi_pending[irq][cpu] |= value; + } } else { goto bad_reg; }