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

[Xen-devel] [RFC 15/16] hack: move gicv2 LRs reads and writes out of spinlocks



From: Andrii Anisov <andrii_anisov@xxxxxxxx>

Use values cached in `struct vcpu` for guest IRQs processing.
This also reduces LR stores and restores on VCPU switch.

Signed-off-by: Andrii Anisov <andrii_anisov@xxxxxxxx>
---
 xen/arch/arm/gic-v2.c     | 56 +++++++++++++++++++++++++++++++----------------
 xen/arch/arm/gic-vgic.c   |  8 +++++--
 xen/include/asm-arm/gic.h |  5 ++++-
 3 files changed, 47 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 25147bd..a2eb0a7 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -176,31 +176,18 @@ static unsigned int gicv2_cpu_mask(const cpumask_t 
*cpumask)
 
 static void gicv2_save_state(struct vcpu *v)
 {
-    int i;
-
-    /* No need for spinlocks here because interrupts are disabled around
-     * this call and it only accesses struct vcpu fields that cannot be
-     * accessed simultaneously by another pCPU.
-     */
-    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
-        v->arch.gic.v2.lr[i] = readl_gich(GICH_LR + i * 4);
-
     v->arch.gic.v2.apr = readl_gich(GICH_APR);
     v->arch.gic.v2.vmcr = readl_gich(GICH_VMCR);
     /* Disable until next VCPU scheduled */
     writel_gich(0, GICH_HCR);
 }
 
-static void gicv2_restore_state(const struct vcpu *v)
+static void gicv2_restore_state(struct vcpu *v)
 {
-    int i;
-
-    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
-        writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
-
     writel_gich(v->arch.gic.v2.apr, GICH_APR);
     writel_gich(v->arch.gic.v2.vmcr, GICH_VMCR);
     writel_gich(GICH_HCR_EN, GICH_HCR);
+    v->arch.gic.v2.lr_update_mask = (1 << gic_hw_ops->info->nr_lrs) - 1;
 }
 
 static void gicv2_dump_state(const struct vcpu *v)
@@ -493,6 +480,7 @@ static void gicv2_disable_interface(void)
 static void gicv2_update_lr(int lr, unsigned int virq, uint8_t priority,
                             unsigned int hw_irq, unsigned int state)
 {
+    struct vcpu *v = current;
     uint32_t lr_reg;
 
     BUG_ON(lr >= gicv2_info.nr_lrs);
@@ -507,19 +495,23 @@ static void gicv2_update_lr(int lr, unsigned int virq, 
uint8_t priority,
         lr_reg |= GICH_V2_LR_HW | ((hw_irq & GICH_V2_LR_PHYSICAL_MASK )
                                    << GICH_V2_LR_PHYSICAL_SHIFT);
 
-    writel_gich(lr_reg, GICH_LR + lr * 4);
+    v->arch.gic.v2.lr[lr] = lr_reg;
+    v->arch.gic.v2.lr_update_mask |= 1<<lr;
 }
 
 static void gicv2_clear_lr(int lr)
 {
-    writel_gich(0, GICH_LR + lr * 4);
+    struct vcpu *v = current;
+
+    v->arch.gic.v2.lr[lr] = 0;
+    v->arch.gic.v2.lr_update_mask |= 1<<lr;
 }
 
 static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
 {
     uint32_t lrv;
 
-    lrv          = readl_gich(GICH_LR + lr * 4);
+    lrv = current->arch.gic.v2.lr[lr];
     lr_reg->virq = (lrv >> GICH_V2_LR_VIRTUAL_SHIFT) & GICH_V2_LR_VIRTUAL_MASK;
     lr_reg->priority = (lrv >> GICH_V2_LR_PRIORITY_SHIFT) & 
GICH_V2_LR_PRIORITY_MASK;
     lr_reg->pending = lrv & GICH_V2_LR_PENDING;
@@ -546,6 +538,7 @@ static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
 static void gicv2_write_lr(int lr, const struct gic_lr *lr_reg)
 {
     uint32_t lrv = 0;
+    struct vcpu *v = current;
 
     lrv = (((lr_reg->virq & GICH_V2_LR_VIRTUAL_MASK) << 
GICH_V2_LR_VIRTUAL_SHIFT)   |
           ((uint32_t)(lr_reg->priority & GICH_V2_LR_PRIORITY_MASK)
@@ -574,7 +567,30 @@ static void gicv2_write_lr(int lr, const struct gic_lr 
*lr_reg)
         lrv |= (uint32_t)lr_reg->virt.source << GICH_V2_LR_CPUID_SHIFT;
     }
 
-    writel_gich(lrv, GICH_LR + lr * 4);
+    v->arch.gic.v2.lr[lr] = lrv;
+    v->arch.gic.v2.lr_update_mask |= 1<<lr;
+}
+
+static void gicv2_fetch_lrs(struct vcpu *v)
+{
+    int i;
+
+    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        if ( this_cpu(lr_mask) & 1<<i )
+            v->arch.gic.v2.lr[i] = readl_gich(GICH_LR + i * 4);
+        else
+            v->arch.gic.v2.lr[i] = 0;
+}
+
+static void gicv2_push_lrs(struct vcpu *v)
+{
+    int i;
+    uint64_t mask = v->arch.gic.v2.lr_update_mask;
+
+    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        if ( mask & 1<<i )
+            writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
+    v->arch.gic.v2.lr_update_mask = 0;
 }
 
 static void gicv2_hcr_status(uint32_t flag, bool status)
@@ -1360,6 +1376,8 @@ const static struct gic_hw_operations gicv2_ops = {
     .map_hwdom_extra_mappings = gicv2_map_hwdown_extra_mappings,
     .iomem_deny_access   = gicv2_iomem_deny_access,
     .do_LPI              = gicv2_do_LPI,
+    .fetch_lrs           = gicv2_fetch_lrs,
+    .push_lrs            = gicv2_push_lrs,
 };
 
 /* Set up the GIC */
diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c
index e511f91..86c8ae2 100644
--- a/xen/arch/arm/gic-vgic.c
+++ b/xen/arch/arm/gic-vgic.c
@@ -277,6 +277,7 @@ void vgic_sync_from_lrs(struct vcpu *v)
         return;
 
     gic_hw_ops->update_hcr_status(GICH_HCR_UIE, false);
+    gic_hw_ops->fetch_lrs(v);
 
     spin_lock(&v->arch.vgic.lock);
 
@@ -403,11 +404,14 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
 
 void vgic_sync_to_lrs(void)
 {
+    struct vcpu *v = current;
     ASSERT(!local_irq_is_enabled());
 
-    gic_restore_pending_irqs(current);
+    gic_restore_pending_irqs(v);
 
-    if ( !list_empty(&current->arch.vgic.lr_pending) && lr_all_full() )
+    gic_hw_ops->push_lrs(v);
+
+    if ( !list_empty(&v->arch.vgic.lr_pending) && lr_all_full() )
         gic_hw_ops->update_hcr_status(GICH_HCR_UIE, true);
 }
 
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 3d7394d..add2566 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -187,6 +187,7 @@ struct gic_v2 {
     uint32_t vmcr;
     uint32_t apr;
     uint32_t lr[64];
+    uint64_t lr_update_mask;
 };
 
 /*
@@ -323,7 +324,7 @@ struct gic_hw_operations {
     /* Save GIC registers */
     void (*save_state)(struct vcpu *);
     /* Restore GIC registers */
-    void (*restore_state)(const struct vcpu *);
+    void (*restore_state)(struct vcpu *);
     /* Dump GIC LR register information */
     void (*dump_state)(const struct vcpu *);
 
@@ -384,6 +385,8 @@ struct gic_hw_operations {
     int (*iomem_deny_access)(const struct domain *d);
     /* Handle LPIs, which require special handling */
     void (*do_LPI)(unsigned int lpi);
+    void (*fetch_lrs) (struct vcpu *v);
+    void (*push_lrs) (struct vcpu *v);
 };
 
 extern const struct gic_hw_operations *gic_hw_ops;
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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