|
@@ -370,9 +370,45 @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
|
|
return value;
|
|
return value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * Tell the CPU about any pending virtual interrupts.
|
|
|
|
+ * This should only be called for changes that affect the
|
|
|
|
+ * vIRQ and vFIQ status and do not change the maintenance
|
|
|
|
+ * interrupt status. This means that unlike gicv3_cpuif_virt_update()
|
|
|
|
+ * this function won't recursively call back into the GIC code.
|
|
|
|
+ * The main use of this is when the redistributor has changed the
|
|
|
|
+ * highest priority pending virtual LPI.
|
|
|
|
+ */
|
|
|
|
+ int idx;
|
|
|
|
+ int irqlevel = 0;
|
|
|
|
+ int fiqlevel = 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
|
|
|
|
+ qemu_set_irq(cs->parent_vfiq, fiqlevel);
|
|
|
|
+ qemu_set_irq(cs->parent_virq, irqlevel);
|
|
|
|
+}
|
|
|
|
+
|
|
static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
|
|
static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
|
|
{
|
|
{
|
|
- /* Tell the CPU about any pending virtual interrupts or
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Tell the CPU about any pending virtual interrupts or
|
|
* maintenance interrupts, following a change to the state
|
|
* maintenance interrupts, following a change to the state
|
|
* of the CPU interface relevant to virtual interrupts.
|
|
* of the CPU interface relevant to virtual interrupts.
|
|
*
|
|
*
|
|
@@ -389,37 +425,17 @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
|
|
* naturally as a result of there being no architectural
|
|
* naturally as a result of there being no architectural
|
|
* linkage between the physical and virtual GIC logic.
|
|
* linkage between the physical and virtual GIC logic.
|
|
*/
|
|
*/
|
|
- int idx;
|
|
|
|
- int irqlevel = 0;
|
|
|
|
- int fiqlevel = 0;
|
|
|
|
- int maintlevel = 0;
|
|
|
|
ARMCPU *cpu = ARM_CPU(cs->cpu);
|
|
ARMCPU *cpu = ARM_CPU(cs->cpu);
|
|
|
|
+ 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;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ gicv3_cpuif_virt_irq_fiq_update(cs);
|
|
|
|
|
|
if ((cs->ich_hcr_el2 & ICH_HCR_EL2_EN) &&
|
|
if ((cs->ich_hcr_el2 & ICH_HCR_EL2_EN) &&
|
|
maintenance_interrupt_state(cs) != 0) {
|
|
maintenance_interrupt_state(cs) != 0) {
|
|
maintlevel = 1;
|
|
maintlevel = 1;
|
|
}
|
|
}
|
|
|
|
|
|
- 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);
|
|
|
|
|
|
+ trace_gicv3_cpuif_virt_set_maint_irq(gicv3_redist_affid(cs), maintlevel);
|
|
qemu_set_irq(cpu->gicv3_maintenance_interrupt, maintlevel);
|
|
qemu_set_irq(cpu->gicv3_maintenance_interrupt, maintlevel);
|
|
}
|
|
}
|
|
|
|
|