aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/intc/arm_gic.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 41141fee53..94d5982e2a 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -74,6 +74,11 @@ static inline bool gic_has_groups(GICState *s)
return s->revision == 2 || s->security_extn;
}
+static inline bool gic_cpu_ns_access(GICState *s, int cpu, MemTxAttrs attrs)
+{
+ return !gic_is_vcpu(cpu) && s->security_extn && !attrs.secure;
+}
+
/* TODO: Many places that call this routine could be optimized. */
/* Update interrupt status after enabled or pending bits have been changed. */
static void gic_update(GICState *s)
@@ -221,7 +226,7 @@ static uint16_t gic_get_current_pending_irq(GICState *s, int cpu,
/* On a GIC without the security extensions, reading this register
* behaves in the same way as a secure access to a GIC with them.
*/
- bool secure = !s->security_extn || attrs.secure;
+ bool secure = !gic_cpu_ns_access(s, cpu, attrs);
if (group == 0 && !secure) {
/* Group0 interrupts hidden from Non-secure access */
@@ -428,7 +433,7 @@ static uint32_t gic_dist_get_priority(GICState *s, int cpu, int irq,
static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
MemTxAttrs attrs)
{
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
if (s->priority_mask[cpu] & 0x80) {
/* Priority Mask in upper half */
pmask = 0x80 | (pmask >> 1);
@@ -444,7 +449,7 @@ static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs)
{
uint32_t pmask = s->priority_mask[cpu];
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
if (pmask & 0x80) {
/* Priority Mask in upper half, return Non-secure view */
pmask = (pmask << 1) & 0xff;
@@ -460,7 +465,7 @@ static uint32_t gic_get_cpu_control(GICState *s, int cpu, MemTxAttrs attrs)
{
uint32_t ret = s->cpu_ctlr[cpu];
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
/* Construct the NS banked view of GICC_CTLR from the correct
* bits of the S banked view. We don't need to move the bypass
* control bits because we don't implement that (IMPDEF) part
@@ -476,7 +481,7 @@ static void gic_set_cpu_control(GICState *s, int cpu, uint32_t value,
{
uint32_t mask;
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
/* The NS view can only write certain bits in the register;
* the rest are unchanged
*/
@@ -507,7 +512,7 @@ static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs)
return 0xff;
}
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
if (s->running_priority[cpu] & 0x80) {
/* Running priority in upper half of range: return the Non-secure
* view of the priority.
@@ -531,7 +536,7 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
/* Before GICv2 prio-drop and deactivate are not separable */
return false;
}
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE_NS;
}
return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE;
@@ -563,7 +568,7 @@ static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
return;
}
- if (s->security_extn && !attrs.secure && !group) {
+ if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
DPRINTF("Non-secure DI for Group0 interrupt %d ignored\n", irq);
return;
}
@@ -605,7 +610,7 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
group = gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm);
- if (s->security_extn && !attrs.secure && !group) {
+ if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq);
return;
}
@@ -1281,7 +1286,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
*data = gic_get_priority_mask(s, cpu, attrs);
break;
case 0x08: /* Binary Point */
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
/* NS view of BPR when CBPR is 1 */
*data = MIN(s->bpr[cpu] + 1, 7);
@@ -1308,7 +1313,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
* With security extensions, secure access: ABPR (alias of NS BPR)
* With security extensions, nonsecure access: RAZ/WI
*/
- if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
+ if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
*data = 0;
} else {
*data = s->abpr[cpu];
@@ -1320,7 +1325,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
if (regno >= GIC_NR_APRS || s->revision != 2) {
*data = 0;
- } else if (s->security_extn && !attrs.secure) {
+ } else if (gic_cpu_ns_access(s, cpu, attrs)) {
/* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
*data = gic_apr_ns_view(s, regno, cpu);
} else {
@@ -1333,7 +1338,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
int regno = (offset - 0xe0) / 4;
if (regno >= GIC_NR_APRS || s->revision != 2 || !gic_has_groups(s) ||
- (s->security_extn && !attrs.secure)) {
+ gic_cpu_ns_access(s, cpu, attrs)) {
*data = 0;
} else {
*data = s->nsapr[regno][cpu];
@@ -1360,7 +1365,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
gic_set_priority_mask(s, cpu, value, attrs);
break;
case 0x08: /* Binary Point */
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
/* WI when CBPR is 1 */
return MEMTX_OK;
@@ -1375,7 +1380,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
gic_complete_irq(s, cpu, value & 0x3ff, attrs);
return MEMTX_OK;
case 0x1c: /* Aliased Binary Point */
- if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
+ if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
/* unimplemented, or NS access: RAZ/WI */
return MEMTX_OK;
} else {
@@ -1389,7 +1394,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
if (regno >= GIC_NR_APRS || s->revision != 2) {
return MEMTX_OK;
}
- if (s->security_extn && !attrs.secure) {
+ if (gic_cpu_ns_access(s, cpu, attrs)) {
/* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
gic_apr_write_ns_view(s, regno, cpu, value);
} else {
@@ -1404,7 +1409,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
if (regno >= GIC_NR_APRS || s->revision != 2) {
return MEMTX_OK;
}
- if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
+ if (!gic_has_groups(s) || (gic_cpu_ns_access(s, cpu, attrs))) {
return MEMTX_OK;
}
s->nsapr[regno][cpu] = value;