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

[PATCH v2 1/4] xen/arm: optimize the size of struct vcpu



When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu
exceeds one page, which requires allocating two pages and led to the
introduction of MAX_PAGES_PER_VCPU.

To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic
member of struct arch_vcpu is changed to a pointer to struct vgic_cpu.
As a result, the size of struct vcpu for Arm64 is reduced to 2048 bytes,
compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y)
and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and
CONFIG_NEW_VGIC=y).

Since the vgic member is now a pointer, vcpu_vgic_init() and
vcpu_vgic_free() are updated to allocate and free the struct vgic_cpu
instance dynamically.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
Changes in v2:
 - New patch.
---
 xen/arch/arm/gic-vgic.c           | 48 ++++++++++-----------
 xen/arch/arm/include/asm/domain.h |  2 +-
 xen/arch/arm/vgic-v3.c            | 34 +++++++--------
 xen/arch/arm/vgic.c               | 72 +++++++++++++++++--------------
 xen/arch/arm/vgic/vgic-init.c     | 10 ++++-
 xen/arch/arm/vgic/vgic-v2.c       |  4 +-
 xen/arch/arm/vgic/vgic.c          | 50 ++++++++++-----------
 7 files changed, 116 insertions(+), 104 deletions(-)

diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c
index ea48c5375a..482b77c986 100644
--- a/xen/arch/arm/gic-vgic.c
+++ b/xen/arch/arm/gic-vgic.c
@@ -42,12 +42,12 @@ static inline void gic_add_to_lr_pending(struct vcpu *v, 
struct pending_irq *n)
 {
     struct pending_irq *iter;
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     if ( !list_empty(&n->lr_queue) )
         return;
 
-    list_for_each_entry ( iter, &v->arch.vgic.lr_pending, lr_queue )
+    list_for_each_entry ( iter, &v->arch.vgic->lr_pending, lr_queue )
     {
         if ( iter->priority > n->priority )
         {
@@ -55,12 +55,12 @@ static inline void gic_add_to_lr_pending(struct vcpu *v, 
struct pending_irq *n)
             return;
         }
     }
-    list_add_tail(&n->lr_queue, &v->arch.vgic.lr_pending);
+    list_add_tail(&n->lr_queue, &v->arch.vgic->lr_pending);
 }
 
 void gic_remove_from_lr_pending(struct vcpu *v, struct pending_irq *p)
 {
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     list_del_init(&p->lr_queue);
 }
@@ -73,7 +73,7 @@ void gic_raise_inflight_irq(struct vcpu *v, unsigned int 
virtual_irq)
     if ( unlikely(!n) )
         return;
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     /* Don't try to update the LR if the interrupt is disabled */
     if ( !test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
@@ -104,7 +104,7 @@ static unsigned int gic_find_unused_lr(struct vcpu *v,
 {
     uint64_t *lr_mask = &this_cpu(lr_mask);
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     if ( unlikely(test_bit(GIC_IRQ_GUEST_PRISTINE_LPI, &p->status)) )
     {
@@ -130,13 +130,13 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned int 
virtual_irq,
     unsigned int nr_lrs = gic_get_nr_lrs();
     struct pending_irq *p = irq_to_pending(v, virtual_irq);
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     if ( unlikely(!p) )
         /* An unmapped LPI does not need to be raised. */
         return;
 
-    if ( v == current && list_empty(&v->arch.vgic.lr_pending) )
+    if ( v == current && list_empty(&v->arch.vgic->lr_pending) )
     {
         i = gic_find_unused_lr(v, p, 0);
 
@@ -156,7 +156,7 @@ static void gic_update_one_lr(struct vcpu *v, int i)
     int irq;
     struct gic_lr lr_val;
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
     ASSERT(!local_irq_is_enabled());
 
     gic_hw_ops->read_lr(i, &lr_val);
@@ -253,7 +253,7 @@ void vgic_sync_from_lrs(struct vcpu *v)
 
     gic_hw_ops->update_hcr_status(GICH_HCR_UIE, false);
 
-    spin_lock_irqsave(&v->arch.vgic.lock, flags);
+    spin_lock_irqsave(&v->arch.vgic->lock, flags);
 
     while ((i = find_next_bit((const unsigned long *) &this_cpu(lr_mask),
                               nr_lrs, i)) < nr_lrs ) {
@@ -261,7 +261,7 @@ void vgic_sync_from_lrs(struct vcpu *v)
         i++;
     }
 
-    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+    spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
 }
 
 static void gic_restore_pending_irqs(struct vcpu *v)
@@ -274,13 +274,13 @@ static void gic_restore_pending_irqs(struct vcpu *v)
 
     ASSERT(!local_irq_is_enabled());
 
-    spin_lock(&v->arch.vgic.lock);
+    spin_lock(&v->arch.vgic->lock);
 
-    if ( list_empty(&v->arch.vgic.lr_pending) )
+    if ( list_empty(&v->arch.vgic->lr_pending) )
         goto out;
 
-    inflight_r = &v->arch.vgic.inflight_irqs;
-    list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
+    inflight_r = &v->arch.vgic->inflight_irqs;
+    list_for_each_entry_safe ( p, t, &v->arch.vgic->lr_pending, lr_queue )
     {
         lr = gic_find_unused_lr(v, p, lr);
         if ( lr >= nr_lrs )
@@ -318,17 +318,17 @@ found:
     }
 
 out:
-    spin_unlock(&v->arch.vgic.lock);
+    spin_unlock(&v->arch.vgic->lock);
 }
 
 void gic_clear_pending_irqs(struct vcpu *v)
 {
     struct pending_irq *p, *t;
 
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     v->arch.lr_mask = 0;
-    list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
+    list_for_each_entry_safe ( p, t, &v->arch.vgic->lr_pending, lr_queue )
         gic_remove_from_lr_pending(v, p);
 }
 
@@ -357,14 +357,14 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
     mask_priority = gic_hw_ops->read_vmcr_priority();
     active_priority = find_first_bit(&apr, 32);
 
-    spin_lock_irqsave(&v->arch.vgic.lock, flags);
+    spin_lock_irqsave(&v->arch.vgic->lock, flags);
 
     /* TODO: We order the guest irqs by priority, but we don't change
      * the priority of host irqs. */
 
     /* find the first enabled non-active irq, the queue is already
      * ordered by priority */
-    list_for_each_entry( p, &v->arch.vgic.inflight_irqs, inflight )
+    list_for_each_entry( p, &v->arch.vgic->inflight_irqs, inflight )
     {
         if ( GIC_PRI_TO_GUEST(p->priority) >= mask_priority )
             goto out;
@@ -378,7 +378,7 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
     }
 
 out:
-    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+    spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
     return rc;
 }
 
@@ -388,7 +388,7 @@ void vgic_sync_to_lrs(void)
 
     gic_restore_pending_irqs(current);
 
-    if ( !list_empty(&current->arch.vgic.lr_pending) && lr_all_full() )
+    if ( !list_empty(&current->arch.vgic->lr_pending) && lr_all_full() )
         gic_hw_ops->update_hcr_status(GICH_HCR_UIE, true);
 }
 
@@ -396,10 +396,10 @@ void gic_dump_vgic_info(struct vcpu *v)
 {
     struct pending_irq *p;
 
-    list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
+    list_for_each_entry ( p, &v->arch.vgic->inflight_irqs, inflight )
         printk("Inflight irq=%u lr=%u\n", p->irq, p->lr);
 
-    list_for_each_entry( p, &v->arch.vgic.lr_pending, lr_queue )
+    list_for_each_entry( p, &v->arch.vgic->lr_pending, lr_queue )
         printk("Pending irq=%d\n", p->irq);
 }
 
diff --git a/xen/arch/arm/include/asm/domain.h 
b/xen/arch/arm/include/asm/domain.h
index 758ad807e4..6cfa793828 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -230,7 +230,7 @@ struct arch_vcpu
     union gic_state_data gic;
     uint64_t lr_mask;
 
-    struct vgic_cpu vgic;
+    struct vgic_cpu *vgic;
 
     /* Timer registers  */
     register_t cntkctl;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 77aab5c3c2..a9bb7e8906 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -162,10 +162,10 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
             goto read_as_zero_32;
         if ( dabt.size != DABT_WORD ) goto bad_width;
 
-        spin_lock_irqsave(&v->arch.vgic.lock, flags);
-        *r = vreg_reg32_extract(!!(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED),
+        spin_lock_irqsave(&v->arch.vgic->lock, flags);
+        *r = vreg_reg32_extract(!!(v->arch.vgic->flags & VGIC_V3_LPIS_ENABLED),
                                 info);
-        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
         return 1;
     }
 
@@ -195,7 +195,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
         /* We use the VCPU ID as the redistributor ID in bits[23:8] */
         typer |= v->vcpu_id << GICR_TYPER_PROC_NUM_SHIFT;
 
-        if ( v->arch.vgic.flags & VGIC_V3_RDIST_LAST )
+        if ( v->arch.vgic->flags & VGIC_V3_RDIST_LAST )
             typer |= GICR_TYPER_LAST;
 
         if ( v->domain->arch.vgic.has_its )
@@ -249,7 +249,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
             goto read_as_zero_64;
         if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
 
-        val = read_atomic(&v->arch.vgic.rdist_pendbase);
+        val = read_atomic(&v->arch.vgic->rdist_pendbase);
         val &= ~GICR_PENDBASER_PTZ;      /* WO, reads as 0 */
         *r = vreg_reg64_extract(val, info);
         return 1;
@@ -467,7 +467,7 @@ static void vgic_vcpu_enable_lpis(struct vcpu *v)
         smp_mb();
     }
 
-    v->arch.vgic.flags |= VGIC_V3_LPIS_ENABLED;
+    v->arch.vgic->flags |= VGIC_V3_LPIS_ENABLED;
 }
 
 static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
@@ -488,14 +488,14 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, 
mmio_info_t *info,
         if ( dabt.size != DABT_WORD ) goto bad_width;
 
         vgic_lock(v);                   /* protects rdists_enabled */
-        spin_lock_irqsave(&v->arch.vgic.lock, flags);
+        spin_lock_irqsave(&v->arch.vgic->lock, flags);
 
         /* LPIs can only be enabled once, but never disabled again. */
         if ( (r & GICR_CTLR_ENABLE_LPIS) &&
-             !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) )
+             !(v->arch.vgic->flags & VGIC_V3_LPIS_ENABLED) )
             vgic_vcpu_enable_lpis(v);
 
-        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
         vgic_unlock(v);
 
         return 1;
@@ -565,18 +565,18 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, 
mmio_info_t *info,
             goto write_ignore_64;
         if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
 
-        spin_lock_irqsave(&v->arch.vgic.lock, flags);
+        spin_lock_irqsave(&v->arch.vgic->lock, flags);
 
         /* Writing PENDBASER with LPIs enabled is UNPREDICTABLE. */
-        if ( !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) )
+        if ( !(v->arch.vgic->flags & VGIC_V3_LPIS_ENABLED) )
         {
-            reg = read_atomic(&v->arch.vgic.rdist_pendbase);
+            reg = read_atomic(&v->arch.vgic->rdist_pendbase);
             vreg_reg64_update(&reg, r, info);
             reg = sanitize_pendbaser(reg);
-            write_atomic(&v->arch.vgic.rdist_pendbase, reg);
+            write_atomic(&v->arch.vgic->rdist_pendbase, reg);
         }
 
-        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
 
         return 1;
     }
@@ -1115,7 +1115,7 @@ static struct vcpu *get_vcpu_from_rdist(struct domain *d,
 
     v = d->vcpu[vcpu_id];
 
-    *offset = gpa - v->arch.vgic.rdist_base;
+    *offset = gpa - v->arch.vgic->rdist_base;
 
     return v;
 }
@@ -1745,7 +1745,7 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
         return -EINVAL;
     }
 
-    v->arch.vgic.rdist_base = rdist_base;
+    v->arch.vgic->rdist_base = rdist_base;
 
     /*
      * If the redistributor is the last one of the
@@ -1756,7 +1756,7 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
     last_cpu = (region->size / GICV3_GICR_SIZE) + region->first_cpu - 1;
 
     if ( v->vcpu_id == last_cpu || (v->vcpu_id == (d->max_vcpus - 1)) )
-        v->arch.vgic.flags |= VGIC_V3_RDIST_LAST;
+        v->arch.vgic->flags |= VGIC_V3_RDIST_LAST;
 
     return 0;
 }
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 3ebdf9953f..8b17871b86 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -84,7 +84,7 @@ static inline struct vgic_irq_rank *vgic_get_rank(struct vcpu 
*v,
                                                   unsigned int rank)
 {
     if ( rank == 0 )
-        return v->arch.vgic.private_irqs;
+        return v->arch.vgic->private_irqs;
     else if ( rank <= DOMAIN_NR_RANKS(v->domain) )
         return &v->domain->arch.vgic.shared_irqs[rank - 1];
     else if ( is_valid_espi_rank(v->domain, rank) )
@@ -370,29 +370,35 @@ int vcpu_vgic_init(struct vcpu *v)
 {
     int i;
 
-    v->arch.vgic.private_irqs = xzalloc(struct vgic_irq_rank);
-    if ( v->arch.vgic.private_irqs == NULL )
+    v->arch.vgic = xzalloc(struct vgic_cpu);
+    if ( v->arch.vgic == NULL )
+        return -ENOMEM;
+
+    v->arch.vgic->private_irqs = xzalloc(struct vgic_irq_rank);
+    if ( v->arch.vgic->private_irqs == NULL )
       return -ENOMEM;
 
     /* SGIs/PPIs are always routed to this VCPU */
-    vgic_rank_init(v->arch.vgic.private_irqs, 0, v->vcpu_id);
+    vgic_rank_init(v->arch.vgic->private_irqs, 0, v->vcpu_id);
 
     v->domain->arch.vgic.handler->vcpu_init(v);
 
-    memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs));
+    memset(&v->arch.vgic->pending_irqs, 0, sizeof(v->arch.vgic->pending_irqs));
     for (i = 0; i < 32; i++)
-        vgic_init_pending_irq(&v->arch.vgic.pending_irqs[i], i);
+        vgic_init_pending_irq(&v->arch.vgic->pending_irqs[i], i);
 
-    INIT_LIST_HEAD(&v->arch.vgic.inflight_irqs);
-    INIT_LIST_HEAD(&v->arch.vgic.lr_pending);
-    spin_lock_init(&v->arch.vgic.lock);
+    INIT_LIST_HEAD(&v->arch.vgic->inflight_irqs);
+    INIT_LIST_HEAD(&v->arch.vgic->lr_pending);
+    spin_lock_init(&v->arch.vgic->lock);
 
     return 0;
 }
 
 int vcpu_vgic_free(struct vcpu *v)
 {
-    xfree(v->arch.vgic.private_irqs);
+    xfree(v->arch.vgic->private_irqs);
+    xfree(v->arch.vgic);
+
     return 0;
 }
 
@@ -423,14 +429,14 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     /* This will never be called for an LPI, as we don't migrate them. */
     ASSERT(!is_lpi(irq));
 
-    spin_lock_irqsave(&old->arch.vgic.lock, flags);
+    spin_lock_irqsave(&old->arch.vgic->lock, flags);
 
     p = irq_to_pending(old, irq);
 
     /* nothing to do for virtual interrupts */
     if ( p->desc == NULL )
     {
-        spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&old->arch.vgic->lock, flags);
         return true;
     }
 
@@ -438,7 +444,7 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     if ( test_bit(GIC_IRQ_GUEST_MIGRATING, &p->status) )
     {
         gprintk(XENLOG_WARNING, "irq %u migration failed: requested while in 
progress\n", irq);
-        spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&old->arch.vgic->lock, flags);
         return false;
     }
 
@@ -447,7 +453,7 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     if ( list_empty(&p->inflight) )
     {
         irq_set_affinity(p->desc, cpumask_of(new->processor));
-        spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&old->arch.vgic->lock, flags);
         return true;
     }
     /* If the IRQ is still lr_pending, re-inject it to the new vcpu */
@@ -455,7 +461,7 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     {
         vgic_remove_irq_from_queues(old, p);
         irq_set_affinity(p->desc, cpumask_of(new->processor));
-        spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&old->arch.vgic->lock, flags);
         vgic_inject_irq(new->domain, new, irq, true);
         return true;
     }
@@ -464,7 +470,7 @@ bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
     if ( !list_empty(&p->inflight) )
         set_bit(GIC_IRQ_GUEST_MIGRATING, &p->status);
 
-    spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
+    spin_unlock_irqrestore(&old->arch.vgic->lock, flags);
     return true;
 }
 
@@ -516,12 +522,12 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, 
unsigned int n)
         irq = i + (32 * n);
         v_target = vgic_get_target_vcpu(v, irq);
 
-        spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
+        spin_lock_irqsave(&v_target->arch.vgic->lock, flags);
         p = irq_to_pending(v_target, irq);
         clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
         gic_remove_from_lr_pending(v_target, p);
         desc = p->desc;
-        spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v_target->arch.vgic->lock, flags);
 
         if ( desc != NULL )
         {
@@ -567,12 +573,12 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, 
unsigned int n)
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
         v_target = vgic_get_target_vcpu(v, irq);
-        spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
+        spin_lock_irqsave(&v_target->arch.vgic->lock, flags);
         p = irq_to_pending(v_target, irq);
         set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
         if ( !list_empty(&p->inflight) && !test_bit(GIC_IRQ_GUEST_VISIBLE, 
&p->status) )
             gic_raise_guest_irq(v_target, irq, p->priority);
-        spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v_target->arch.vgic->lock, flags);
         if ( p->desc != NULL )
         {
             irq_set_affinity(p->desc, cpumask_of(v_target->processor));
@@ -701,7 +707,7 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned 
int irq)
     /* Pending irqs allocation strategy: the first vgic.nr_spis irqs
      * are used for SPIs; the rests are used for per cpu irqs */
     if ( irq < 32 )
-        n = &v->arch.vgic.pending_irqs[irq];
+        n = &v->arch.vgic->pending_irqs[irq];
     else if ( is_lpi(irq) )
         n = v->domain->arch.vgic.handler->lpi_to_pending(v->domain, irq);
     else
@@ -734,16 +740,16 @@ void vgic_clear_pending_irqs(struct vcpu *v)
     struct pending_irq *p, *t;
     unsigned long flags;
 
-    spin_lock_irqsave(&v->arch.vgic.lock, flags);
-    list_for_each_entry_safe ( p, t, &v->arch.vgic.inflight_irqs, inflight )
+    spin_lock_irqsave(&v->arch.vgic->lock, flags);
+    list_for_each_entry_safe ( p, t, &v->arch.vgic->inflight_irqs, inflight )
         list_del_init(&p->inflight);
     gic_clear_pending_irqs(v);
-    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+    spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
 }
 
 void vgic_remove_irq_from_queues(struct vcpu *v, struct pending_irq *p)
 {
-    ASSERT(spin_is_locked(&v->arch.vgic.lock));
+    ASSERT(spin_is_locked(&v->arch.vgic->lock));
 
     clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
     list_del_init(&p->inflight);
@@ -772,20 +778,20 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
         v = vgic_get_target_vcpu(d->vcpu[0], virq);
     };
 
-    spin_lock_irqsave(&v->arch.vgic.lock, flags);
+    spin_lock_irqsave(&v->arch.vgic->lock, flags);
 
     n = irq_to_pending(v, virq);
     /* If an LPI has been removed, there is nothing to inject here. */
     if ( unlikely(!n) )
     {
-        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
         return;
     }
 
     /* vcpu offline */
     if ( test_bit(_VPF_down, &v->pause_flags) )
     {
-        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
         return;
     }
 
@@ -804,7 +810,7 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
     if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
         gic_raise_guest_irq(v, virq, priority);
 
-    list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight )
+    list_for_each_entry ( iter, &v->arch.vgic->inflight_irqs, inflight )
     {
         if ( iter->priority > priority )
         {
@@ -812,9 +818,9 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
             goto out;
         }
     }
-    list_add_tail(&n->inflight, &v->arch.vgic.inflight_irqs);
+    list_add_tail(&n->inflight, &v->arch.vgic->inflight_irqs);
 out:
-    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+    spin_unlock_irqrestore(&v->arch.vgic->lock, flags);
 
     /* we have a new higher priority irq, inject it into the guest */
     vcpu_kick(v);
@@ -924,7 +930,7 @@ void vgic_check_inflight_irqs_pending(struct vcpu *v, 
unsigned int rank, uint32_
 
         v_target = vgic_get_target_vcpu(v, irq);
 
-        spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
+        spin_lock_irqsave(&v_target->arch.vgic->lock, flags);
 
         p = irq_to_pending(v_target, irq);
 
@@ -933,7 +939,7 @@ void vgic_check_inflight_irqs_pending(struct vcpu *v, 
unsigned int rank, uint32_
                    "%pv trying to clear pending interrupt %u.\n",
                    v, irq);
 
-        spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
+        spin_unlock_irqrestore(&v_target->arch.vgic->lock, flags);
     }
 }
 
diff --git a/xen/arch/arm/vgic/vgic-init.c b/xen/arch/arm/vgic/vgic-init.c
index f8d7d3a226..67f297797f 100644
--- a/xen/arch/arm/vgic/vgic-init.c
+++ b/xen/arch/arm/vgic/vgic-init.c
@@ -57,7 +57,7 @@
  */
 static void vgic_vcpu_early_init(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
     unsigned int i;
 
     INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
@@ -202,6 +202,10 @@ int vcpu_vgic_init(struct vcpu *v)
 {
     int ret = 0;
 
+    v->arch.vgic = xzalloc(struct vgic_cpu);
+    if ( v->arch.vgic == NULL )
+        return -ENOMEM;
+
     vgic_vcpu_early_init(v);
 
     if ( gic_hw_version() == GIC_V2 )
@@ -241,10 +245,12 @@ void domain_vgic_free(struct domain *d)
 
 int vcpu_vgic_free(struct vcpu *v)
 {
-    struct vgic_cpu *vgic_cpu = &v->arch.vgic;
+    struct vgic_cpu *vgic_cpu = v->arch.vgic;
 
     INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
 
+    xfree(vgic_cpu);
+
     return 0;
 }
 
diff --git a/xen/arch/arm/vgic/vgic-v2.c b/xen/arch/arm/vgic/vgic-v2.c
index 6a558089c5..e64d681dd2 100644
--- a/xen/arch/arm/vgic/vgic-v2.c
+++ b/xen/arch/arm/vgic/vgic-v2.c
@@ -56,8 +56,8 @@ void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, paddr_t 
csize,
  */
 void vgic_v2_fold_lr_state(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
-    unsigned int used_lrs = vcpu->arch.vgic.used_lrs;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
+    unsigned int used_lrs = vcpu->arch.vgic->used_lrs;
     unsigned long flags;
     unsigned int lr;
 
diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
index b2c0e1873a..146bd124c3 100644
--- a/xen/arch/arm/vgic/vgic.c
+++ b/xen/arch/arm/vgic/vgic.c
@@ -40,8 +40,8 @@
  * When taking more than one ap_list_lock at the same time, always take the
  * lowest numbered VCPU's ap_list_lock first, so:
  *   vcpuX->vcpu_id < vcpuY->vcpu_id:
- *     spin_lock(vcpuX->arch.vgic.ap_list_lock);
- *     spin_lock(vcpuY->arch.vgic.ap_list_lock);
+ *     spin_lock(vcpuX->arch.vgic->ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic->ap_list_lock);
  *
  * Since the VGIC must support injecting virtual interrupts from ISRs, we have
  * to use the spin_lock_irqsave/spin_unlock_irqrestore versions of outer
@@ -102,7 +102,7 @@ struct vgic_irq *vgic_get_irq(struct domain *d, struct vcpu 
*vcpu,
 {
     /* SGIs and PPIs */
     if ( intid <= VGIC_MAX_PRIVATE )
-        return &vcpu->arch.vgic.private_irqs[intid];
+        return &vcpu->arch.vgic->private_irqs[intid];
 
     /* SPIs */
     if ( intid <= VGIC_MAX_SPI )
@@ -245,7 +245,7 @@ out:
 /* Must be called with the ap_list_lock held */
 static void vgic_sort_ap_list(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
 
     ASSERT(spin_is_locked(&vgic_cpu->ap_list_lock));
 
@@ -323,7 +323,7 @@ retry:
 
     /* someone can do stuff here, which we re-check below */
 
-    spin_lock_irqsave(&vcpu->arch.vgic.ap_list_lock, flags);
+    spin_lock_irqsave(&vcpu->arch.vgic->ap_list_lock, flags);
     spin_lock(&irq->irq_lock);
 
     /*
@@ -341,7 +341,7 @@ retry:
     if ( unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq)) )
     {
         spin_unlock(&irq->irq_lock);
-        spin_unlock_irqrestore(&vcpu->arch.vgic.ap_list_lock, flags);
+        spin_unlock_irqrestore(&vcpu->arch.vgic->ap_list_lock, flags);
 
         spin_lock_irqsave(&irq->irq_lock, flags);
         goto retry;
@@ -352,11 +352,11 @@ retry:
      * now in the ap_list.
      */
     vgic_get_irq_kref(irq);
-    list_add_tail(&irq->ap_list, &vcpu->arch.vgic.ap_list_head);
+    list_add_tail(&irq->ap_list, &vcpu->arch.vgic->ap_list_head);
     irq->vcpu = vcpu;
 
     spin_unlock(&irq->irq_lock);
-    spin_unlock_irqrestore(&vcpu->arch.vgic.ap_list_lock, flags);
+    spin_unlock_irqrestore(&vcpu->arch.vgic->ap_list_lock, flags);
 
     vcpu_kick(vcpu);
 
@@ -422,7 +422,7 @@ void vgic_inject_irq(struct domain *d, struct vcpu *vcpu, 
unsigned int intid,
  */
 static void vgic_prune_ap_list(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
     struct vgic_irq *irq, *tmp;
     unsigned long flags;
 
@@ -487,8 +487,8 @@ retry:
             vcpuB = vcpu;
         }
 
-        spin_lock_irqsave(&vcpuA->arch.vgic.ap_list_lock, flags);
-        spin_lock(&vcpuB->arch.vgic.ap_list_lock);
+        spin_lock_irqsave(&vcpuA->arch.vgic->ap_list_lock, flags);
+        spin_lock(&vcpuB->arch.vgic->ap_list_lock);
         spin_lock(&irq->irq_lock);
 
         /*
@@ -502,7 +502,7 @@ retry:
          */
         if ( target_vcpu == vgic_target_oracle(irq) )
         {
-            struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic;
+            struct vgic_cpu *new_cpu = target_vcpu->arch.vgic;
 
             list_del(&irq->ap_list);
             irq->vcpu = target_vcpu;
@@ -510,8 +510,8 @@ retry:
         }
 
         spin_unlock(&irq->irq_lock);
-        spin_unlock(&vcpuB->arch.vgic.ap_list_lock);
-        spin_unlock_irqrestore(&vcpuA->arch.vgic.ap_list_lock, flags);
+        spin_unlock(&vcpuB->arch.vgic->ap_list_lock);
+        spin_unlock_irqrestore(&vcpuA->arch.vgic->ap_list_lock, flags);
         goto retry;
     }
 
@@ -542,7 +542,7 @@ static void vgic_set_underflow(struct vcpu *vcpu)
 /* Requires the ap_list_lock to be held. */
 static int compute_ap_list_depth(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
     struct vgic_irq *irq;
     int count = 0;
 
@@ -557,7 +557,7 @@ static int compute_ap_list_depth(struct vcpu *vcpu)
 /* Requires the VCPU's ap_list_lock to be held. */
 static void vgic_flush_lr_state(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
     struct vgic_irq *irq;
     int count = 0;
 
@@ -583,7 +583,7 @@ static void vgic_flush_lr_state(struct vcpu *vcpu)
         }
     }
 
-    vcpu->arch.vgic.used_lrs = count;
+    vcpu->arch.vgic->used_lrs = count;
 }
 
 /**
@@ -600,7 +600,7 @@ static void vgic_flush_lr_state(struct vcpu *vcpu)
 void vgic_sync_from_lrs(struct vcpu *vcpu)
 {
     /* An empty ap_list_head implies used_lrs == 0 */
-    if ( list_empty(&vcpu->arch.vgic.ap_list_head) )
+    if ( list_empty(&vcpu->arch.vgic->ap_list_head) )
         return;
 
     vgic_fold_lr_state(vcpu);
@@ -628,14 +628,14 @@ void vgic_sync_to_lrs(void)
      * and introducing additional synchronization mechanism doesn't change
      * this.
      */
-    if ( list_empty(&current->arch.vgic.ap_list_head) )
+    if ( list_empty(&current->arch.vgic->ap_list_head) )
         return;
 
     ASSERT(!local_irq_is_enabled());
 
-    spin_lock(&current->arch.vgic.ap_list_lock);
+    spin_lock(&current->arch.vgic->ap_list_lock);
     vgic_flush_lr_state(current);
-    spin_unlock(&current->arch.vgic.ap_list_lock);
+    spin_unlock(&current->arch.vgic->ap_list_lock);
 
     gic_hw_ops->update_hcr_status(GICH_HCR_EN, 1);
 }
@@ -652,7 +652,7 @@ void vgic_sync_to_lrs(void)
  */
 int vgic_vcpu_pending_irq(struct vcpu *vcpu)
 {
-    struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic;
+    struct vgic_cpu *vgic_cpu = vcpu->arch.vgic;
     struct vgic_irq *irq;
     unsigned long flags;
     int ret = 0;
@@ -761,11 +761,11 @@ void vgic_free_virq(struct domain *d, unsigned int virq)
 
 void gic_dump_vgic_info(struct vcpu *v)
 {
-    struct vgic_cpu *vgic_cpu = &v->arch.vgic;
+    struct vgic_cpu *vgic_cpu = v->arch.vgic;
     struct vgic_irq *irq;
     unsigned long flags;
 
-    spin_lock_irqsave(&v->arch.vgic.ap_list_lock, flags);
+    spin_lock_irqsave(&v->arch.vgic->ap_list_lock, flags);
 
     if ( !list_empty(&vgic_cpu->ap_list_head) )
         printk("   active or pending interrupts queued:\n");
@@ -781,7 +781,7 @@ void gic_dump_vgic_info(struct vcpu *v)
         spin_unlock(&irq->irq_lock);
     }
 
-    spin_unlock_irqrestore(&v->arch.vgic.ap_list_lock, flags);
+    spin_unlock_irqrestore(&v->arch.vgic->ap_list_lock, flags);
 }
 
 void vgic_clear_pending_irqs(struct vcpu *v)
-- 
2.52.0




 


Rackspace

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