[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH v4 11/20] intc/arm_gic: Implement virtualization exten
From: |
Luc Michel |
Subject: |
[Qemu-arm] [PATCH v4 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq |
Date: |
Sat, 14 Jul 2018 19:15:52 +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 60704cabbb..be9e2594d9 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -365,17 +365,44 @@ 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);
@@ -387,6 +414,8 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu,
MemTxAttrs attrs)
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.
@@ -395,28 +424,13 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu,
MemTxAttrs attrs)
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 v4 12/20] intc/arm_gic: Implement virtualization extensions in gic_(deactivate|complete_irq), (continued)
- [Qemu-arm] [PATCH v4 03/20] intc/arm_gic: Remove some dead code and put some functions static, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio), Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write), Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq,
Luc Michel <=
- [Qemu-arm] [PATCH v4 01/20] intc/arm_gic: Refactor operations on the distributor, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 16/20] intc/arm_gic: Implement gic_update_virt() function, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 14/20] intc/arm_gic: Wire the vCPU interface, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 05/20] intc/arm_gic: Add the virtualization extensions to the GIC state, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions, Luc Michel, 2018/07/14
- [Qemu-arm] [PATCH v4 17/20] intc/arm_gic: Implement maintenance interrupt generation, Luc Michel, 2018/07/14