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; ret = domain_vgic_register(d); if ( ret < 0 ) return ret; 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; }
int arch_domain_create(struct domain *d, unsigned int domcr_flags, struct xen_arch_domainconfig *config) { int rc, count = 0; BUILD_BUG_ON(GUEST_MAX_VCPUS < MAX_VIRT_CPUS); d->arch.relmem = RELMEM_not_started; /* Idle domains do not need this setup */ if ( is_idle_domain(d) ) return 0; ASSERT(config != NULL); /* p2m_init relies on some value initialized by the IOMMU subsystem */ if ( (rc = iommu_domain_init(d)) != 0 ) goto fail; if ( (rc = p2m_init(d)) != 0 ) goto fail; rc = -ENOMEM; if ( (d->shared_info = alloc_xenheap_pages(0, 0)) == NULL ) goto fail; /* Default the virtual ID to match the physical */ d->arch.vpidr = boot_cpu_data.midr.bits; clear_page(d->shared_info); share_xen_page_with_guest( virt_to_page(d->shared_info), d, XENSHARE_writable); switch ( config->gic_version ) { case XEN_DOMCTL_CONFIG_GIC_NATIVE: switch ( gic_hw_version () ) { case GIC_V2: config->gic_version = XEN_DOMCTL_CONFIG_GIC_V2; d->arch.vgic.version = GIC_V2; break; case GIC_V3: config->gic_version = XEN_DOMCTL_CONFIG_GIC_V3; d->arch.vgic.version = GIC_V3; break; default: BUG(); } break; case XEN_DOMCTL_CONFIG_GIC_V2: d->arch.vgic.version = GIC_V2; break; case XEN_DOMCTL_CONFIG_GIC_V3: d->arch.vgic.version = GIC_V3; break; default: rc = -EOPNOTSUPP; goto fail; } if ( (rc = domain_vgic_register(d, &count)) != 0 ) goto fail; if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 ) goto fail; if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 ) goto fail; if ( (rc = domain_vtimer_init(d, config)) != 0 ) goto fail; update_domain_wallclock_time(d); /* * The hardware domain will get a PPI later in * arch/arm/domain_build.c depending on the * interrupt map of the hardware. */ if ( !is_hardware_domain(d) ) { d->arch.evtchn_irq = GUEST_EVTCHN_PPI; /* At this stage vgic_reserve_virq should never fail */ if ( !vgic_reserve_virq(d, GUEST_EVTCHN_PPI) ) BUG(); } /* * Virtual UART is only used by linux early printk and decompress code. * Only use it for the hardware domain because the linux kernel may not * support multi-platform. */ if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) ) goto fail; return 0; fail: d->is_dying = DOMDYING_dead; arch_domain_destroy(d); return rc; }