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

[Xen-devel] [RFC v2 01/16] gic:gic-vgic: separate GIV3 code more thoroughly



From: Andrii Anisov <andrii_anisov@xxxxxxxx>

This reduces some code and conditions in an IRQ processing path,
reducing IRQ latency for a build supported GICV2 only.

Signed-off-by: Andrii Anisov <andrii_anisov@xxxxxxxx>
---

Its a patch [1] with a better message and removed build errors.
Comments from Andre are not addressed yet.

[1] https://lists.xenproject.org/archives/html/xen-devel/2018-11/msg03282.html

---
 xen/arch/arm/gic-vgic.c    | 13 ++++++++++++-
 xen/arch/arm/gic.c         |  6 ++++++
 xen/arch/arm/vgic.c        | 20 ++++++++++++++++++++
 xen/arch/arm/vgic/vgic.c   |  2 ++
 xen/include/asm-arm/irq.h  |  2 ++
 xen/include/asm-arm/vgic.h | 17 +++++++++++------
 6 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c
index 48922f5..74b5fae 100644
--- a/xen/arch/arm/gic-vgic.c
+++ b/xen/arch/arm/gic-vgic.c
@@ -36,7 +36,9 @@ static inline void gic_set_lr(int lr, struct pending_irq *p,
 {
     ASSERT(!local_irq_is_enabled());
 
+#ifdef CONFIG_GICV3
     clear_bit(GIC_IRQ_GUEST_PRISTINE_LPI, &p->status);
+#endif
 
     gic_hw_ops->update_lr(lr, p->irq, p->priority,
                           p->desc ? p->desc->irq : INVALID_IRQ, state);
@@ -77,9 +79,11 @@ void gic_raise_inflight_irq(struct vcpu *v, unsigned int 
virtual_irq)
 {
     struct pending_irq *n = irq_to_pending(v, virtual_irq);
 
+#ifdef CONFIG_GICV3
     /* If an LPI has been removed meanwhile, there is nothing left to raise. */
     if ( unlikely(!n) )
         return;
+#endif
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
 
@@ -112,13 +116,14 @@ static unsigned int gic_find_unused_lr(struct vcpu *v,
 {
     unsigned int nr_lrs = gic_get_nr_lrs();
     unsigned long *lr_mask = (unsigned long *) &this_cpu(lr_mask);
-    struct gic_lr lr_val;
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
 
+#ifdef CONFIG_GICV3
     if ( unlikely(test_bit(GIC_IRQ_GUEST_PRISTINE_LPI, &p->status)) )
     {
         unsigned int used_lr;
+        struct gic_lr lr_val;
 
         for_each_set_bit(used_lr, lr_mask, nr_lrs)
         {
@@ -127,6 +132,7 @@ static unsigned int gic_find_unused_lr(struct vcpu *v,
                 return used_lr;
         }
     }
+#endif
 
     lr = find_next_zero_bit(lr_mask, nr_lrs, lr);
 
@@ -142,9 +148,11 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned int 
virtual_irq,
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
 
+#ifdef CONFIG_GICV3
     if ( unlikely(!p) )
         /* An unmapped LPI does not need to be raised. */
         return;
+#endif
 
     if ( v == current && list_empty(&v->arch.vgic.lr_pending) )
     {
@@ -172,6 +180,8 @@ static void gic_update_one_lr(struct vcpu *v, int i)
     gic_hw_ops->read_lr(i, &lr_val);
     irq = lr_val.virq;
     p = irq_to_pending(v, irq);
+
+#ifdef CONFIG_GICV3
     /*
      * An LPI might have been unmapped, in which case we just clean up here.
      * If that LPI is marked as PRISTINE, the information in the LR is bogus,
@@ -188,6 +198,7 @@ static void gic_update_one_lr(struct vcpu *v, int i)
 
         return;
     }
+#endif
 
     if ( lr_val.active )
     {
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 6cc7dec..77fc06f 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -136,7 +136,9 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int 
virq,
     /* Caller has already checked that the IRQ is an SPI */
     ASSERT(virq >= 32);
     ASSERT(virq < vgic_num_irqs(d));
+#ifdef CONFIG_GICV3
     ASSERT(!is_lpi(virq));
+#endif
 
     /*
      * When routing an IRQ to guest, the virtual state is not synced
@@ -168,7 +170,9 @@ int gic_remove_irq_from_guest(struct domain *d, unsigned 
int virq,
 
     ASSERT(spin_is_locked(&desc->lock));
     ASSERT(test_bit(_IRQ_GUEST, &desc->status));
+#ifdef CONFIG_GICV3
     ASSERT(!is_lpi(virq));
+#endif
 
     /*
      * Removing an interrupt while the domain is running may have
@@ -391,6 +395,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
             do_IRQ(regs, irq, is_fiq);
             local_irq_disable();
         }
+#ifdef CONFIG_GICV3
         else if ( is_lpi(irq) )
         {
             local_irq_enable();
@@ -398,6 +403,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
             gic_hw_ops->do_LPI(irq);
             local_irq_disable();
         }
+#endif
         else if ( unlikely(irq < 16) )
         {
             do_sgi(regs, irq);
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 255210c..dd35695 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -64,14 +64,18 @@ struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, 
unsigned int irq)
 
 void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
 {
+#ifdef CONFIG_GICV3
     /* The lpi_vcpu_id field must be big enough to hold a VCPU ID. */
     BUILD_BUG_ON(BIT(sizeof(p->lpi_vcpu_id) * 8) < MAX_VIRT_CPUS);
+#endif
 
     memset(p, 0, sizeof(*p));
     INIT_LIST_HEAD(&p->inflight);
     INIT_LIST_HEAD(&p->lr_queue);
     p->irq = virq;
+#ifdef CONFIG_GICV3
     p->lpi_vcpu_id = INVALID_VCPU_ID;
+#endif
 }
 
 static void vgic_rank_init(struct vgic_irq_rank *rank, uint8_t index,
@@ -246,9 +250,11 @@ static int vgic_get_virq_priority(struct vcpu *v, unsigned 
int virq)
 {
     struct vgic_irq_rank *rank;
 
+#ifdef CONFIG_GICV3
     /* LPIs don't have a rank, also store their priority separately. */
     if ( is_lpi(virq) )
         return v->domain->arch.vgic.handler->lpi_get_priority(v->domain, virq);
+#endif
 
     rank = vgic_rank_irq(v, virq);
     return ACCESS_ONCE(rank->priority[virq & INTERRUPT_RANK_MASK]);
@@ -259,8 +265,10 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     unsigned long flags;
     struct pending_irq *p;
 
+#ifdef CONFIG_GICV3
     /* This will never be called for an LPI, as we don't migrate them. */
     ASSERT(!is_lpi(irq));
+#endif
 
     spin_lock_irqsave(&old->arch.vgic.lock, flags);
 
@@ -315,6 +323,7 @@ void arch_move_irqs(struct vcpu *v)
     struct vcpu *v_target;
     int i;
 
+#ifdef CONFIG_GICV3
     /*
      * We don't migrate LPIs at the moment.
      * If we ever do, we must make sure that the struct pending_irq does
@@ -325,6 +334,7 @@ void arch_move_irqs(struct vcpu *v)
      * don't participate.
      */
     ASSERT(!is_lpi(vgic_num_irqs(d) - 1));
+#endif
 
     for ( i = 32; i < vgic_num_irqs(d); i++ )
     {
@@ -346,8 +356,10 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
     int i = 0;
     struct vcpu *v_target;
 
+#ifdef CONFIG_GICV3
     /* LPIs will never be disabled via this function. */
     ASSERT(!is_lpi(32 * n + 31));
+#endif
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
@@ -396,8 +408,10 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     struct vcpu *v_target;
     struct domain *d = v->domain;
 
+#ifdef CONFIG_GICV3
     /* LPIs will never be enabled via this function. */
     ASSERT(!is_lpi(32 * n + 31));
+#endif
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
@@ -493,8 +507,10 @@ struct pending_irq *irq_to_pending(struct vcpu *v, 
unsigned int irq)
      * are used for SPIs; the rests are used for per cpu irqs */
     if ( irq < 32 )
         n = &v->arch.vgic.pending_irqs[irq];
+#ifdef CONFIG_GICV3
     else if ( is_lpi(irq) )
         n = v->domain->arch.vgic.handler->lpi_to_pending(v->domain, irq);
+#endif
     else
         n = &v->domain->arch.vgic.pending_irqs[irq - 32];
     return n;
@@ -553,12 +569,14 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
     n = irq_to_pending(v, virq);
+#ifdef CONFIG_GICV3
     /* If an LPI has been removed, there is nothing to inject here. */
     if ( unlikely(!n) )
     {
         spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
         return;
     }
+#endif
 
     /* vcpu offline */
     if ( test_bit(_VPF_down, &v->pause_flags) )
@@ -610,8 +628,10 @@ bool vgic_evtchn_irq_pending(struct vcpu *v)
     struct pending_irq *p;
 
     p = irq_to_pending(v, v->domain->arch.evtchn_irq);
+#ifdef CONFIG_GICV3
     /* Does not work for LPIs. */
     ASSERT(!is_lpi(v->domain->arch.evtchn_irq));
+#endif
 
     return list_empty(&p->inflight);
 }
diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
index e2844dc..b8dbdaf 100644
--- a/xen/arch/arm/vgic/vgic.c
+++ b/xen/arch/arm/vgic/vgic.c
@@ -703,8 +703,10 @@ bool vgic_evtchn_irq_pending(struct vcpu *v)
     unsigned long flags;
     bool pending;
 
+#ifdef CONFIG_GICV3
     /* Does not work for LPIs. */
     ASSERT(!is_lpi(v->domain->arch.evtchn_irq));
+#endif
 
     irq = vgic_get_irq(v->domain, v, v->domain->arch.evtchn_irq);
     spin_lock_irqsave(&irq->irq_lock, flags);
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index e45d574..4f1ef3c 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -63,10 +63,12 @@ struct irq_desc *__irq_to_desc(int irq);
 
 void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
 
+#ifdef CONFIG_GICV3
 static inline bool is_lpi(unsigned int irq)
 {
     return irq >= LPI_OFFSET;
 }
+#endif
 
 #define domain_pirq_to_irq(d, pirq) (pirq)
 
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 447d24e..c5cb63f 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -63,27 +63,32 @@ struct pending_irq
      * GIC_IRQ_GUEST_MIGRATING: the irq is being migrated to a different
      * vcpu while it is still inflight and on an GICH_LR register on the
      * old vcpu.
-     *
-     * GIC_IRQ_GUEST_PRISTINE_LPI: the IRQ is a newly mapped LPI, which
-     * has never been in an LR before. This means that any trace of an
-     * LPI with the same number in an LR must be from an older LPI, which
-     * has been unmapped before.
-     *
      */
 #define GIC_IRQ_GUEST_QUEUED   0
 #define GIC_IRQ_GUEST_ACTIVE   1
 #define GIC_IRQ_GUEST_VISIBLE  2
 #define GIC_IRQ_GUEST_ENABLED  3
 #define GIC_IRQ_GUEST_MIGRATING   4
+#ifdef CONFIG_GICV3
+    /*
+     * GIC_IRQ_GUEST_PRISTINE_LPI: the IRQ is a newly mapped LPI, which
+     * has never been in an LR before. This means that any trace of an
+     * LPI with the same number in an LR must be from an older LPI, which
+     * has been unmapped before.
+     * Valid for GICV3 only.
+     */
 #define GIC_IRQ_GUEST_PRISTINE_LPI  5
+#endif
     unsigned long status;
     struct irq_desc *desc; /* only set it the irq corresponds to a physical 
irq */
     unsigned int irq;
 #define GIC_INVALID_LR         (uint8_t)~0
     uint8_t lr;
     uint8_t priority;
+#ifdef CONFIG_GICV3
     uint8_t lpi_priority;       /* Caches the priority if this is an LPI. */
     uint8_t lpi_vcpu_id;        /* The VCPU for an LPI. */
+#endif
     /* inflight is used to append instances of pending_irq to
      * vgic.inflight_irqs */
     struct list_head inflight;
-- 
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®.