|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XEN PATCH v2 22/25] arm: new VGIC: its: Implement MMIO-based LPI invalidation
Since GICv4.1, it has become legal for an implementation to advertise
GICR_{INVLPIR,INVALLR,SYNCR} while having an ITS, allowing for a more
efficient invalidation scheme (no guest command queue contention when
multiple CPUs are generating invalidations).
Provide the invalidation registers as a primitive to their ITS
counterpart. Note that we don't advertise them to the guest yet.
Based on Linux commit 4645d11f4a553 by Marc Zyngier
Signed-off-by: Mykyta Poturai <mykyta_poturai@xxxxxxxx>
---
xen/arch/arm/include/asm/new_vgic.h | 1 +
xen/arch/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++--
xen/arch/arm/vgic/vgic-mmio.h | 15 +++++++
3 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/include/asm/new_vgic.h
b/xen/arch/arm/include/asm/new_vgic.h
index b038fb7861..dfc434ab41 100644
--- a/xen/arch/arm/include/asm/new_vgic.h
+++ b/xen/arch/arm/include/asm/new_vgic.h
@@ -239,6 +239,7 @@ struct vgic_cpu {
struct vgic_io_device rd_iodev;
struct vgic_redist_region *rdreg;
uint32_t rdreg_index;
+ atomic_t syncr_busy;
struct vgic_io_device sgi_iodev;
/* Contains the attributes and gpa of the LPI pending tables. */
diff --git a/xen/arch/arm/vgic/vgic-mmio-v3.c b/xen/arch/arm/vgic/vgic-mmio-v3.c
index 4bf8c21203..0e3835d38a 100644
--- a/xen/arch/arm/vgic/vgic-mmio-v3.c
+++ b/xen/arch/arm/vgic/vgic-mmio-v3.c
@@ -583,6 +583,65 @@ static void vgic_mmio_write_pendbase(struct vcpu *vcpu,
paddr_t addr,
old_pendbaser );
}
+static unsigned long vgic_mmio_read_sync(struct vcpu *vcpu, paddr_t addr,
+ unsigned int len)
+{
+ return !!atomic_read(&vcpu->arch.vgic.syncr_busy);
+}
+
+static void vgic_set_rdist_busy(struct vcpu *vcpu, bool busy)
+{
+ if ( busy )
+ {
+ atomic_inc(&vcpu->arch.vgic.syncr_busy);
+ smp_mb__after_atomic();
+ }
+ else
+ {
+ smp_mb__before_atomic();
+ atomic_dec(&vcpu->arch.vgic.syncr_busy);
+ }
+}
+
+static void vgic_mmio_write_invlpi(struct vcpu *vcpu, paddr_t addr,
+ unsigned int len, unsigned long val)
+{
+ struct vgic_irq *irq;
+
+ /*
+ * If the guest wrote only to the upper 32bit part of the
+ * register, drop the write on the floor, as it is only for
+ * vPEs (which we don't support for obvious reasons).
+ *
+ * Also discard the access if LPIs are not enabled.
+ */
+ if ( (addr & 4) || !vgic_lpis_enabled(vcpu) )
+ return;
+
+ vgic_set_rdist_busy(vcpu, true);
+
+ irq = vgic_get_irq(vcpu->domain, NULL, val & 0xffffffff);
+ if ( irq )
+ {
+ vgic_its_inv_lpi(vcpu->domain, irq);
+ vgic_put_irq(vcpu->domain, irq);
+ }
+
+ vgic_set_rdist_busy(vcpu, false);
+}
+
+static void vgic_mmio_write_invall(struct vcpu *vcpu, paddr_t addr,
+ unsigned int len, unsigned long val)
+{
+ /* See vgic_mmio_write_invlpi() for the early return rationale */
+ if ( (addr & 4) || !vgic_lpis_enabled(vcpu) )
+ return;
+
+ vgic_set_rdist_busy(vcpu, true);
+ vgic_its_invall(vcpu);
+ vgic_set_rdist_busy(vcpu, false);
+}
+
static const struct vgic_register_region vgic_v3_dist_registers[] = {
REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc,
@@ -655,13 +714,13 @@ static const struct vgic_register_region
vgic_v3_rd_registers[] = {
vgic_mmio_read_pendbase, vgic_mmio_write_pendbase, 8,
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_INVLPIR,
- vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+ vgic_mmio_read_raz, vgic_mmio_write_invlpi, 8,
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_INVALLR,
- vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+ vgic_mmio_read_raz, vgic_mmio_write_invall, 8,
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_SYNCR,
- vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+ vgic_mmio_read_sync, vgic_mmio_write_wi, 4,
VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
diff --git a/xen/arch/arm/vgic/vgic-mmio.h b/xen/arch/arm/vgic/vgic-mmio.h
index edf8665cda..12f4d690f6 100644
--- a/xen/arch/arm/vgic/vgic-mmio.h
+++ b/xen/arch/arm/vgic/vgic-mmio.h
@@ -153,4 +153,19 @@ unsigned long extract_bytes(uint64_t data, unsigned int
offset,
uint64_t update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
unsigned long val);
+#ifdef CONFIG_HAS_ITS
+int vgic_its_inv_lpi(struct domain *d, struct vgic_irq *irq);
+int vgic_its_invall(struct vcpu *vcpu);
+#else
+static inline int vgic_its_inv_lpi(struct domain *d, struct vgic_irq *irq)
+{
+ return 0;
+}
+
+static inline int vgic_its_invall(struct vcpu *vcpu)
+{
+ return 0;
+}
+#endif
+
#endif
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |