[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 07/20] intc/arm_gic: Add virtualization extension
From: |
Luc Michel |
Subject: |
[Qemu-devel] [PATCH v3 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions |
Date: |
Fri, 29 Jun 2018 15:29:41 +0200 |
Add some helper macros and functions related to the virtualization
extensions to gic_internal.h.
The GICH_LR_* macros help extracting specific fields of a list register
value. The only tricky one is the priority field as only the MSB are
stored. The value must be shifted accordingly to obtain the correct
priority value.
gic_is_vcpu() and gic_get_vcpu_real_id() help with (v)CPU id manipulation
to abstract the fact that vCPU id are in the range
[ GIC_NCPU; (GIC_NCPU + num_cpu) [.
gic_lr_* and gic_virq_is_valid() help with the list registers.
gic_get_lr_entry() tries to find the LR entry for a given (vCPU, irq)
pair. gic_get_lr_entry_nofail() is meant to be used in contexts where we
know for sure that the entry exists, so we can avoid the NULL check on
the returned pointer.
Signed-off-by: Luc Michel <address@hidden>
---
hw/intc/arm_gic.c | 5 ++++
hw/intc/gic_internal.h | 65 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index b2dd379bd2..f25d1b1270 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -61,6 +61,11 @@ static inline int gic_get_current_cpu(GICState *s)
return 0;
}
+static inline int gic_get_current_vcpu(GICState *s)
+{
+ return gic_get_current_cpu(s) + GIC_NCPU;
+}
+
/* Return true if this GIC config has interrupt groups, which is
* true if we're a GICv2, or a GICv1 with the security extensions.
*/
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 1aa888a576..4242a16bd4 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -129,6 +129,20 @@ REG32(GICH_LR63, 0x1fc)
R_GICH_LR0_Priority_MASK | R_GICH_LR0_State_MASK | \
R_GICH_LR0_Grp1_MASK | R_GICH_LR0_HW_MASK)
+#define GICH_LR_STATE_INVALID 0
+#define GICH_LR_STATE_PENDING 1
+#define GICH_LR_STATE_ACTIVE 2
+#define GICH_LR_STATE_ACTIVE_PENDING 3
+
+#define GICH_LR_VIRT_ID(entry) (FIELD_EX32(entry, GICH_LR0, VirtualID))
+#define GICH_LR_PHYS_ID(entry) (FIELD_EX32(entry, GICH_LR0, PhysicalID))
+#define GICH_LR_CPUID(entry) (FIELD_EX32(entry, GICH_LR0, CPUID))
+#define GICH_LR_EOI(entry) (FIELD_EX32(entry, GICH_LR0, EOI))
+#define GICH_LR_PRIORITY(entry) (FIELD_EX32(entry, GICH_LR0, Priority) << 3)
+#define GICH_LR_STATE(entry) (FIELD_EX32(entry, GICH_LR0, State))
+#define GICH_LR_GROUP(entry) (FIELD_EX32(entry, GICH_LR0, Grp1))
+#define GICH_LR_HW(entry) (FIELD_EX32(entry, GICH_LR0, HW))
+
/* Valid bits for GICC_CTLR for GICv1, v1 with security extensions,
* GICv2 and GICv2 with security extensions:
*/
@@ -164,4 +178,55 @@ static inline bool gic_is_vcpu(int cpu)
return cpu >= GIC_NCPU;
}
+static inline int gic_get_vcpu_real_id(int cpu)
+{
+ return (cpu >= GIC_NCPU) ? (cpu - GIC_NCPU) : cpu;
+}
+
+static inline bool gic_lr_entry_is_free(uint32_t entry)
+{
+ return (GICH_LR_STATE(entry) == GICH_LR_STATE_INVALID)
+ && (GICH_LR_HW(entry) || !GICH_LR_EOI(entry));
+}
+
+static inline bool gic_lr_entry_is_eoi(uint32_t entry)
+{
+ return (GICH_LR_STATE(entry) == GICH_LR_STATE_INVALID)
+ && !GICH_LR_HW(entry) && GICH_LR_EOI(entry);
+}
+
+/* Return a pointer on the LR entry for a given (irq,vcpu) pair.
+ * Having multiple LRs with the same VirtualID leads to UNPREDICTABLE
+ * behaviour in the GIC. We choose to return the first one that matches.
+ */
+static inline uint32_t *gic_get_lr_entry(GICState *s, int irq, int vcpu)
+{
+ int cpu = gic_get_vcpu_real_id(vcpu);
+ int lr_idx;
+
+ for (lr_idx = 0; lr_idx < s->num_lrs; lr_idx++) {
+ uint32_t *entry = &s->h_lr[lr_idx][cpu];
+
+ if ((GICH_LR_VIRT_ID(*entry) == irq) &&
+ (!gic_lr_entry_is_free(*entry))) {
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+static inline bool gic_virq_is_valid(GICState *s, int irq, int vcpu)
+{
+ return gic_get_lr_entry(s, irq, vcpu) != NULL;
+}
+
+static inline uint32_t *gic_get_lr_entry_nofail(GICState *s, int irq, int vcpu)
+{
+ uint32_t *entry = gic_get_lr_entry(s, irq, vcpu);
+ assert(entry);
+
+ return entry;
+}
+
#endif /* QEMU_ARM_GIC_INTERNAL_H */
--
2.17.1
- [Qemu-devel] [PATCH v3 00/20] arm_gic: add virtualization extensions support, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 13/20] intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write), Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 01/20] intc/arm_gic: Implement write to GICD_ISACTIVERn and GICD_ICACTIVERn registers, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 07/20] intc/arm_gic: Add virtualization extensions helper macros and functions,
Luc Michel <=
- [Qemu-devel] [PATCH v3 10/20] intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio), Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 15/20] intc/arm_gic: Implement the virtual interface registers, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 03/20] intc/arm_gic: Remove some dead code and put some functions static, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 06/20] intc/arm_gic: Add virtual interface register definitions, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 09/20] intc/arm_gic: Add virtualization enabled IRQ helper functions, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 12/20] intc/arm_gic: Implement virtualization extensions in gic_complete_irq, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 17/20] intc/arm_gic: Implement maintenance interrupt generation, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 11/20] intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 18/20] intc/arm_gic: Improve traces, Luc Michel, 2018/06/29
- [Qemu-devel] [PATCH v3 16/20] intc/arm_gic: Implement gic_update_virt() function, Luc Michel, 2018/06/29