From: Luc Michel <luc.michel@greensocs.com>
To: qemu-devel@nongnu.org
Cc: Luc Michel <luc.michel@greensocs.com>,
qemu-arm@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
saipava@xilinx.com, edgari@xilinx.com, mark.burton@greensocs.com,
Jan Kiszka <jan.kiszka@web.de>
Subject: [Qemu-devel] [PATCH v3 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions
Date: Fri, 29 Jun 2018 15:29:43 +0200 [thread overview]
Message-ID: <20180629132954.24269-10-luc.michel@greensocs.com> (raw)
In-Reply-To: <20180629132954.24269-1-luc.michel@greensocs.com>
Add some helper functions to gic_internal.h to get or change the state
of an IRQ. When the current CPU is not a vCPU, the call is forwarded to
the GIC distributor. Otherwise, it acts on the list register matching
the IRQ in the current CPU virtual interface.
gic_clear_active can have a side effect on the distributor, even in the
vCPU case, when the correponding LR has the HW field set.
Use those functions in the CPU interface code path to prepare for the
vCPU interface implementation.
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
---
hw/intc/arm_gic.c | 32 ++++++++---------
hw/intc/gic_internal.h | 78 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 18 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 8ab3025901..d55a88bb33 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -222,7 +222,8 @@ static uint16_t gic_get_current_pending_irq(GICState *s, int cpu,
uint16_t pending_irq = s->current_pending[cpu];
if (pending_irq < GIC_MAXIRQ && gic_has_groups(s)) {
- int group = GIC_DIST_TEST_GROUP(pending_irq, (1 << cpu));
+ int group = gic_test_group(s, pending_irq, cpu);
+
/* On a GIC without the security extensions, reading this register
* behaves in the same way as a secure access to a GIC with them.
*/
@@ -253,7 +254,7 @@ static int gic_get_group_priority(GICState *s, int cpu, int irq)
if (gic_has_groups(s) &&
!(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) &&
- GIC_DIST_TEST_GROUP(irq, (1 << cpu))) {
+ gic_test_group(s, irq, cpu)) {
bpr = s->abpr[cpu] - 1;
assert(bpr >= 0);
} else {
@@ -266,7 +267,7 @@ static int gic_get_group_priority(GICState *s, int cpu, int irq)
*/
mask = ~0U << ((bpr & 7) + 1);
- return GIC_DIST_GET_PRIORITY(irq, cpu) & mask;
+ return gic_get_priority(s, irq, cpu) & mask;
}
static void gic_activate_irq(GICState *s, int cpu, int irq)
@@ -279,14 +280,14 @@ static void gic_activate_irq(GICState *s, int cpu, int irq)
int regno = preemption_level / 32;
int bitno = preemption_level % 32;
- if (gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, (1 << cpu))) {
+ if (gic_has_groups(s) && gic_test_group(s, irq, cpu)) {
s->nsapr[regno][cpu] |= (1 << bitno);
} else {
s->apr[regno][cpu] |= (1 << bitno);
}
s->running_priority[cpu] = prio;
- GIC_DIST_SET_ACTIVE(irq, 1 << cpu);
+ gic_set_active(s, irq, cpu);
}
static int gic_get_prio_from_apr_bits(GICState *s, int cpu)
@@ -355,7 +356,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
return irq;
}
- if (GIC_DIST_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) {
+ if (gic_get_priority(s, irq, cpu) >= s->running_priority[cpu]) {
DPRINTF("ACK, pending interrupt (%d) has insufficient priority\n", irq);
return 1023;
}
@@ -364,8 +365,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
/* Clear pending flags for both level and edge triggered interrupts.
* Level triggered IRQs will be reasserted once they become inactive.
*/
- GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK
- : cm);
+ gic_clear_pending(s, irq, cpu);
ret = irq;
} else {
if (irq < GIC_NR_SGIS) {
@@ -377,9 +377,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
src = ctz32(s->sgi_pending[irq][cpu]);
s->sgi_pending[irq][cpu] &= ~(1 << src);
if (s->sgi_pending[irq][cpu] == 0) {
- GIC_DIST_CLEAR_PENDING(irq,
- GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK
- : cm);
+ gic_clear_pending(s, irq, cpu);
}
ret = irq | ((src & 0x7) << 10);
} else {
@@ -387,8 +385,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
* interrupts. (level triggered interrupts with an active line
* remain pending, see gic_test_pending)
*/
- GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK
- : cm);
+ gic_clear_pending(s, irq, cpu);
ret = irq;
}
}
@@ -544,8 +541,7 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
{
- int cm = 1 << cpu;
- int group = gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm);
+ int group = gic_has_groups(s) && gic_test_group(s, irq, cpu);
if (!gic_eoi_split(s, cpu, attrs)) {
/* This is UNPREDICTABLE; we choose to ignore it */
@@ -559,7 +555,7 @@ static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
return;
}
- GIC_DIST_CLEAR_ACTIVE(irq, cm);
+ gic_clear_active(s, irq, cpu);
}
static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
@@ -594,7 +590,7 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
}
}
- group = gic_has_groups(s) && GIC_DIST_TEST_GROUP(irq, cm);
+ group = gic_has_groups(s) && gic_test_group(s, irq, cpu);
if (gic_cpu_ns_access(s, cpu, attrs) && !group) {
DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq);
@@ -610,7 +606,7 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
/* In GICv2 the guest can choose to split priority-drop and deactivate */
if (!gic_eoi_split(s, cpu, attrs)) {
- GIC_DIST_CLEAR_ACTIVE(irq, cm);
+ gic_clear_active(s, irq, cpu);
}
gic_update(s);
}
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 4242a16bd4..4cacd34264 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -143,6 +143,13 @@ REG32(GICH_LR63, 0x1fc)
#define GICH_LR_GROUP(entry) (FIELD_EX32(entry, GICH_LR0, Grp1))
#define GICH_LR_HW(entry) (FIELD_EX32(entry, GICH_LR0, HW))
+#define GICH_LR_CLEAR_PENDING(entry) \
+ ((entry) &= ~(GICH_LR_STATE_PENDING << R_GICH_LR0_State_SHIFT))
+#define GICH_LR_SET_ACTIVE(entry) \
+ ((entry) |= (GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT))
+#define GICH_LR_CLEAR_ACTIVE(entry) \
+ ((entry) &= ~(GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT))
+
/* Valid bits for GICC_CTLR for GICv1, v1 with security extensions,
* GICv2 and GICv2 with security extensions:
*/
@@ -229,4 +236,75 @@ static inline uint32_t *gic_get_lr_entry_nofail(GICState *s, int irq, int vcpu)
return entry;
}
+static inline bool gic_test_group(GICState *s, int irq, int cpu)
+{
+ if (gic_is_vcpu(cpu)) {
+ uint32_t *entry = gic_get_lr_entry_nofail(s, irq, cpu);
+ return GICH_LR_GROUP(*entry);
+ } else {
+ return GIC_DIST_TEST_GROUP(irq, 1 << cpu);
+ }
+}
+
+static inline void gic_clear_pending(GICState *s, int irq, int cpu)
+{
+ if (gic_is_vcpu(cpu)) {
+ uint32_t *entry = gic_get_lr_entry_nofail(s, irq, cpu);
+ GICH_LR_CLEAR_PENDING(*entry);
+ } 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_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK
+ : (1 << cpu));
+ }
+}
+
+static inline void gic_set_active(GICState *s, int irq, int cpu)
+{
+ if (gic_is_vcpu(cpu)) {
+ uint32_t *entry = gic_get_lr_entry_nofail(s, irq, cpu);
+ GICH_LR_SET_ACTIVE(*entry);
+ } else {
+ GIC_DIST_SET_ACTIVE(irq, 1 << cpu);
+ }
+}
+
+static inline void gic_clear_active(GICState *s, int irq, int cpu)
+{
+ if (gic_is_vcpu(cpu)) {
+ uint32_t *entry = gic_get_lr_entry_nofail(s, irq, cpu);
+ GICH_LR_CLEAR_ACTIVE(*entry);
+
+ if (GICH_LR_HW(*entry)) {
+ /* Hardware interrupt. We must forward the deactivation request to
+ * the distributor.
+ */
+ int phys_irq = GICH_LR_PHYS_ID(*entry);
+ int rcpu = gic_get_vcpu_real_id(cpu);
+
+ /* This is equivalent to a NS write to DIR on the physical CPU
+ * interface. Hence group0 interrupt deactivation is ignored if
+ * the GIC is secure.
+ */
+ if (!s->security_extn || GIC_DIST_TEST_GROUP(phys_irq, 1 << rcpu)) {
+ GIC_DIST_CLEAR_ACTIVE(phys_irq, 1 << rcpu);
+ }
+ }
+ } else {
+ GIC_DIST_CLEAR_ACTIVE(irq, 1 << cpu);
+ }
+}
+
+static inline int gic_get_priority(GICState *s, int irq, int cpu)
+{
+ if (gic_is_vcpu(cpu)) {
+ uint32_t *entry = gic_get_lr_entry_nofail(s, irq, cpu);
+ return GICH_LR_PRIORITY(*entry);
+ } else {
+ return GIC_DIST_GET_PRIORITY(irq, cpu);
+ }
+}
+
#endif /* QEMU_ARM_GIC_INTERNAL_H */
--
2.17.1
next prev parent reply other threads:[~2018-06-29 13:31 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-29 13:29 [Qemu-devel] [PATCH v3 00/20] arm_gic: add virtualization extensions support Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 01/20] intc/arm_gic: Implement write to GICD_ISACTIVERn and GICD_ICACTIVERn registers Luc Michel
2018-07-10 17:09 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 02/20] intc/arm_gic: Refactor operations on the distributor Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 03/20] intc/arm_gic: Remove some dead code and put some functions static Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 04/20] vmstate.h: Provide VMSTATE_UINT16_SUB_ARRAY Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 05/20] intc/arm_gic: Add the virtualization extensions to the GIC state Luc Michel
2018-07-10 17:12 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 06/20] intc/arm_gic: Add virtual interface register definitions Luc Michel
2018-07-10 17:15 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions Luc Michel
2018-07-12 12:27 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 08/20] intc/arm_gic: Refactor secure/ns access check in the CPU interface Luc Michel
2018-07-12 12:30 ` Peter Maydell
2018-06-29 13:29 ` Luc Michel [this message]
2018-07-12 12:44 ` [Qemu-devel] [PATCH v3 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio) Luc Michel
2018-07-12 12:54 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq Luc Michel
2018-07-12 13:19 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 12/20] intc/arm_gic: Implement virtualization extensions in gic_complete_irq Luc Michel
2018-07-12 12:34 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write) Luc Michel
2018-07-12 13:25 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 14/20] intc/arm_gic: Wire the vCPU interface Luc Michel
2018-07-12 13:37 ` Peter Maydell
2018-07-13 14:44 ` Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 15/20] intc/arm_gic: Implement the virtual interface registers Luc Michel
2018-07-12 13:43 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 16/20] intc/arm_gic: Implement gic_update_virt() function Luc Michel
2018-07-12 13:56 ` Peter Maydell
2018-07-13 13:33 ` Luc Michel
2018-07-13 13:41 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 17/20] intc/arm_gic: Implement maintenance interrupt generation Luc Michel
2018-07-12 14:27 ` Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 18/20] intc/arm_gic: Improve traces Luc Michel
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 19/20] xlnx-zynqmp: Improve GIC wiring and MMIO mapping Luc Michel
2018-07-12 14:29 ` [Qemu-devel] [Qemu-arm] " Peter Maydell
2018-06-29 13:29 ` [Qemu-devel] [PATCH v3 20/20] arm/virt: Add support for GICv2 virtualization extensions Luc Michel
2018-07-05 6:51 ` Jan Kiszka
2018-07-05 8:00 ` Jan Kiszka
2018-07-05 8:46 ` Luc Michel
2018-07-05 9:28 ` Peter Maydell
2018-07-12 14:57 ` Peter Maydell
2018-07-06 9:25 ` Jan Kiszka
2018-07-12 14:43 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180629132954.24269-10-luc.michel@greensocs.com \
--to=luc.michel@greensocs.com \
--cc=edgari@xilinx.com \
--cc=jan.kiszka@web.de \
--cc=mark.burton@greensocs.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=saipava@xilinx.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).