int cpumask_to_xenctl_cpumap( struct xenctl_cpumap *xenctl_cpumap, const cpumask_t *cpumask) { unsigned int guest_bytes, copy_bytes, i; uint8_t zero = 0; int err = 0; uint8_t *bytemap = xmalloc_array(uint8_t, (nr_cpu_ids + 7) / 8); if ( !bytemap ) return -ENOMEM; guest_bytes = (xenctl_cpumap->nr_cpus + 7) / 8; copy_bytes = min_t(unsigned int, guest_bytes, (nr_cpu_ids + 7) / 8); bitmap_long_to_byte(bytemap, cpumask_bits(cpumask), nr_cpu_ids); if ( copy_bytes != 0 ) if ( copy_to_guest(xenctl_cpumap->bitmap, bytemap, copy_bytes) ) err = -EFAULT; for ( i = copy_bytes; !err && i < guest_bytes; i++ ) if ( copy_to_guest_offset(xenctl_cpumap->bitmap, i, &zero, 1) ) err = -EFAULT; xfree(bytemap); return err; }
struct domain *alloc_domain_struct(void) { struct domain *d; BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE); d = alloc_xenheap_pages(0, 0); if ( d == NULL ) return NULL; clear_page(d); d->arch.grant_table_gpfn = xmalloc_array(xen_pfn_t, max_nr_grant_frames); return d; }
struct domain *domain_create( domid_t domid, unsigned int domcr_flags, ssidref_t ssidref) { struct domain *d, **pd; enum { INIT_xsm = 1u<<0, INIT_watchdog = 1u<<1, INIT_rangeset = 1u<<2, INIT_evtchn = 1u<<3, INIT_gnttab = 1u<<4, INIT_arch = 1u<<5 }; int init_status = 0; int poolid = CPUPOOLID_NONE; if ( (d = alloc_domain_struct()) == NULL ) return NULL; d->domain_id = domid; lock_profile_register_struct(LOCKPROF_TYPE_PERDOM, d, domid, "Domain"); if ( xsm_alloc_security_domain(d) != 0 ) goto fail; init_status |= INIT_xsm; watchdog_domain_init(d); init_status |= INIT_watchdog; atomic_set(&d->refcnt, 1); spin_lock_init_prof(d, domain_lock); spin_lock_init_prof(d, page_alloc_lock); spin_lock_init(&d->hypercall_deadlock_mutex); INIT_PAGE_LIST_HEAD(&d->page_list); INIT_PAGE_LIST_HEAD(&d->xenpage_list); spin_lock_init(&d->node_affinity_lock); spin_lock_init(&d->shutdown_lock); d->shutdown_code = -1; if ( domcr_flags & DOMCRF_hvm ) d->is_hvm = 1; if ( domid == 0 ) { d->is_pinned = opt_dom0_vcpus_pin; d->disable_migrate = 1; } rangeset_domain_initialise(d); init_status |= INIT_rangeset; d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); d->irq_caps = rangeset_new(d, "Interrupts", 0); if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) goto fail; if ( domcr_flags & DOMCRF_dummy ) return d; if ( !is_idle_domain(d) ) { if ( xsm_domain_create(d, ssidref) != 0 ) goto fail; d->is_paused_by_controller = 1; atomic_inc(&d->pause_count); if ( domid ) d->nr_pirqs = nr_irqs_gsi + extra_domU_irqs; else d->nr_pirqs = nr_irqs_gsi + extra_dom0_irqs; if ( d->nr_pirqs > nr_irqs ) d->nr_pirqs = nr_irqs; d->pirq_to_evtchn = xmalloc_array(u16, d->nr_pirqs); d->pirq_mask = xmalloc_array( unsigned long, BITS_TO_LONGS(d->nr_pirqs)); if ( (d->pirq_to_evtchn == NULL) || (d->pirq_mask == NULL) ) goto fail; memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn)); bitmap_zero(d->pirq_mask, d->nr_pirqs); if ( evtchn_init(d) != 0 ) goto fail; init_status |= INIT_evtchn; if ( grant_table_create(d) != 0 ) goto fail; init_status |= INIT_gnttab; poolid = 0; d->mem_event = xzalloc(struct mem_event_per_domain); if ( !d->mem_event ) goto fail; } if ( arch_domain_create(d, domcr_flags) != 0 ) goto fail; init_status |= INIT_arch; if ( cpupool_add_domain(d, poolid) != 0 ) goto fail; if ( sched_init_domain(d) != 0 ) goto fail; if ( !is_idle_domain(d) ) { spin_lock(&domlist_update_lock); pd = &domain_list; /* NB. domain_list maintained in order of domid. */ for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) if ( (*pd)->domain_id > d->domain_id ) break; d->next_in_list = *pd; d->next_in_hashbucket = domain_hash[DOMAIN_HASH(domid)]; rcu_assign_pointer(*pd, d); rcu_assign_pointer(domain_hash[DOMAIN_HASH(domid)], d); spin_unlock(&domlist_update_lock); } return d; fail: d->is_dying = DOMDYING_dead; atomic_set(&d->refcnt, DOMAIN_DESTROYED); xfree(d->mem_event); if ( init_status & INIT_arch ) arch_domain_destroy(d); if ( init_status & INIT_gnttab ) grant_table_destroy(d); if ( init_status & INIT_evtchn ) { evtchn_destroy(d); evtchn_destroy_final(d); } if ( init_status & INIT_rangeset ) rangeset_domain_destroy(d); if ( init_status & INIT_watchdog ) watchdog_domain_destroy(d); if ( init_status & INIT_xsm ) xsm_free_security_domain(d); xfree(d->pirq_mask); xfree(d->pirq_to_evtchn); free_domain_struct(d); return NULL; }