[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 16/18] x86: add pv multidomain construction
This adds the ability to domain builder for the construction of multiple pv domains at boot. Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx> Reviewed-by: Christopher Clark <christopher.clark@xxxxxxxxxx> --- xen/arch/x86/dom0_build.c | 31 ----- xen/arch/x86/domain_builder.c | 58 ++++++-- xen/arch/x86/include/asm/dom0_build.h | 2 - xen/arch/x86/include/asm/setup.h | 2 + xen/arch/x86/pv/Makefile | 2 +- .../x86/pv/{dom0_build.c => domain_builder.c} | 86 +++++++----- xen/common/domain-builder/Kconfig | 10 ++ xen/common/domain-builder/core.c | 130 ++++++++++++++++-- xen/include/xen/bootdomain.h | 6 + xen/include/xen/domain_builder.h | 19 +++ 10 files changed, 259 insertions(+), 87 deletions(-) rename xen/arch/x86/pv/{dom0_build.c => domain_builder.c} (92%) diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c index 0600773b8f..85a10f63aa 100644 --- a/xen/arch/x86/dom0_build.c +++ b/xen/arch/x86/dom0_build.c @@ -524,37 +524,6 @@ int __init dom0_setup_permissions(struct domain *d) return rc; } - -int __init construct_domain(struct boot_domain *bd) -{ - int rc = 0; - - /* Sanity! */ - BUG_ON(!pv_shim && bd->domid != 0); - BUG_ON(bd->domain->vcpu[0] == NULL); - BUG_ON(bd->domain->vcpu[0]->is_initialised); - - process_pending_softirqs(); - - if ( builder_is_initdom(bd) ) - { - if ( is_hvm_domain(bd->domain) ) - rc = dom0_construct_pvh(bd); - else if ( is_pv_domain(bd->domain) ) - rc = dom0_construct_pv(bd); - else - panic("Cannot construct Dom0. No guest interface available\n"); - } - - if ( rc ) - return rc; - - /* Sanity! */ - BUG_ON(!bd->domain->vcpu[0]->is_initialised); - - return 0; -} - /* * Local variables: * mode: C diff --git a/xen/arch/x86/domain_builder.c b/xen/arch/x86/domain_builder.c index d8babb1090..94f3ff4d5a 100644 --- a/xen/arch/x86/domain_builder.c +++ b/xen/arch/x86/domain_builder.c @@ -6,6 +6,7 @@ #include <xen/grant_table.h> #include <xen/iommu.h> #include <xen/sched.h> +#include <xen/softirq.h> #include <asm/pv/shim.h> #include <asm/dom0_build.h> @@ -189,18 +190,22 @@ void __init arch_create_dom( if ( !pv_shim && builder_is_ctldom(bd) ) is_privileged = CDF_privileged; - /* Create initial domain. Not d0 for pvshim. */ - bd->domid = get_initial_domain_id(); + /* Determine proper domain id. */ + if ( builder_is_initdom(bd) ) + bd->domid = get_initial_domain_id(); + else + bd->domid = bd->domid ? bd->domid : get_next_domid(); bd->domain = domain_create(bd->domid, &dom_cfg, is_privileged); if ( IS_ERR(bd->domain) ) panic("Error creating d%u: %ld\n", bd->domid, PTR_ERR(bd->domain)); - init_dom0_cpuid_policy(bd->domain); + if ( builder_is_initdom(bd) ) + init_dom0_cpuid_policy(bd->domain); if ( alloc_dom_vcpu0(bd) == NULL ) panic("Error creating d%uv0\n", bd->domid); - /* Grab the DOM0 command line. */ + /* Grab the command line. */ cmdline = (bd->kernel->string.kind == BOOTSTR_CMDLINE) ? bd->kernel->string.bytes : NULL; if ( cmdline || bi->arch->kextra ) @@ -210,15 +215,23 @@ void __init arch_create_dom( cmdline = arch_prepare_cmdline(cmdline, bi->arch); strlcpy(dom_cmdline, cmdline, MAX_GUEST_CMDLINE); - if ( bi->arch->kextra ) - /* kextra always includes exactly one leading space. */ - strlcat(dom_cmdline, bi->arch->kextra, MAX_GUEST_CMDLINE); + if ( builder_is_initdom(bd) ) + { + if ( bi->arch->kextra ) + /* kextra always includes exactly one leading space. */ + strlcat(dom_cmdline, bi->arch->kextra, MAX_GUEST_CMDLINE); - apply_xen_cmdline(dom_cmdline); + apply_xen_cmdline(dom_cmdline); + } strlcpy(bd->kernel->string.bytes, dom_cmdline, MAX_GUEST_CMDLINE); } + if ( alloc_system_evtchn(bi, bd) != 0 ) + printk(XENLOG_WARNING "%s: " + "unable set up system event channels for Dom%d\n", + __func__, bd->domid); + /* * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0(). * This saves a large number of corner cases interactions with @@ -240,3 +253,32 @@ void __init arch_create_dom( } } +int __init construct_domain(struct boot_domain *bd) +{ + int rc = 0; + + /* Sanity! */ + BUG_ON(bd->domid != bd->domain->domain_id); + BUG_ON(bd->domain->vcpu[0] == NULL); + BUG_ON(bd->domain->vcpu[0]->is_initialised); + + process_pending_softirqs(); + + if ( is_hvm_domain(bd->domain) ) + if ( builder_is_initdom(bd) ) + rc = dom0_construct_pvh(bd); + else + panic("Cannot construct HVM DomU. Not supported.\n"); + else if ( is_pv_domain(bd->domain) ) + rc = dom_construct_pv(bd); + else + panic("Cannot construct Dom0. No guest interface available\n"); + + if ( rc ) + return rc; + + /* Sanity! */ + BUG_ON(!bd->domain->vcpu[0]->is_initialised); + + return 0; +} diff --git a/xen/arch/x86/include/asm/dom0_build.h b/xen/arch/x86/include/asm/dom0_build.h index 6c26ab0878..3624a57641 100644 --- a/xen/arch/x86/include/asm/dom0_build.h +++ b/xen/arch/x86/include/asm/dom0_build.h @@ -22,8 +22,6 @@ unsigned long dom_compute_nr_pages( int dom0_setup_permissions(struct domain *d); -int dom0_construct_pv(struct boot_domain *bd); - int dom0_construct_pvh(struct boot_domain *bd); unsigned long dom0_paging_pages(const struct domain *d, diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h index 6f53623fb3..328f9a8611 100644 --- a/xen/arch/x86/include/asm/setup.h +++ b/xen/arch/x86/include/asm/setup.h @@ -36,6 +36,8 @@ static inline void vesa_init(void) {}; void apply_xen_cmdline(char *cmdline); int construct_domain(struct boot_domain *bd); +int dom_construct_pv(struct boot_domain *bd); + void setup_io_bitmap(struct domain *d); unsigned long initial_images_nrpages(nodeid_t node); diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile index 6cda354cc4..d06a3c1de1 100644 --- a/xen/arch/x86/pv/Makefile +++ b/xen/arch/x86/pv/Makefile @@ -15,5 +15,5 @@ obj-$(CONFIG_PV_SHIM) += shim.o obj-$(CONFIG_TRACEBUFFER) += trace.o obj-y += traps.o -obj-bin-y += dom0_build.init.o +obj-bin-y += domain_builder.init.o obj-bin-y += gpr_switch.o diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/domain_builder.c similarity index 92% rename from xen/arch/x86/pv/dom0_build.c rename to xen/arch/x86/pv/domain_builder.c index ff5c93fa14..2ecf1b0ae3 100644 --- a/xen/arch/x86/pv/dom0_build.c +++ b/xen/arch/x86/pv/domain_builder.c @@ -1,5 +1,5 @@ /****************************************************************************** - * pv/dom0_build.c + * pv/domain_builder.c * * Copyright (c) 2002-2005, K A Fraser */ @@ -8,6 +8,7 @@ #include <xen/bootinfo.h> #include <xen/console.h> #include <xen/domain.h> +#include <xen/domain_builder.h> #include <xen/domain_page.h> #include <xen/init.h> #include <xen/libelf.h> @@ -296,7 +297,7 @@ static struct page_info * __init alloc_chunk(struct domain *d, return page; } -int __init dom0_construct_pv(struct boot_domain *bd) +int __init dom_construct_pv(struct boot_domain *bd) { int i, rc, order, machine; bool compatible, compat; @@ -350,7 +351,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) /* Machine address of next candidate page-table page. */ paddr_t mpt_alloc; - printk(XENLOG_INFO "*** Building a PV Dom%d ***\n", d->domain_id); + printk(XENLOG_INFO "*** Constructing a PV Dom%d ***\n", d->domain_id); d->max_pages = ~0U; @@ -362,7 +363,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) if ( (rc = elf_init(&elf, image_start, image_len)) != 0 ) return rc; - if ( opt_dom0_verbose ) + if ( builder_is_ctldom(bd) && opt_dom0_verbose ) elf_set_verbose(&elf); elf_parse_binary(&elf); @@ -384,7 +385,8 @@ int __init dom0_construct_pv(struct boot_domain *bd) { if ( unlikely(rc = switch_compat(d)) ) { - printk("Dom0 failed to switch to compat: %d\n", rc); + printk("Dom%d failed to switch to compat: %d\n", + d->domain_id, rc); return rc; } @@ -404,22 +406,23 @@ int __init dom0_construct_pv(struct boot_domain *bd) if ( elf_msb(&elf) ) compatible = false; - printk(" Dom0 kernel: %s-bit%s, %s, paddr %#" PRIx64 " -> %#" PRIx64 "\n", - elf_64bit(&elf) ? "64" : elf_32bit(&elf) ? "32" : "??", + printk(" Dom%d kernel: %s-bit%s, %s, paddr %#" PRIx64 " -> %#" PRIx64 "\n", + d->domain_id, elf_64bit(&elf) ? "64" : elf_32bit(&elf) ? "32" : "??", parms.pae ? ", PAE" : "", elf_msb(&elf) ? "msb" : "lsb", elf.pstart, elf.pend); if ( elf.bsd_symtab_pstart ) - printk(" Dom0 symbol map %#" PRIx64 " -> %#" PRIx64 "\n", - elf.bsd_symtab_pstart, elf.bsd_symtab_pend); + printk(" Dom%d symbol map %#" PRIx64 " -> %#" PRIx64 "\n", + d->domain_id, elf.bsd_symtab_pstart, elf.bsd_symtab_pend); if ( !compatible ) { - printk("Mismatch between Xen and DOM0 kernel\n"); + printk("Mismatch between Xen and DOM%d kernel\n", d->domain_id); return -EINVAL; } - if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE ) + if ( builder_is_initdom(bd) && + parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE ) { if ( !pv_shim && !test_bit(XENFEAT_dom0, parms.f_supported) ) { @@ -443,7 +446,8 @@ int __init dom0_construct_pv(struct boot_domain *bd) if ( value > __HYPERVISOR_COMPAT_VIRT_START ) { - printk("Dom0 expects too high a hypervisor start address\n"); + printk("Dom%d expects too high a hypervisor start address\n", + d->domain_id); return -ERANGE; } HYPERVISOR_COMPAT_VIRT_START(d) = @@ -487,7 +491,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) vstartinfo_start = round_pgup(vphysmap_end); vstartinfo_end = vstartinfo_start + sizeof(struct start_info); - if ( pv_shim ) + if ( pv_shim || ! builder_is_initdom(bd) ) { vxenstore_start = round_pgup(vstartinfo_end); vxenstore_end = vxenstore_start + PAGE_SIZE; @@ -578,8 +582,8 @@ int __init dom0_construct_pv(struct boot_domain *bd) } printk("PHYSICAL MEMORY ARRANGEMENT:\n" - " Dom0 alloc.: %"PRIpaddr"->%"PRIpaddr, - pfn_to_paddr(alloc_spfn), pfn_to_paddr(alloc_epfn)); + " Dom%d alloc.: %"PRIpaddr"->%"PRIpaddr, + d->domain_id, pfn_to_paddr(alloc_spfn), pfn_to_paddr(alloc_epfn)); if ( domain_tot_pages(d) < nr_pages ) printk(" (%lu pages to be allocated)", nr_pages - domain_tot_pages(d)); @@ -596,7 +600,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) printk(" Init. ramdisk: %p->%p\n", _p(vinitrd_start), _p(vinitrd_end)); printk(" Phys-Mach map: %p->%p\n", _p(vphysmap_start), _p(vphysmap_end)); printk(" Start info: %p->%p\n", _p(vstartinfo_start), _p(vstartinfo_end)); - if ( pv_shim ) + if ( pv_shim || ! builder_is_initdom(bd) ) { printk(" Xenstore ring: %p->%p\n", _p(vxenstore_start), _p(vxenstore_end)); printk(" Console ring: %p->%p\n", _p(vconsole_start), _p(vconsole_end)); @@ -617,7 +621,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) ? v_end > HYPERVISOR_COMPAT_VIRT_START(d) : (v_start < HYPERVISOR_VIRT_END) && (v_end > HYPERVISOR_VIRT_START) ) { - printk("DOM0 image overlaps with Xen private area.\n"); + printk("DOM%d image overlaps with Xen private area.\n", d->domain_id); return -EINVAL; } @@ -768,9 +772,6 @@ int __init dom0_construct_pv(struct boot_domain *bd) init_hypercall_page(d, _p(parms.virt_hypercall)); } - /* Free temporary buffers. */ - discard_initial_images(); - /* Set up start info area. */ si = (start_info_t *)vstartinfo_start; clear_page(si); @@ -778,7 +779,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) si->shared_info = virt_to_maddr(d->shared_info); - if ( !pv_shim ) + if ( !pv_shim && builder_is_ctldom(bd) ) si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; if ( !vinitrd_start && initrd_len ) si->flags |= SIF_MOD_START_PFN; @@ -789,6 +790,19 @@ int __init dom0_construct_pv(struct boot_domain *bd) snprintf(si->magic, sizeof(si->magic), "xen-3.0-x86_%d%s", elf_64bit(&elf) ? 64 : 32, parms.pae ? "p" : ""); + if ( !builder_is_initdom(bd) ) + { + si->store_mfn = ((vxenstore_start - v_start) >> PAGE_SHIFT) + + alloc_spfn; + bd->store.mfn = si->store_mfn; + si->store_evtchn = bd->store.evtchn; + + si->console.domU.mfn = ((vconsole_start - v_start) >> PAGE_SHIFT) + + alloc_spfn; + bd->console.mfn = si->console.domU.mfn; + si->console.domU.evtchn = bd->console.evtchn; + } + count = domain_tot_pages(d); /* Set up the phys->machine table if not part of the initial mapping. */ @@ -871,23 +885,24 @@ int __init dom0_construct_pv(struct boot_domain *bd) sizeof(si->cmd_line)); #ifdef CONFIG_VIDEO - if ( !pv_shim && fill_console_start_info((void *)(si + 1)) ) - { - si->console.dom0.info_off = sizeof(struct start_info); - si->console.dom0.info_size = sizeof(struct dom0_vga_console_info); - } + if ( builder_is_hwdom(bd) ) + if ( !pv_shim && fill_console_start_info((void *)(si + 1)) ) + { + si->console.dom0.info_off = sizeof(struct start_info); + si->console.dom0.info_size = sizeof(struct dom0_vga_console_info); + } #endif /* * TODO: provide an empty stub for fill_console_start_info in the * !CONFIG_VIDEO case so the logic here can be simplified. */ - if ( pv_shim ) + if ( builder_is_hwdom(bd) && pv_shim ) pv_shim_setup_dom(d, l4start, v_start, vxenstore_start, vconsole_start, vphysmap_start, si); #ifdef CONFIG_COMPAT - if ( compat ) + if ( builder_is_hwdom(bd) && compat ) xlat_start_info(si, pv_shim ? XLAT_start_info_console_domU : XLAT_start_info_console_dom0); #endif @@ -926,15 +941,18 @@ int __init dom0_construct_pv(struct boot_domain *bd) if ( test_bit(XENFEAT_supervisor_mode_kernel, parms.f_required) ) panic("Dom0 requires supervisor-mode execution\n"); - rc = dom0_setup_permissions(d); - BUG_ON(rc != 0); + if ( builder_is_hwdom(bd) ) + { + rc = dom0_setup_permissions(d); + BUG_ON(rc != 0); + } if ( d->domain_id == hardware_domid ) iommu_hwdom_init(d); #ifdef CONFIG_SHADOW_PAGING /* Fill the shadow pool if necessary. */ - if ( opt_dom0_shadow || opt_pv_l1tf_hwdom ) + if ( builder_is_hwdom(bd) && (opt_dom0_shadow || opt_pv_l1tf_hwdom) ) { bool preempted; @@ -948,7 +966,7 @@ int __init dom0_construct_pv(struct boot_domain *bd) } /* Activate shadow mode, if requested. Reuse the pv_l1tf tasklet. */ - if ( opt_dom0_shadow ) + if ( builder_is_hwdom(bd) && opt_dom0_shadow ) { printk("Switching dom0 to using shadow paging\n"); tasklet_schedule(&d->arch.paging.shadow.pv_l1tf_tasklet); @@ -960,8 +978,8 @@ int __init dom0_construct_pv(struct boot_domain *bd) out: if ( elf_check_broken(&elf) ) - printk(XENLOG_WARNING "Dom0 kernel broken ELF: %s\n", - elf_check_broken(&elf)); + printk(XENLOG_WARNING "Dom%d kernel broken ELF: %s\n", + d->domain_id, elf_check_broken(&elf)); return rc; } diff --git a/xen/common/domain-builder/Kconfig b/xen/common/domain-builder/Kconfig index 893038cab3..0232e1ed8a 100644 --- a/xen/common/domain-builder/Kconfig +++ b/xen/common/domain-builder/Kconfig @@ -12,4 +12,14 @@ config BUILDER_FDT If unsure, say N. +config MULTIDOM_BUILDER + bool "Multidomain building (UNSUPPORTED)" if UNSUPPORTED + depends on BUILDER_FDT + ---help--- + Enables the domain builder to construct multiple domains. + + This feature is currently experimental. + + If unsure, say N. + endmenu diff --git a/xen/common/domain-builder/core.c b/xen/common/domain-builder/core.c index b030b07d71..c6a268eb96 100644 --- a/xen/common/domain-builder/core.c +++ b/xen/common/domain-builder/core.c @@ -1,6 +1,7 @@ #include <xen/bootdomain.h> #include <xen/bootinfo.h> #include <xen/domain_builder.h> +#include <xen/event.h> #include <xen/init.h> #include <xen/types.h> @@ -60,37 +61,144 @@ void __init builder_init(struct boot_info *info) d->kernel->string.kind = BOOTSTR_CMDLINE; } +static bool __init build_domain(struct boot_info *info, struct boot_domain *bd) +{ + if ( bd->constructed == true ) + return true; + + if ( bd->kernel == NULL ) + return false; + + printk(XENLOG_INFO "*** Building Dom%d ***\n", bd->domid); + + arch_create_dom(info, bd); + if ( bd->domain ) + { + bd->constructed = true; + return true; + } + + return false; +} + uint32_t __init builder_create_domains(struct boot_info *info) { uint32_t build_count = 0, functions_built = 0; + struct boot_domain *bd; int i; + if ( IS_ENABLED(CONFIG_MULTIDOM_BUILDER) ) + { + bd = builder_dom_by_function(info, BUILD_FUNCTION_XENSTORE); + if ( build_domain(info, bd) ) + { + functions_built |= bd->functions; + build_count++; + } + else + printk(XENLOG_WARNING "Xenstore build failed, system may be unusable\n"); + + bd = builder_dom_by_function(info, BUILD_FUNCTION_CONSOLE); + if ( build_domain(info, bd) ) + { + functions_built |= bd->functions; + build_count++; + } + else + printk(XENLOG_WARNING "Console build failed, system may be unusable\n"); + } + for ( i = 0; i < info->builder->nr_doms; i++ ) { - struct boot_domain *d = &info->builder->domains[i]; + bd = &info->builder->domains[i]; if ( ! IS_ENABLED(CONFIG_MULTIDOM_BUILDER) && - ! builder_is_initdom(d) && + ! builder_is_initdom(bd) && functions_built & BUILD_FUNCTION_INITIAL_DOM ) continue; - if ( d->kernel == NULL ) + if ( !build_domain(info, bd) ) { - if ( builder_is_initdom(d) ) + if ( builder_is_initdom(bd) ) panic("%s: intial domain missing kernel\n", __func__); - printk(XENLOG_ERR "%s:Dom%d definiton has no kernel\n", __func__, - d->domid); + printk(XENLOG_WARNING "Dom%d build failed, skipping\n", bd->domid); continue; } - arch_create_dom(info, d); - if ( d->domain ) + functions_built |= bd->functions; + build_count++; + } + + if ( IS_ENABLED(CONFIG_X86) ) + /* Free temporary buffers. */ + discard_initial_images(); + + return build_count; +} + +domid_t __init get_next_domid(void) +{ + static domid_t __initdata last_domid = 0; + domid_t next; + + for ( next = last_domid + 1; next < DOMID_FIRST_RESERVED; next++ ) + { + struct domain *d; + + if ( (d = rcu_lock_domain_by_id(next)) == NULL ) { - functions_built |= d->functions; - build_count++; + last_domid = next; + return next; } + + rcu_unlock_domain(d); } - return build_count; + return 0; +} + +int __init alloc_system_evtchn( + const struct boot_info *info, struct boot_domain *bd) +{ + evtchn_alloc_unbound_t evtchn_req; + struct boot_domain *c = builder_dom_by_function(info, + BUILD_FUNCTION_CONSOLE); + struct boot_domain *s = builder_dom_by_function(info, + BUILD_FUNCTION_XENSTORE); + int rc; + + evtchn_req.dom = bd->domid; + + if ( c != NULL && c != bd && c->constructed ) + { + evtchn_req.remote_dom = c->domid; + + rc = evtchn_alloc_unbound(&evtchn_req); + if ( rc ) + { + printk("Failed allocating console event channel for domain %d\n", + bd->domid); + return rc; + } + + bd->console.evtchn = evtchn_req.port; + } + + if ( s != NULL && s != bd && s->constructed ) + { + evtchn_req.remote_dom = s->domid; + + rc = evtchn_alloc_unbound(&evtchn_req); + if ( rc ) + { + printk("Failed allocating xenstore event channel for domain %d\n", + bd->domid); + return rc; + } + + bd->store.evtchn = evtchn_req.port; + } + + return 0; } diff --git a/xen/include/xen/bootdomain.h b/xen/include/xen/bootdomain.h index b172d16f4e..9c5d4d385e 100644 --- a/xen/include/xen/bootdomain.h +++ b/xen/include/xen/bootdomain.h @@ -47,6 +47,12 @@ struct boot_domain { struct boot_module *configs[BUILD_MAX_CONF_MODS]; struct domain *domain; + struct { + xen_pfn_t mfn; + unsigned int evtchn; + } store, console; + bool constructed; + }; #endif diff --git a/xen/include/xen/domain_builder.h b/xen/include/xen/domain_builder.h index c0d997f7bd..f9e43c9689 100644 --- a/xen/include/xen/domain_builder.h +++ b/xen/include/xen/domain_builder.h @@ -34,6 +34,22 @@ static inline bool builder_is_hwdom(struct boot_domain *bd) bd->permissions & BUILD_PERMISSION_HARDWARE ); } +static inline struct boot_domain *builder_dom_by_function( + const struct boot_info *info, uint32_t func) +{ + int i; + + for ( i = 0; i < info->builder->nr_doms; i++ ) + { + struct boot_domain *bd = &info->builder->domains[i]; + + if ( bd->functions & func ) + return bd; + } + + return NULL; +} + static inline struct domain *builder_get_hwdom(struct boot_info *info) { int i; @@ -51,6 +67,9 @@ static inline struct domain *builder_get_hwdom(struct boot_info *info) void builder_init(struct boot_info *info); uint32_t builder_create_domains(struct boot_info *info); +domid_t get_next_domid(void); +int alloc_system_evtchn( + const struct boot_info *info, struct boot_domain *bd); void arch_create_dom(const struct boot_info *bi, struct boot_domain *bd); #endif /* XEN_DOMAIN_BUILDER_H */ -- 2.20.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |