diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 492b2421ab..7b4f3fb81a 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -56,17 +56,42 @@ static const uint8_t gic_id_gicv2[] = {
     0x04, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x2b, 0x00, 0x0d, 0xf0, 0x05, 0xb1
 };
 
-static inline int gic_get_current_cpu(GICState *s)
+
+/*
+ * The GIC should only be accessed by the CPU so if it is not we
+ * should fail the transaction (it would either be a bug in how we've
+ * wired stuff up, a limitation of the translator or the guest doing
+ * something weird like programming a DMA master to write to the MMIO
+ * region).
+ *
+ * Note the cpu_index is global and we currently don't have any models
+ * with multiple SoC's with different CPUs. However if we did we would
+ * need to transform the cpu_index into the socket core.
+ */
+typedef struct {
+    bool valid;
+    int cpu_index;
+} GicCPU;
+
+static inline GicCPU gic_get_current_cpu(GICState *s, MemTxAttrs attrs)
 {
-    if (!qtest_enabled() && s->num_cpu > 1) {
-        return current_cpu->cpu_index;
+    if (attrs.requester_type != MTRT_CPU) {
+        qemu_log_mask(LOG_UNIMP | LOG_GUEST_ERROR,
+                      "%s: saw non-CPU transaction", __func__);
+        return (GicCPU) { .valid = false };
     }
-    return 0;
+    g_assert(attrs.requester_id < s->num_cpu);
+
+    return (GicCPU) { .valid = true, .cpu_index = attrs.requester_id };
 }
 
-static inline int gic_get_current_vcpu(GICState *s)
+static inline GicCPU gic_get_current_vcpu(GICState *s, MemTxAttrs attrs)
 {
-    return gic_get_current_cpu(s) + GIC_NCPU;
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+    if (cpu.valid) {
+        cpu.cpu_index += GIC_NCPU;
+    }
+    return cpu;
 }
 
 /* Return true if this GIC config has interrupt groups, which is
@@ -941,17 +966,14 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
     gic_update(s);
 }
 
-static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
+static uint32_t gic_dist_readb(GICState *s, int cpu, hwaddr offset, MemTxAttrs attrs)
 {
-    GICState *s = (GICState *)opaque;
     uint32_t res;
     int irq;
     int i;
-    int cpu;
     int cm;
     int mask;
 
-    cpu = gic_get_current_cpu(s);
     cm = 1 << cpu;
     if (offset < 0x100) {
         if (offset == 0) {      /* GICD_CTLR */
@@ -1152,19 +1174,26 @@ bad_reg:
 static MemTxResult gic_dist_read(void *opaque, hwaddr offset, uint64_t *data,
                                  unsigned size, MemTxAttrs attrs)
 {
+    GICState *s = (GICState *)opaque;
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+
+    if (!cpu.valid) {
+        return MEMTX_ACCESS_ERROR;
+    }
+
     switch (size) {
     case 1:
-        *data = gic_dist_readb(opaque, offset, attrs);
+        *data = gic_dist_readb(s, cpu.cpu_index, offset, attrs);
         break;
     case 2:
-        *data = gic_dist_readb(opaque, offset, attrs);
-        *data |= gic_dist_readb(opaque, offset + 1, attrs) << 8;
+        *data = gic_dist_readb(s, cpu.cpu_index, offset, attrs);
+        *data |= gic_dist_readb(s, cpu.cpu_index, offset + 1, attrs) << 8;
         break;
     case 4:
-        *data = gic_dist_readb(opaque, offset, attrs);
-        *data |= gic_dist_readb(opaque, offset + 1, attrs) << 8;
-        *data |= gic_dist_readb(opaque, offset + 2, attrs) << 16;
-        *data |= gic_dist_readb(opaque, offset + 3, attrs) << 24;
+        *data = gic_dist_readb(s, cpu.cpu_index, offset, attrs);
+        *data |= gic_dist_readb(s, cpu.cpu_index, offset + 1, attrs) << 8;
+        *data |= gic_dist_readb(s, cpu.cpu_index, offset + 2, attrs) << 16;
+        *data |= gic_dist_readb(s, cpu.cpu_index, offset + 3, attrs) << 24;
         break;
     default:
         return MEMTX_ERROR;
@@ -1174,15 +1203,12 @@ static MemTxResult gic_dist_read(void *opaque, hwaddr offset, uint64_t *data,
     return MEMTX_OK;
 }
 
-static void gic_dist_writeb(void *opaque, hwaddr offset,
+static void gic_dist_writeb(GICState *s, int cpu, hwaddr offset,
                             uint32_t value, MemTxAttrs attrs)
 {
-    GICState *s = (GICState *)opaque;
     int irq;
     int i;
-    int cpu;
 
-    cpu = gic_get_current_cpu(s);
     if (offset < 0x100) {
         if (offset == 0) {
             if (s->security_extn && !attrs.secure) {
@@ -1459,24 +1485,21 @@ bad_reg:
                   "gic_dist_writeb: Bad offset %x\n", (int)offset);
 }
 
-static void gic_dist_writew(void *opaque, hwaddr offset,
+static void gic_dist_writew(GICState *s, int cpu, hwaddr offset,
                             uint32_t value, MemTxAttrs attrs)
 {
-    gic_dist_writeb(opaque, offset, value & 0xff, attrs);
-    gic_dist_writeb(opaque, offset + 1, value >> 8, attrs);
+    gic_dist_writeb(s, cpu, offset, value & 0xff, attrs);
+    gic_dist_writeb(s, cpu, offset + 1, value >> 8, attrs);
 }
 
-static void gic_dist_writel(void *opaque, hwaddr offset,
+static void gic_dist_writel(GICState *s, int cpu, hwaddr offset,
                             uint32_t value, MemTxAttrs attrs)
 {
-    GICState *s = (GICState *)opaque;
     if (offset == 0xf00) {
-        int cpu;
         int irq;
         int mask;
         int target_cpu;
 
-        cpu = gic_get_current_cpu(s);
         irq = value & 0xf;
         switch ((value >> 24) & 3) {
         case 0:
@@ -1503,24 +1526,31 @@ static void gic_dist_writel(void *opaque, hwaddr offset,
         gic_update(s);
         return;
     }
-    gic_dist_writew(opaque, offset, value & 0xffff, attrs);
-    gic_dist_writew(opaque, offset + 2, value >> 16, attrs);
+    gic_dist_writew(s, cpu, offset, value & 0xffff, attrs);
+    gic_dist_writew(s, cpu, offset + 2, value >> 16, attrs);
 }
 
 static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data,
                                   unsigned size, MemTxAttrs attrs)
 {
+    GICState *s = (GICState *)opaque;
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+
+    if (!cpu.valid) {
+        return MEMTX_ACCESS_ERROR;
+    }
+
     trace_gic_dist_write(offset, size, data);
 
     switch (size) {
     case 1:
-        gic_dist_writeb(opaque, offset, data, attrs);
+        gic_dist_writeb(s, cpu.cpu_index, offset, data, attrs);
         return MEMTX_OK;
     case 2:
-        gic_dist_writew(opaque, offset, data, attrs);
+        gic_dist_writew(s, cpu.cpu_index, offset, data, attrs);
         return MEMTX_OK;
     case 4:
-        gic_dist_writel(opaque, offset, data, attrs);
+        gic_dist_writel(s, cpu.cpu_index, offset, data, attrs);
         return MEMTX_OK;
     default:
         return MEMTX_ERROR;
@@ -1780,7 +1810,12 @@ static MemTxResult gic_thiscpu_read(void *opaque, hwaddr addr, uint64_t *data,
                                     unsigned size, MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-    return gic_cpu_read(s, gic_get_current_cpu(s), addr, data, attrs);
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+    if (cpu.valid) {
+        return gic_cpu_read(s, cpu.cpu_index, addr, data, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 static MemTxResult gic_thiscpu_write(void *opaque, hwaddr addr,
@@ -1788,7 +1823,12 @@ static MemTxResult gic_thiscpu_write(void *opaque, hwaddr addr,
                                      MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-    return gic_cpu_write(s, gic_get_current_cpu(s), addr, value, attrs);
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+    if (cpu.valid) {
+        return gic_cpu_write(s, cpu.cpu_index, addr, value, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 /* Wrappers to read/write the GIC CPU interface for a specific CPU.
@@ -1817,8 +1857,12 @@ static MemTxResult gic_thisvcpu_read(void *opaque, hwaddr addr, uint64_t *data,
                                     unsigned size, MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-
-    return gic_cpu_read(s, gic_get_current_vcpu(s), addr, data, attrs);
+    GicCPU cpu = gic_get_current_vcpu(s, attrs);
+    if (cpu.valid) {
+        return gic_cpu_read(s, cpu.cpu_index, addr, data, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 static MemTxResult gic_thisvcpu_write(void *opaque, hwaddr addr,
@@ -1826,8 +1870,12 @@ static MemTxResult gic_thisvcpu_write(void *opaque, hwaddr addr,
                                      MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-
-    return gic_cpu_write(s, gic_get_current_vcpu(s), addr, value, attrs);
+    GicCPU cpu = gic_get_current_vcpu(s, attrs);
+    if (cpu.valid) {
+        return gic_cpu_write(s, cpu.cpu_index, addr, value, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 static uint32_t gic_compute_eisr(GICState *s, int cpu, int lr_start)
@@ -1858,9 +1906,8 @@ static uint32_t gic_compute_elrsr(GICState *s, int cpu, int lr_start)
     return ret;
 }
 
-static void gic_vmcr_write(GICState *s, uint32_t value, MemTxAttrs attrs)
+static void gic_vmcr_write(GICState *s, int vcpu, uint32_t value, MemTxAttrs attrs)
 {
-    int vcpu = gic_get_current_vcpu(s);
     uint32_t ctlr;
     uint32_t abpr;
     uint32_t bpr;
@@ -1881,7 +1928,10 @@ static MemTxResult gic_hyp_read(void *opaque, int cpu, hwaddr addr,
                                 uint64_t *data, MemTxAttrs attrs)
 {
     GICState *s = ARM_GIC(opaque);
-    int vcpu = cpu + GIC_NCPU;
+    GicCPU vcpu = gic_get_current_vcpu(s, attrs);
+    if (!vcpu.valid) {
+        return MEMTX_ACCESS_ERROR;
+    }
 
     switch (addr) {
     case A_GICH_HCR: /* Hypervisor Control */
@@ -1898,11 +1948,11 @@ static MemTxResult gic_hyp_read(void *opaque, int cpu, hwaddr addr,
 
     case A_GICH_VMCR: /* Virtual Machine Control */
         *data = FIELD_DP32(0, GICH_VMCR, VMCCtlr,
-                           extract32(s->cpu_ctlr[vcpu], 0, 10));
-        *data = FIELD_DP32(*data, GICH_VMCR, VMABP, s->abpr[vcpu]);
-        *data = FIELD_DP32(*data, GICH_VMCR, VMBP, s->bpr[vcpu]);
+                           extract32(s->cpu_ctlr[vcpu.cpu_index], 0, 10));
+        *data = FIELD_DP32(*data, GICH_VMCR, VMABP, s->abpr[vcpu.cpu_index]);
+        *data = FIELD_DP32(*data, GICH_VMCR, VMBP, s->bpr[vcpu.cpu_index]);
         *data = FIELD_DP32(*data, GICH_VMCR, VMPriMask,
-                           extract32(s->priority_mask[vcpu], 3, 5));
+                           extract32(s->priority_mask[vcpu.cpu_index], 3, 5));
         break;
 
     case A_GICH_MISR: /* Maintenance Interrupt Status */
@@ -1949,7 +1999,10 @@ static MemTxResult gic_hyp_write(void *opaque, int cpu, hwaddr addr,
                                  uint64_t value, MemTxAttrs attrs)
 {
     GICState *s = ARM_GIC(opaque);
-    int vcpu = cpu + GIC_NCPU;
+    GicCPU vcpu = gic_get_current_vcpu(s, attrs);
+    if (!vcpu.valid) {
+        return MEMTX_ACCESS_ERROR;
+    }
 
     trace_gic_hyp_write(addr, value);
 
@@ -1959,12 +2012,13 @@ static MemTxResult gic_hyp_write(void *opaque, int cpu, hwaddr addr,
         break;
 
     case A_GICH_VMCR: /* Virtual Machine Control */
-        gic_vmcr_write(s, value, attrs);
+        gic_vmcr_write(s, vcpu.cpu_index, value, attrs);
         break;
 
     case A_GICH_APR: /* Active Priorities */
         s->h_apr[cpu] = value;
-        s->running_priority[vcpu] = gic_get_prio_from_apr_bits(s, vcpu);
+        s->running_priority[vcpu.cpu_index] =
+            gic_get_prio_from_apr_bits(s, vcpu.cpu_index);
         break;
 
     case A_GICH_LR0 ... A_GICH_LR63: /* List Registers */
@@ -1991,20 +2045,28 @@ static MemTxResult gic_hyp_write(void *opaque, int cpu, hwaddr addr,
 }
 
 static MemTxResult gic_thiscpu_hyp_read(void *opaque, hwaddr addr, uint64_t *data,
-                                    unsigned size, MemTxAttrs attrs)
+                                        unsigned size, MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-
-    return gic_hyp_read(s, gic_get_current_cpu(s), addr, data, attrs);
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+    if (cpu.valid) {
+        return gic_hyp_read(s, cpu.cpu_index, addr, data, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 static MemTxResult gic_thiscpu_hyp_write(void *opaque, hwaddr addr,
-                                     uint64_t value, unsigned size,
-                                     MemTxAttrs attrs)
+                                         uint64_t value, unsigned size,
+                                         MemTxAttrs attrs)
 {
     GICState *s = (GICState *)opaque;
-
-    return gic_hyp_write(s, gic_get_current_cpu(s), addr, value, attrs);
+    GicCPU cpu = gic_get_current_cpu(s, attrs);
+    if (cpu.valid) {
+        return gic_hyp_write(s, cpu.cpu_index, addr, value, attrs);
+    } else {
+        return MEMTX_ACCESS_ERROR;
+    }
 }
 
 static MemTxResult gic_do_hyp_read(void *opaque, hwaddr addr, uint64_t *data,
