int domain_vgic_init(struct domain *d) { int i; d->arch.vgic.ctlr = 0; if ( is_hardware_domain(d) ) d->arch.vgic.nr_spis = gic_number_lines() - 32; else d->arch.vgic.nr_spis = 0; /* We don't need SPIs for the guest */ switch ( gic_hw_version() ) { #ifdef CONFIG_ARM_64 case GIC_V3: if ( vgic_v3_init(d) ) return -ENODEV; break; #endif case GIC_V2: if ( vgic_v2_init(d) ) return -ENODEV; break; default: return -ENODEV; } spin_lock_init(&d->arch.vgic.lock); d->arch.vgic.shared_irqs = xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); if ( d->arch.vgic.shared_irqs == NULL ) return -ENOMEM; d->arch.vgic.pending_irqs = xzalloc_array(struct pending_irq, d->arch.vgic.nr_spis); if ( d->arch.vgic.pending_irqs == NULL ) return -ENOMEM; for (i=0; i<d->arch.vgic.nr_spis; i++) { INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].inflight); INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].lr_queue); } for (i=0; i<DOMAIN_NR_RANKS(d); i++) spin_lock_init(&d->arch.vgic.shared_irqs[i].lock); d->arch.vgic.handler->domain_init(d); d->arch.vgic.allocated_irqs = xzalloc_array(unsigned long, BITS_TO_LONGS(vgic_num_irqs(d))); if ( !d->arch.vgic.allocated_irqs ) return -ENOMEM; /* vIRQ0-15 (SGIs) are reserved */ for ( i = 0; i < NR_GIC_SGI; i++ ) set_bit(i, d->arch.vgic.allocated_irqs); return 0; }
static int domain_vgic_register(struct domain *d) { switch ( d->arch.vgic.version ) { #ifdef CONFIG_HAS_GICV3 case GIC_V3: if ( vgic_v3_init(d) ) return -ENODEV; break; #endif case GIC_V2: if ( vgic_v2_init(d) ) return -ENODEV; break; default: printk(XENLOG_G_ERR "d%d: Unknown vGIC version %u\n", d->domain_id, d->arch.vgic.version); return -ENODEV; } return 0; }
int domain_vgic_init(struct domain *d, unsigned int nr_spis) { int i; int ret; d->arch.vgic.ctlr = 0; /* Limit the number of virtual SPIs supported to (1020 - 32) = 988 */ if ( nr_spis > (1020 - NR_LOCAL_IRQS) ) return -EINVAL; d->arch.vgic.nr_spis = nr_spis; switch ( d->arch.vgic.version ) { #ifdef CONFIG_HAS_GICV3 case GIC_V3: if ( vgic_v3_init(d) ) return -ENODEV; break; #endif case GIC_V2: if ( vgic_v2_init(d) ) return -ENODEV; break; default: printk(XENLOG_G_ERR "d%d: Unknown vGIC version %u\n", d->domain_id, d->arch.vgic.version); return -ENODEV; } spin_lock_init(&d->arch.vgic.lock); d->arch.vgic.shared_irqs = xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); if ( d->arch.vgic.shared_irqs == NULL ) return -ENOMEM; d->arch.vgic.pending_irqs = xzalloc_array(struct pending_irq, d->arch.vgic.nr_spis); if ( d->arch.vgic.pending_irqs == NULL ) return -ENOMEM; for (i=0; i<d->arch.vgic.nr_spis; i++) vgic_init_pending_irq(&d->arch.vgic.pending_irqs[i], i + 32); /* SPIs are routed to VCPU0 by default */ for ( i = 0; i < DOMAIN_NR_RANKS(d); i++ ) vgic_rank_init(&d->arch.vgic.shared_irqs[i], i + 1, 0); ret = d->arch.vgic.handler->domain_init(d); if ( ret ) return ret; d->arch.vgic.allocated_irqs = xzalloc_array(unsigned long, BITS_TO_LONGS(vgic_num_irqs(d))); if ( !d->arch.vgic.allocated_irqs ) return -ENOMEM; /* vIRQ0-15 (SGIs) are reserved */ for ( i = 0; i < NR_GIC_SGI; i++ ) set_bit(i, d->arch.vgic.allocated_irqs); return 0; }