[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v6 23/36] ARM: vGICv3: handle disabled LPIs



If a guest disables an LPI, we do not forward this to the associated
host LPI to avoid queueing commands to the host ITS command queue.
So it may happen that an LPI fires nevertheless on the host. In this
case we can bail out early, but have to save the pending state on the
virtual side. We do this by storing the pending bit in struct
pending_irq, which is associated with mapped LPIs.

Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
---
 xen/arch/arm/gic-v3-lpi.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index 5f3fe2c..a670f73 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -137,6 +137,31 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
use_pta)
 }
 
 /*
+ * TODO: Investigate what to do here for potential interrupt storms.
+ * For disabling LPIs we would need to queue a ITS host command, which
+ * we avoid so far during a guest's runtime. Also re-enabling would
+ * trigger a host command upon the guest sending a command, which could
+ * be an attack vector for hogging the host command queue.
+ * See the thread around here for some background:
+ * https://lists.xen.org/archives/html/xen-devel/2016-12/msg00003.html
+ */
+static bool vgic_can_inject_lpi(struct vcpu *vcpu, uint32_t vlpi)
+{
+    struct pending_irq *p;
+
+    p = vcpu->domain->arch.vgic.handler->lpi_to_pending(vcpu->domain, vlpi);
+    if ( !p )
+        return false;
+
+    if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
+        return true;
+
+    set_bit(GIC_IRQ_GUEST_LPI_PENDING, &p->status);
+
+    return false;
+}
+
+/*
  * Handle incoming LPIs, which are a bit special, because they are potentially
  * numerous and also only get injected into guests. Treat them specially here,
  * by just looking up their target vCPU and virtual LPI number and hand it
@@ -187,7 +212,15 @@ void gicv3_do_LPI(unsigned int lpi)
 
     /* Check if the VCPU is ready to receive LPIs. */
     if ( vcpu->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
-        vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
+    {
+        /*
+         * We keep all host LPIs enabled, so check if it's disabled on the
+         * guest side and just record this LPI in the virtual pending table
+         * in this case. The guest picks it up once it gets enabled again.
+         */
+        if ( vgic_can_inject_lpi(vcpu, hlpi.virt_lpi) )
+            vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
+    }
 
     rcu_unlock_domain(d);
 }
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.