]> Git Repo - qemu.git/blobdiff - hw/intc/arm_gicv3_cpuif.c
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20170717-pull-request' into...
[qemu.git] / hw / intc / arm_gicv3_cpuif.c
index e0690825d0855e61d179cf2ff49e190a9f256f64..5cbafaf497583a7973b4c2e36cdb14e846007fe9 100644 (file)
 
 #include "qemu/osdep.h"
 #include "qemu/bitops.h"
+#include "qemu/main-loop.h"
 #include "trace.h"
 #include "gicv3_internal.h"
 #include "cpu.h"
 
+void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
+{
+    ARMCPU *arm_cpu = ARM_CPU(cpu);
+    CPUARMState *env = &arm_cpu->env;
+
+    env->gicv3state = (void *)s;
+};
+
 static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
 {
     /* Given the CPU, find the right GICv3CPUState struct.
@@ -203,6 +212,90 @@ static int hppvi_index(GICv3CPUState *cs)
     return idx;
 }
 
+static uint32_t icv_gprio_mask(GICv3CPUState *cs, int group)
+{
+    /* Return a mask word which clears the subpriority bits from
+     * a priority value for a virtual interrupt in the specified group.
+     * This depends on the VBPR value.
+     * If using VBPR0 then:
+     *  a BPR of 0 means the group priority bits are [7:1];
+     *  a BPR of 1 means they are [7:2], and so on down to
+     *  a BPR of 7 meaning no group priority bits at all.
+     * If using VBPR1 then:
+     *  a BPR of 0 is impossible (the minimum value is 1)
+     *  a BPR of 1 means the group priority bits are [7:1];
+     *  a BPR of 2 means they are [7:2], and so on down to
+     *  a BPR of 7 meaning the group priority is [7].
+     *
+     * Which BPR to use depends on the group of the interrupt and
+     * the current ICH_VMCR_EL2.VCBPR settings.
+     *
+     * This corresponds to the VGroupBits() pseudocode.
+     */
+    int bpr;
+
+    if (group == GICV3_G1NS && cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) {
+        group = GICV3_G0;
+    }
+
+    bpr = read_vbpr(cs, group);
+    if (group == GICV3_G1NS) {
+        assert(bpr > 0);
+        bpr--;
+    }
+
+    return ~0U << (bpr + 1);
+}
+
+static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
+{
+    /* Return true if we can signal this virtual interrupt defined by
+     * the given list register value; see the pseudocode functions
+     * CanSignalVirtualInterrupt and CanSignalVirtualInt.
+     * Compare also icc_hppi_can_preempt() which is the non-virtual
+     * equivalent of these checks.
+     */
+    int grp;
+    uint32_t mask, prio, rprio, vpmr;
+
+    if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) {
+        /* Virtual interface disabled */
+        return false;
+    }
+
+    /* We don't need to check that this LR is in Pending state because
+     * that has already been done in hppvi_index().
+     */
+
+    prio = ich_lr_prio(lr);
+    vpmr = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
+                     ICH_VMCR_EL2_VPMR_LENGTH);
+
+    if (prio >= vpmr) {
+        /* Priority mask masks this interrupt */
+        return false;
+    }
+
+    rprio = ich_highest_active_virt_prio(cs);
+    if (rprio == 0xff) {
+        /* No running interrupt so we can preempt */
+        return true;
+    }
+
+    grp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+    mask = icv_gprio_mask(cs, grp);
+
+    /* We only preempt a running interrupt if the pending interrupt's
+     * group priority is sufficient (the subpriorities are not considered).
+     */
+    if ((prio & mask) < (rprio & mask)) {
+        return true;
+    }
+
+    return false;
+}
+
 static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
                                                 uint32_t *misr)
 {
@@ -285,6 +378,53 @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
 
 static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
 {
+    /* Tell the CPU about any pending virtual interrupts or
+     * maintenance interrupts, following a change to the state
+     * of the CPU interface relevant to virtual interrupts.
+     *
+     * CAUTION: this function will call qemu_set_irq() on the
+     * CPU maintenance IRQ line, which is typically wired up
+     * to the GIC as a per-CPU interrupt. This means that it
+     * will recursively call back into the GIC code via
+     * gicv3_redist_set_irq() and thus into the CPU interface code's
+     * gicv3_cpuif_update(). It is therefore important that this
+     * function is only called as the final action of a CPU interface
+     * register write implementation, after all the GIC state
+     * fields have been updated. gicv3_cpuif_update() also must
+     * not cause this function to be called, but that happens
+     * naturally as a result of there being no architectural
+     * linkage between the physical and virtual GIC logic.
+     */
+    int idx;
+    int irqlevel = 0;
+    int fiqlevel = 0;
+    int maintlevel = 0;
+
+    idx = hppvi_index(cs);
+    trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx);
+    if (idx >= 0) {
+        uint64_t lr = cs->ich_lr_el2[idx];
+
+        if (icv_hppi_can_preempt(cs, lr)) {
+            /* Virtual interrupts are simple: G0 are always FIQ, and G1 IRQ */
+            if (lr & ICH_LR_EL2_GROUP) {
+                irqlevel = 1;
+            } else {
+                fiqlevel = 1;
+            }
+        }
+    }
+
+    if (cs->ich_hcr_el2 & ICH_HCR_EL2_EN) {
+        maintlevel = maintenance_interrupt_state(cs);
+    }
+
+    trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel,
+                                    irqlevel, maintlevel);
+
+    qemu_set_irq(cs->parent_vfiq, fiqlevel);
+    qemu_set_irq(cs->parent_virq, irqlevel);
+    qemu_set_irq(cs->maintenance_irq, maintlevel);
 }
 
 static uint64_t icv_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -480,6 +620,53 @@ static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri)
     return value;
 }
 
+static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
+{
+    /* Activate the interrupt in the specified list register
+     * by moving it from Pending to Active state, and update the
+     * Active Priority Registers.
+     */
+    uint32_t mask = icv_gprio_mask(cs, grp);
+    int prio = ich_lr_prio(cs->ich_lr_el2[idx]) & mask;
+    int aprbit = prio >> (8 - cs->vprebits);
+    int regno = aprbit / 32;
+    int regbit = aprbit % 32;
+
+    cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+    cs->ich_lr_el2[idx] |= ICH_LR_EL2_STATE_ACTIVE_BIT;
+    cs->ich_apr[grp][regno] |= (1 << regbit);
+}
+
+static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
+    int idx = hppvi_index(cs);
+    uint64_t intid = INTID_SPURIOUS;
+
+    if (idx >= 0) {
+        uint64_t lr = cs->ich_lr_el2[idx];
+        int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+        if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
+            intid = ich_lr_vintid(lr);
+            if (intid < INTID_SECURE) {
+                icv_activate_irq(cs, idx, grp);
+            } else {
+                /* Interrupt goes from Pending to Invalid */
+                cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+                /* We will now return the (bogus) ID from the list register,
+                 * as per the pseudocode.
+                 */
+            }
+        }
+    }
+
+    trace_gicv3_icv_iar_read(ri->crm == 8 ? 0 : 1,
+                             gicv3_redist_affid(cs), intid);
+    return intid;
+}
+
 static int icc_highest_active_prio(GICv3CPUState *cs)
 {
     /* Calculate the current running priority based on the set bits
@@ -504,20 +691,37 @@ static uint32_t icc_gprio_mask(GICv3CPUState *cs, int group)
 {
     /* Return a mask word which clears the subpriority bits from
      * a priority value for an interrupt in the specified group.
-     * This depends on the BPR value:
+     * This depends on the BPR value. For CBPR0 (S or NS):
      *  a BPR of 0 means the group priority bits are [7:1];
      *  a BPR of 1 means they are [7:2], and so on down to
      *  a BPR of 7 meaning no group priority bits at all.
+     * For CBPR1 NS:
+     *  a BPR of 0 is impossible (the minimum value is 1)
+     *  a BPR of 1 means the group priority bits are [7:1];
+     *  a BPR of 2 means they are [7:2], and so on down to
+     *  a BPR of 7 meaning the group priority is [7].
+     *
      * Which BPR to use depends on the group of the interrupt and
      * the current ICC_CTLR.CBPR settings.
+     *
+     * This corresponds to the GroupBits() pseudocode.
      */
+    int bpr;
+
     if ((group == GICV3_G1 && cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR) ||
         (group == GICV3_G1NS &&
          cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) {
         group = GICV3_G0;
     }
 
-    return ~0U << ((cs->icc_bpr[group] & 7) + 1);
+    bpr = cs->icc_bpr[group] & 7;
+
+    if (group == GICV3_G1NS) {
+        assert(bpr > 0);
+        bpr--;
+    }
+
+    return ~0U << (bpr + 1);
 }
 
 static bool icc_no_enabled_hppi(GICv3CPUState *cs)
@@ -572,6 +776,8 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
     ARMCPU *cpu = ARM_CPU(cs->cpu);
     CPUARMState *env = &cpu->env;
 
+    g_assert(qemu_mutex_iothread_locked());
+
     trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq,
                              cs->hppi.grp, cs->hppi.prio);
 
@@ -773,6 +979,10 @@ static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri)
     GICv3CPUState *cs = icc_cs_from_env(env);
     uint64_t intid;
 
+    if (icv_access(env, HCR_FMO)) {
+        return icv_iar_read(env, ri);
+    }
+
     if (!icc_hppi_can_preempt(cs)) {
         intid = INTID_SPURIOUS;
     } else {
@@ -792,6 +1002,10 @@ static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
     GICv3CPUState *cs = icc_cs_from_env(env);
     uint64_t intid;
 
+    if (icv_access(env, HCR_IMO)) {
+        return icv_iar_read(env, ri);
+    }
+
     if (!icc_hppi_can_preempt(cs)) {
         intid = INTID_SPURIOUS;
     } else {
@@ -956,6 +1170,48 @@ static void icv_increment_eoicount(GICv3CPUState *cs)
                                 ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1);
 }
 
+static int icv_drop_prio(GICv3CPUState *cs)
+{
+    /* Drop the priority of the currently active virtual interrupt
+     * (favouring group 0 if there is a set active bit at
+     * the same priority for both group 0 and group 1).
+     * Return the priority value for the bit we just cleared,
+     * or 0xff if no bits were set in the AP registers at all.
+     * Note that though the ich_apr[] are uint64_t only the low
+     * 32 bits are actually relevant.
+     */
+    int i;
+    int aprmax = 1 << (cs->vprebits - 5);
+
+    assert(aprmax <= ARRAY_SIZE(cs->ich_apr[0]));
+
+    for (i = 0; i < aprmax; i++) {
+        uint64_t *papr0 = &cs->ich_apr[GICV3_G0][i];
+        uint64_t *papr1 = &cs->ich_apr[GICV3_G1NS][i];
+        int apr0count, apr1count;
+
+        if (!*papr0 && !*papr1) {
+            continue;
+        }
+
+        /* We can't just use the bit-twiddling hack icc_drop_prio() does
+         * because we need to return the bit number we cleared so
+         * it can be compared against the list register's priority field.
+         */
+        apr0count = ctz32(*papr0);
+        apr1count = ctz32(*papr1);
+
+        if (apr0count <= apr1count) {
+            *papr0 &= *papr0 - 1;
+            return (apr0count + i * 32) << (icv_min_vbpr(cs) + 1);
+        } else {
+            *papr1 &= *papr1 - 1;
+            return (apr1count + i * 32) << (icv_min_vbpr(cs) + 1);
+        }
+    }
+    return 0xff;
+}
+
 static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
@@ -989,6 +1245,57 @@ static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
     gicv3_cpuif_virt_update(cs);
 }
 
+static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    /* End of Interrupt */
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int irq = value & 0xffffff;
+    int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
+    int idx, dropprio;
+
+    trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
+                               gicv3_redist_affid(cs), value);
+
+    if (irq >= cs->gic->num_irq) {
+        /* Also catches special interrupt numbers and LPIs */
+        return;
+    }
+
+    /* We implement the IMPDEF choice of "drop priority before doing
+     * error checks" (because that lets us avoid scanning the AP
+     * registers twice).
+     */
+    dropprio = icv_drop_prio(cs);
+    if (dropprio == 0xff) {
+        /* No active interrupt. It is CONSTRAINED UNPREDICTABLE
+         * whether the list registers are checked in this
+         * situation; we choose not to.
+         */
+        return;
+    }
+
+    idx = icv_find_active(cs, irq);
+
+    if (idx < 0) {
+        /* No valid list register corresponding to EOI ID */
+        icv_increment_eoicount(cs);
+    } else {
+        uint64_t lr = cs->ich_lr_el2[idx];
+        int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+        int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
+
+        if (thisgrp == grp && lr_gprio == dropprio) {
+            if (!icv_eoi_split(env, cs)) {
+                /* Priority drop and deactivate not split: deactivate irq now */
+                icv_deactivate_irq(cs, idx);
+            }
+        }
+    }
+
+    gicv3_cpuif_virt_update(cs);
+}
+
 static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
                            uint64_t value)
 {
@@ -997,6 +1304,11 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
     int irq = value & 0xffffff;
     int grp;
 
+    if (icv_access(env, ri->crm == 8 ? HCR_FMO : HCR_IMO)) {
+        icv_eoir_write(env, ri, value);
+        return;
+    }
+
     trace_gicv3_icc_eoir_write(ri->crm == 8 ? 0 : 1,
                                gicv3_redist_affid(cs), value);
 
@@ -1110,6 +1422,7 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     GICv3CPUState *cs = icc_cs_from_env(env);
     int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
+    uint64_t minval;
 
     if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) {
         icv_bpr_write(env, ri, value);
@@ -1137,6 +1450,11 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
         return;
     }
 
+    minval = (grp == GICV3_G1NS) ? GIC_MIN_BPR_NS : GIC_MIN_BPR;
+    if (value < minval) {
+        value = minval;
+    }
+
     cs->icc_bpr[grp] = value & 7;
     gicv3_cpuif_update(cs);
 }
@@ -1566,9 +1884,17 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
                                           const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TC) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if ((env->cp15.scr_el3 & (SCR_FIQ | SCR_IRQ)) == (SCR_FIQ | SCR_IRQ)) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) == 0)) {
@@ -1594,13 +1920,47 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
     return r;
 }
 
+static CPAccessResult gicv3_dir_access(CPUARMState *env,
+                                       const ARMCPRegInfo *ri, bool isread)
+{
+    GICv3CPUState *cs = icc_cs_from_env(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TDIR) &&
+        arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
+
+    return gicv3_irqfiq_access(env, ri, isread);
+}
+
+static CPAccessResult gicv3_sgi_access(CPUARMState *env,
+                                       const ARMCPRegInfo *ri, bool isread)
+{
+    if ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) &&
+        arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
+
+    return gicv3_irqfiq_access(env, ri, isread);
+}
+
 static CPAccessResult gicv3_fiq_access(CPUARMState *env,
                                        const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TALL0) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if (env->cp15.scr_el3 & SCR_FIQ) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & HCR_FMO) == 0)) {
@@ -1630,9 +1990,17 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env,
                                        const ARMCPRegInfo *ri, bool isread)
 {
     CPAccessResult r = CP_ACCESS_OK;
+    GICv3CPUState *cs = icc_cs_from_env(env);
+    int el = arm_current_el(env);
+
+    if ((cs->ich_hcr_el2 & ICH_HCR_EL2_TALL1) &&
+        el == 1 && !arm_is_secure_below_el3(env)) {
+        /* Takes priority over a possible EL3 trap */
+        return CP_ACCESS_TRAP_EL2;
+    }
 
     if (env->cp15.scr_el3 & SCR_IRQ) {
-        switch (arm_current_el(env)) {
+        switch (el) {
         case 1:
             if (arm_is_secure_below_el3(env) ||
                 ((env->cp15.hcr_el2 & HCR_IMO) == 0)) {
@@ -1671,11 +2039,7 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
     cs->icc_pmr_el1 = 0;
     cs->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
     cs->icc_bpr[GICV3_G1] = GIC_MIN_BPR;
-    if (arm_feature(env, ARM_FEATURE_EL3)) {
-        cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR_NS;
-    } else {
-        cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR;
-    }
+    cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR_NS;
     memset(cs->icc_apr, 0, sizeof(cs->icc_apr));
     memset(cs->icc_igrpen, 0, sizeof(cs->icc_igrpen));
     cs->icc_ctlr_el3 = ICC_CTLR_EL3_NDS | ICC_CTLR_EL3_A3V |
@@ -1686,7 +2050,7 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
     cs->ich_hcr_el2 = 0;
     memset(cs->ich_lr_el2, 0, sizeof(cs->ich_lr_el2));
     cs->ich_vmcr_el2 = ICH_VMCR_EL2_VFIQEN |
-        (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR1_SHIFT) |
+        ((icv_min_vbpr(cs) + 1) << ICH_VMCR_EL2_VBPR1_SHIFT) |
         (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR0_SHIFT);
 }
 
@@ -1788,7 +2152,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
     { .name = "ICC_DIR_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 1,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_dir_access,
       .writefn = icc_dir_write,
     },
     { .name = "ICC_RPR_EL1", .state = ARM_CP_STATE_BOTH,
@@ -1800,37 +2164,37 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
     { .name = "ICC_SGI1R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 5,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi1r_write,
     },
     { .name = "ICC_SGI1R",
       .cp = 15, .opc1 = 0, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi1r_write,
     },
     { .name = "ICC_ASGI1R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 6,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_asgi1r_write,
     },
     { .name = "ICC_ASGI1R",
       .cp = 15, .opc1 = 1, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_asgi1r_write,
     },
     { .name = "ICC_SGI0R_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 7,
       .type = ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi0r_write,
     },
     { .name = "ICC_SGI0R",
       .cp = 15, .opc1 = 2, .crm = 12,
       .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
-      .access = PL1_W, .accessfn = gicv3_irqfiq_access,
+      .access = PL1_W, .accessfn = gicv3_sgi_access,
       .writefn = icc_sgi0r_write,
     },
     { .name = "ICC_IAR1_EL1", .state = ARM_CP_STATE_BOTH,
@@ -2113,7 +2477,7 @@ static uint64_t ich_elrsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
         uint64_t lr = cs->ich_lr_el2[i];
 
         if ((lr & ICH_LR_EL2_STATE_MASK) == 0 &&
-            ((lr & ICH_LR_EL2_HW) == 1 || (lr & ICH_LR_EL2_EOI) == 0)) {
+            ((lr & ICH_LR_EL2_HW) != 0 || (lr & ICH_LR_EL2_EOI) == 0)) {
             value |= (1 << i);
         }
     }
@@ -2260,6 +2624,8 @@ void gicv3_init_cpuif(GICv3State *s)
             && cpu->gic_num_lrs) {
             int j;
 
+            cs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
+
             cs->num_list_regs = cpu->gic_num_lrs;
             cs->vpribits = cpu->gic_vpribits;
             cs->vprebits = cpu->gic_vprebits;
This page took 0.039777 seconds and 4 git commands to generate.