[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH v5 11/20] intc/arm_gic: Implement virtualization exten
From: |
Luc Michel |
Subject: |
[Qemu-arm] [PATCH v5 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq |
Date: |
Fri, 27 Jul 2018 11:54:12 +0200 |
Implement virtualization extensions in the gic_acknowledge_irq()
function. This function changes the state of the highest priority IRQ
from pending to active.
When the current CPU is a vCPU, modifying the state of an IRQ modifies
the corresponding LR entry. However if we clear the pending flag before
setting the active one, we lose track of the LR entry as it becomes
invalid. The next call to gic_get_lr_entry() will fail.
To overcome this issue, we call gic_activate_irq() before
gic_clear_pending(). This does not change the general behaviour of
gic_acknowledge_irq.
We also move the SGI case in gic_clear_pending_sgi() to enhance
code readability as the virtualization extensions support adds a if-else
level.
Signed-off-by: Luc Michel <address@hidden>
Reviewed-by: Peter Maydell <address@hidden>
---
hw/intc/arm_gic.c | 52 ++++++++++++++++++++++++++++++-----------------
1 file changed, 33 insertions(+), 19 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index de73dc9f54..d80acde989 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -363,21 +363,48 @@ static void gic_drop_prio(GICState *s, int cpu, int group)
}
s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu);
}
+static inline uint32_t gic_clear_pending_sgi(GICState *s, int irq, int cpu)
+{
+ int src;
+ uint32_t ret;
+
+ if (!gic_is_vcpu(cpu)) {
+ /* Lookup the source CPU for the SGI and clear this in the
+ * sgi_pending map. Return the src and clear the overall pending
+ * state on this CPU if the SGI is not pending from any CPUs.
+ */
+ assert(s->sgi_pending[irq][cpu] != 0);
+ src = ctz32(s->sgi_pending[irq][cpu]);
+ s->sgi_pending[irq][cpu] &= ~(1 << src);
+ if (s->sgi_pending[irq][cpu] == 0) {
+ gic_clear_pending(s, irq, cpu);
+ }
+ ret = irq | ((src & 0x7) << 10);
+ } else {
+ uint32_t *lr_entry = gic_get_lr_entry(s, irq, cpu);
+ src = GICH_LR_CPUID(*lr_entry);
+
+ gic_clear_pending(s, irq, cpu);
+ ret = irq | (src << 10);
+ }
+
+ return ret;
+}
+
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
{
- int ret, irq, src;
- int cm = 1 << cpu;
+ int ret, irq;
/* gic_get_current_pending_irq() will return 1022 or 1023 appropriately
* for the case where this GIC supports grouping and the pending interrupt
* is in the wrong group.
*/
irq = gic_get_current_pending_irq(s, cpu, attrs);
- trace_gic_acknowledge_irq(cpu, irq);
+ trace_gic_acknowledge_irq(gic_get_vcpu_real_id(cpu), irq);
if (irq >= GIC_MAXIRQ) {
DPRINTF("ACK, no pending interrupt or it is hidden: %d\n", irq);
return irq;
}
@@ -385,40 +412,27 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu,
MemTxAttrs attrs)
if (gic_get_priority(s, irq, cpu) >= s->running_priority[cpu]) {
DPRINTF("ACK, pending interrupt (%d) has insufficient priority\n",
irq);
return 1023;
}
+ gic_activate_irq(s, cpu, irq);
+
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.
*/
gic_clear_pending(s, irq, cpu);
ret = irq;
} else {
if (irq < GIC_NR_SGIS) {
- /* Lookup the source CPU for the SGI and clear this in the
- * sgi_pending map. Return the src and clear the overall pending
- * state on this CPU if the SGI is not pending from any CPUs.
- */
- assert(s->sgi_pending[irq][cpu] != 0);
- src = ctz32(s->sgi_pending[irq][cpu]);
- s->sgi_pending[irq][cpu] &= ~(1 << src);
- if (s->sgi_pending[irq][cpu] == 0) {
- gic_clear_pending(s, irq, cpu);
- }
- ret = irq | ((src & 0x7) << 10);
+ ret = gic_clear_pending_sgi(s, irq, cpu);
} else {
- /* Clear pending state for both level and edge triggered
- * interrupts. (level triggered interrupts with an active line
- * remain pending, see gic_test_pending)
- */
gic_clear_pending(s, irq, cpu);
ret = irq;
}
}
- gic_activate_irq(s, cpu, irq);
gic_update(s);
DPRINTF("ACK %d\n", irq);
return ret;
}
--
2.18.0
- [Qemu-arm] [PATCH v5 02/20] intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers, (continued)
- [Qemu-arm] [PATCH v5 02/20] intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 04/20] vmstate.h: Provide VMSTATE_UINT16_SUB_ARRAY, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 12/20] intc/arm_gic: Implement virtualization extensions in gic_(deactivate|complete_irq), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 03/20] intc/arm_gic: Remove some dead code and put some functions static, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 06/20] intc/arm_gic: Add virtual interface register definitions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq,
Luc Michel <=
- [Qemu-arm] [PATCH v5 14/20] intc/arm_gic: Wire the vCPU interface, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 18/20] intc/arm_gic: Improve traces, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 17/20] intc/arm_gic: Implement maintenance interrupt generation, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 20/20] arm/virt: Add support for GICv2 virtualization extensions, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 19/20] xlnx-zynqmp: Improve GIC wiring and MMIO mapping, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio), Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 16/20] intc/arm_gic: Implement gic_update_virt() function, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 15/20] intc/arm_gic: Implement the virtual interface registers, Luc Michel, 2018/07/27
- [Qemu-arm] [PATCH v5 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions, Luc Michel, 2018/07/27