#include "qemu/log.h"
#include "trace.h"
-//#define DEBUG_GIC
+/* #define DEBUG_GIC */
#ifdef DEBUG_GIC
-#define DPRINTF(fmt, ...) \
-do { fprintf(stderr, "arm_gic: " fmt , ## __VA_ARGS__); } while (0)
+#define DEBUG_GIC_GATE 1
#else
-#define DPRINTF(fmt, ...) do {} while(0)
+#define DEBUG_GIC_GATE 0
#endif
+#define DPRINTF(fmt, ...) do { \
+ if (DEBUG_GIC_GATE) { \
+ fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
static const uint8_t gic_id_11mpcore[] = {
0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1
};
return;
}
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
gic_set_irq_11mpcore(s, irq, level, cm, target);
} else {
gic_set_irq_generic(s, irq, level, cm, target);
return 1023;
}
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
/* Clear pending flags for both level and edge triggered interrupts.
* Level triggered IRQs will be reasserted once they become inactive.
*/
return; /* No active IRQ. */
}
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
/* Mark level triggered interrupts as pending if they are still
raised. */
if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
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);
}
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);
}
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);
}
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))
} else if (offset < 0xf10) {
goto bad_reg;
} else if (offset < 0xf30) {
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
goto bad_reg;
}
/* 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) {
case 2:
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
break;
- case REV_NVIC:
- /* Shouldn't be able to get here */
- abort();
default:
res = 0;
}
(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);
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);
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));
}
}
}
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. */
if (irq < GIC_NR_SGIS)
value |= 0xaa;
for (i = 0; i < 4; i++) {
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ 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) {
if (value & (1 << (i * 2))) {
GIC_SET_MODEL(irq + i);
} else {
goto bad_reg;
} else if (offset < 0xf20) {
/* GICD_CPENDSGIRn */
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
goto bad_reg;
}
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 */
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ if (s->revision == REV_11MPCORE) {
goto bad_reg;
}
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;
}