From nobody Fri Nov 29 02:42:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1652476084; cv=none; d=zohomail.com; s=zohoarc; b=LvI2Lu2suXt+uCLnRVFvIwtW43k+rlWzNWbEpAh0hggZ8eeVOMUZhwAcEYbFhl61rn0Ivty/X02KUgM5a/amd/uQuQBuVa4LP7lGP3ck3jykJz4KQBgxOoHIdGmZGA3Qj4wuWwLVIME6JfRcNDRQNyqNzoTjl60LJLkX6lpczYw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1652476084; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=begm1Uxh360qJKOzakt+h0YIvsvH+sjyYUFdy59LGPE=; b=Dg6VXczWLD+WuNUMuWzLHy460xQ2IGw9+V2Zjjv4V33bln1kQRSmS+0XrUYRDfuOM+RzUDCQbbrjQRXiTecp/NPqDOUaOg7dNFsSEp1XjJfdTojUMl5B+c6buZFy4xxP2ETG7ks5u6OwdS9Jr4D6Md8noTKOil7fwZrm8r9YFDo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1652476084304650.0761427770666; Fri, 13 May 2022 14:08:04 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.328783.551962 (Exim 4.92) (envelope-from ) id 1npcVh-0005pQ-Dd; Fri, 13 May 2022 21:07:41 +0000 Received: by outflank-mailman (output) from mailman id 328783.551962; Fri, 13 May 2022 21:07:41 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1npcVh-0005oT-5Y; Fri, 13 May 2022 21:07:41 +0000 Received: by outflank-mailman (input) for mailman id 328783; Fri, 13 May 2022 21:07:40 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1npcVg-0004iU-6i for xen-devel@lists.xenproject.org; Fri, 13 May 2022 21:07:40 +0000 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id b6fe1e4d-d300-11ec-b8b8-f95467ff1ed0; Fri, 13 May 2022 23:07:37 +0200 (CEST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 31B446230E; Fri, 13 May 2022 21:07:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D9EAC34100; Fri, 13 May 2022 21:07:35 +0000 (UTC) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: b6fe1e4d-d300-11ec-b8b8-f95467ff1ed0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1652476055; bh=np7FZDzo1soVXzJPDCUCWYC3dzjUNzPqexG/fuvJoXc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a0F5TVJqdJlvd12iFnhVbUUbrKysjbMl9FP1nRE/mwvz/AZv9JcQaCRCp0KVf9ZWC DxuH9iXE3cvAXhRmpHNLT105CaKypw5CxlvRDWFSGqoFGe/9t4euCPKcStH53zrPM4 Lq5LYXKoMJTR+6dF6CxVSRDK2qVrrtDhriZJjX0yRnW2QFtLC5vXkkRdYVq1zC17Vx F9cl0eXyptQZEsOfgP8STK4Q9gr3O5T1EpIRrF0B0QS073DW0sHD97xE51nMoVxDxg QsnhRzQa/99Xth3UACGaYL5JKOz1zoDcSJS7pyQ1kUEPBw7q3+Q1yMnxFI1WjFcscp GVPTObcyX+haQ== From: Stefano Stabellini To: xen-devel@lists.xenproject.org Cc: sstabellini@kernel.org, jgross@suse.com, Bertrand.Marquis@arm.com, julien@xen.org, Volodymyr_Babchuk@epam.com, Luca Miccio , Stefano Stabellini , Wei Liu , Anthony PERARD Subject: [PATCH v7 6/7] tools: add example application to initialize dom0less PV drivers Date: Fri, 13 May 2022 14:07:29 -0700 Message-Id: <20220513210730.679871-6-sstabellini@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @kernel.org) X-ZM-MESSAGEID: 1652476085789100011 Content-Type: text/plain; charset="utf-8" From: Luca Miccio Add an example application that can be run in dom0 to complete the dom0less domains initialization so that they can get access to xenstore and use PV drivers. The application sets "connection" to XENSTORE_RECONNECT on the xenstore page before calling xs_introduce_domain to signal that the connection is not ready yet to be used. XENSTORE_RECONNECT is reset soon after by xenstored. Signed-off-by: Luca Miccio Signed-off-by: Stefano Stabellini CC: Wei Liu CC: Anthony PERARD CC: Juergen Gross Acked-by: Julien Grall --- Changes in v8: - check on HVM_PARAM_STORE_EVTCHN to see if the domain is xen,enhanced - fix ubuntu native build, #include for PROT_* definitions Changes in v7: - use PROT_READ | PROT_WRITE instead XS_READ | XS_WRITE Changes in v6: - include xs_wire.h and use its definitions Changes in v5: - set XS_CONNECTION_STATE_RECONNECTING before xs_introduce_domain Changes in v4: - only alloc xs page (no other magic pages) - add xenstore permissions - check all return values - rename restore_xenstore to create_xenstore - set target_memkb - set start_time properly - close xs transaction on error - call xc_dom_gnttab_seed instead of xc_dom_gnttab_init - xs_open instead of xs_daemon_open Changes in v3: - handle xenstore errors - add an in-code comment about xenstore entries - less verbose output - clean-up error path in main Changes in v2: - do not set HVM_PARAM_STORE_EVTCHN twice - rename restore_xenstore to create_xenstore - increase maxmem connection reconnecting --- tools/helpers/Makefile | 13 ++ tools/helpers/init-dom0less.c | 340 ++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 tools/helpers/init-dom0less.c --- tools/helpers/Makefile | 13 ++ tools/helpers/init-dom0less.c | 345 ++++++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 tools/helpers/init-dom0less.c diff --git a/tools/helpers/Makefile b/tools/helpers/Makefile index 7f6c422440..8d78ab1e90 100644 --- a/tools/helpers/Makefile +++ b/tools/helpers/Makefile @@ -10,6 +10,9 @@ ifeq ($(CONFIG_Linux),y) ifeq ($(CONFIG_X86),y) PROGS +=3D init-xenstore-domain endif +ifeq ($(CONFIG_ARM),y) +PROGS +=3D init-dom0less +endif endif =20 XEN_INIT_DOM0_OBJS =3D xen-init-dom0.o init-dom-json.o @@ -26,6 +29,13 @@ $(INIT_XENSTORE_DOMAIN_OBJS): CFLAGS +=3D $(CFLAGS_libxe= nstore) $(INIT_XENSTORE_DOMAIN_OBJS): CFLAGS +=3D $(CFLAGS_libxenlight) $(INIT_XENSTORE_DOMAIN_OBJS): CFLAGS +=3D -include $(XEN_ROOT)/tools/confi= g.h =20 +INIT_DOM0LESS_OBJS =3D init-dom0less.o init-dom-json.o +$(INIT_DOM0LESS_OBJS): CFLAGS +=3D $(CFLAGS_libxentoollog) +$(INIT_DOM0LESS_OBJS): CFLAGS +=3D $(CFLAGS_libxenstore) +$(INIT_DOM0LESS_OBJS): CFLAGS +=3D $(CFLAGS_libxenlight) +$(INIT_DOM0LESS_OBJS): CFLAGS +=3D $(CFLAGS_libxenctrl) +$(INIT_DOM0LESS_OBJS): CFLAGS +=3D $(CFLAGS_libxenevtchn) + .PHONY: all all: $(PROGS) =20 @@ -35,6 +45,9 @@ xen-init-dom0: $(XEN_INIT_DOM0_OBJS) init-xenstore-domain: $(INIT_XENSTORE_DOMAIN_OBJS) $(CC) $(LDFLAGS) -o $@ $(INIT_XENSTORE_DOMAIN_OBJS) $(LDLIBS_libxentoollo= g) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIB= S_libxenlight) $(APPEND_LDFLAGS) =20 +init-dom0less: $(INIT_DOM0LESS_OBJS) + $(CC) $(LDFLAGS) -o $@ $(INIT_DOM0LESS_OBJS) $(LDLIBS_libxenctrl) $(LDLIB= S_libxenevtchn) $(LDLIBS_libxentoollog) $(LDLIBS_libxenstore) $(LDLIBS_libx= enlight) $(LDLIBS_libxenguest) $(LDLIBS_libxenforeignmemory) $(APPEND_LDFLA= GS) + .PHONY: install install: all $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN) diff --git a/tools/helpers/init-dom0less.c b/tools/helpers/init-dom0less.c new file mode 100644 index 0000000000..3e7ad54da7 --- /dev/null +++ b/tools/helpers/init-dom0less.c @@ -0,0 +1,345 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init-dom-json.h" + +#define XENSTORE_PFN_OFFSET 1 +#define STR_MAX_LENGTH 64 + +static int alloc_xs_page(struct xc_interface_core *xch, + libxl_dominfo *info, + uint64_t *xenstore_pfn) +{ + int rc; + const xen_pfn_t base =3D GUEST_MAGIC_BASE >> XC_PAGE_SHIFT; + xen_pfn_t p2m =3D (GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_O= FFSET; + + rc =3D xc_domain_setmaxmem(xch, info->domid, + info->max_memkb + (XC_PAGE_SIZE/1024)); + if (rc < 0) + return rc; + + rc =3D xc_domain_populate_physmap_exact(xch, info->domid, 1, 0, 0, &p2= m); + if (rc < 0) + return rc; + + *xenstore_pfn =3D base + XENSTORE_PFN_OFFSET; + rc =3D xc_clear_domain_page(xch, info->domid, *xenstore_pfn); + if (rc < 0) + return rc; + + return 0; +} + +static bool do_xs_write_dom(struct xs_handle *xsh, xs_transaction_t t, + domid_t domid, char *path, char *val) +{ + char full_path[STR_MAX_LENGTH]; + struct xs_permissions perms[2]; + + perms[0].id =3D domid; + perms[0].perms =3D XS_PERM_NONE; + perms[1].id =3D 0; + perms[1].perms =3D XS_PERM_READ; + + if (snprintf(full_path, STR_MAX_LENGTH, + "/local/domain/%u/%s", domid, path) < 0) + return false; + if (!xs_write(xsh, t, full_path, val, strlen(val))) + return false; + return xs_set_permissions(xsh, t, full_path, perms, 2); +} + +static bool do_xs_write_libxl(struct xs_handle *xsh, xs_transaction_t t, + domid_t domid, char *path, char *val) +{ + char full_path[STR_MAX_LENGTH]; + + if (snprintf(full_path, STR_MAX_LENGTH, + "/libxl/%u/%s", domid, path) < 0) + return false; + return xs_write(xsh, t, full_path, val, strlen(val)); +} + +static bool do_xs_write_vm(struct xs_handle *xsh, xs_transaction_t t, + libxl_uuid uuid, char *path, char *val) +{ + char full_path[STR_MAX_LENGTH]; + + if (snprintf(full_path, STR_MAX_LENGTH, + "/vm/" LIBXL_UUID_FMT "/%s", LIBXL_UUID_BYTES(uuid), path= ) < 0) + return false; + return xs_write(xsh, t, full_path, val, strlen(val)); +} + +/* + * The xenstore nodes are the xenstore nodes libxl writes at domain + * creation. + * + * The list was retrieved by running xenstore-ls on a corresponding + * domain started by xl/libxl. + */ +static int create_xenstore(struct xs_handle *xsh, + libxl_dominfo *info, libxl_uuid uuid, + evtchn_port_t xenstore_port) +{ + domid_t domid; + unsigned int i; + char uuid_str[STR_MAX_LENGTH]; + char dom_name_str[STR_MAX_LENGTH]; + char vm_val_str[STR_MAX_LENGTH]; + char id_str[STR_MAX_LENGTH]; + char max_memkb_str[STR_MAX_LENGTH]; + char target_memkb_str[STR_MAX_LENGTH]; + char cpu_str[STR_MAX_LENGTH]; + char xenstore_port_str[STR_MAX_LENGTH]; + char ring_ref_str[STR_MAX_LENGTH]; + xs_transaction_t t; + struct timeval start_time; + char start_time_str[STR_MAX_LENGTH]; + int rc; + + if (gettimeofday(&start_time, NULL) < 0) + return -errno; + rc =3D snprintf(start_time_str, STR_MAX_LENGTH, "%jd.%02d", + (intmax_t)start_time.tv_sec, (int)start_time.tv_usec / 10000); + if (rc < 0) + return rc; + + domid =3D info->domid; + rc =3D snprintf(id_str, STR_MAX_LENGTH, "%u", domid); + if (rc < 0) + return rc; + rc =3D snprintf(dom_name_str, STR_MAX_LENGTH, "dom0less-%u", domid); + if (rc < 0) + return rc; + rc =3D snprintf(uuid_str, STR_MAX_LENGTH, LIBXL_UUID_FMT, LIBXL_UUID_B= YTES(uuid)); + if (rc < 0) + return rc; + rc =3D snprintf(vm_val_str, STR_MAX_LENGTH, + "vm/" LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid)); + if (rc < 0) + return rc; + rc =3D snprintf(max_memkb_str, STR_MAX_LENGTH, "%lu", info->max_memkb); + if (rc < 0) + return rc; + rc =3D snprintf(target_memkb_str, STR_MAX_LENGTH, "%lu", info->current= _memkb); + if (rc < 0) + return rc; + rc =3D snprintf(ring_ref_str, STR_MAX_LENGTH, "%lld", + (GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_OFFSE= T); + if (rc < 0) + return rc; + rc =3D snprintf(xenstore_port_str, STR_MAX_LENGTH, "%u", xenstore_port= ); + if (rc < 0) + return rc; + +retry_transaction: + t =3D xs_transaction_start(xsh); + if (t =3D=3D XBT_NULL) + return -errno; + + rc =3D -EIO; + /* /vm */ + if (!do_xs_write_vm(xsh, t, uuid, "name", dom_name_str)) goto err; + if (!do_xs_write_vm(xsh, t, uuid, "uuid", uuid_str)) goto err; + if (!do_xs_write_vm(xsh, t, uuid, "start_time", start_time_str)) goto = err; + + /* /domain */ + if (!do_xs_write_dom(xsh, t, domid, "vm", vm_val_str)) goto err; + if (!do_xs_write_dom(xsh, t, domid, "name", dom_name_str)) goto err; + if (!do_xs_write_dom(xsh, t, domid, "cpu", "")) goto err; + for (i =3D 0; i < info->vcpu_max_id; i++) { + rc =3D snprintf(cpu_str, STR_MAX_LENGTH, "cpu/%u/availability/", i= ); + if (rc < 0) + goto err; + rc =3D -EIO; + if (!do_xs_write_dom(xsh, t, domid, cpu_str, + (info->cpupool & (1 << i)) ? "online" : "offl= ine")) + goto err; + } + + if (!do_xs_write_dom(xsh, t, domid, "memory", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "memory/static-max", max_memkb_str= )) goto err; + if (!do_xs_write_dom(xsh, t, domid, "memory/target", target_memkb_str)= ) goto err; + if (!do_xs_write_dom(xsh, t, domid, "memory/videoram", "-1")) goto err; + + if (!do_xs_write_dom(xsh, t, domid, "device", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "device/suspend", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "device/suspend/event-channel", ""= )) goto err; + + if (!do_xs_write_dom(xsh, t, domid, "control", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "control/shutdown", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "control/feature-poweroff", "1")) = goto err; + if (!do_xs_write_dom(xsh, t, domid, "control/feature-reboot", "1")) go= to err; + if (!do_xs_write_dom(xsh, t, domid, "control/feature-suspend", "")) go= to err; + if (!do_xs_write_dom(xsh, t, domid, "control/sysrq", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "control/platform-feature-multipro= cessor-suspend", "1")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "control/platform-feature-xs_reset= _watches", "1")) goto err; + + if (!do_xs_write_dom(xsh, t, domid, "domid", id_str)) goto err; + if (!do_xs_write_dom(xsh, t, domid, "data", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "drivers", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "feature", "")) goto err; + if (!do_xs_write_dom(xsh, t, domid, "attr", "")) goto err; + + if (!do_xs_write_dom(xsh, t, domid, "store/port", xenstore_port_str)) = goto err; + if (!do_xs_write_dom(xsh, t, domid, "store/ring-ref", ring_ref_str)) g= oto err; + + if (!do_xs_write_libxl(xsh, t, domid, "type", "pvh")) goto err; + if (!do_xs_write_libxl(xsh, t, domid, "dm-version", "qemu_xen")) goto = err; + + if (!xs_transaction_end(xsh, t, false)) { + if (errno =3D=3D EAGAIN) + goto retry_transaction; + else + return -errno; + } + + return 0; + +err: + xs_transaction_end(xsh, t, true); + return rc; +} + +static int init_domain(struct xs_handle *xsh, + struct xc_interface_core *xch, + xenforeignmemory_handle *xfh, + libxl_dominfo *info) +{ + libxl_uuid uuid; + uint64_t xenstore_evtchn, xenstore_pfn; + int rc; + struct xenstore_domain_interface *intf; + + printf("Init dom0less domain: %u\n", info->domid); + + rc =3D xc_hvm_param_get(xch, info->domid, HVM_PARAM_STORE_EVTCHN, + &xenstore_evtchn); + if (rc !=3D 0) { + printf("Failed to get HVM_PARAM_STORE_EVTCHN\n"); + return 1; + } + + /* no xen,enhanced; nothing to do */ + if (!xenstore_evtchn) + return 0; + + /* Alloc xenstore page */ + if (alloc_xs_page(xch, info, &xenstore_pfn) !=3D 0) { + printf("Error on alloc magic pages\n"); + return 1; + } + + intf =3D xenforeignmemory_map(xfh, info->domid, PROT_READ | PROT_WRITE= , 1, + &xenstore_pfn, NULL); + if (!intf) { + printf("Error mapping xenstore page\n"); + return 1; + } + intf->connection =3D XENSTORE_RECONNECT; + xenforeignmemory_unmap(xfh, intf, 1); + + rc =3D xc_dom_gnttab_seed(xch, info->domid, true, + (xen_pfn_t)-1, xenstore_pfn, 0, 0); + if (rc) + err(1, "xc_dom_gnttab_seed"); + + libxl_uuid_generate(&uuid); + xc_domain_sethandle(xch, info->domid, libxl_uuid_bytearray(&uuid)); + + rc =3D gen_stub_json_config(info->domid, &uuid); + if (rc) + err(1, "gen_stub_json_config"); + + /* Now everything is ready: set HVM_PARAM_STORE_PFN */ + rc =3D xc_hvm_param_set(xch, info->domid, HVM_PARAM_STORE_PFN, + xenstore_pfn); + if (rc < 0) + return rc; + + rc =3D create_xenstore(xsh, info, uuid, xenstore_evtchn); + if (rc) + err(1, "writing to xenstore"); + + rc =3D xs_introduce_domain(xsh, info->domid, + (GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_OFFSET, + xenstore_evtchn); + if (!rc) + err(1, "xs_introduce_domain"); + return 0; +} + +/* Check if domain has been configured in XS */ +static bool domain_exists(struct xs_handle *xsh, int domid) +{ + return xs_is_domain_introduced(xsh, domid); +} + +int main(int argc, char **argv) +{ + libxl_dominfo *info =3D NULL; + libxl_ctx *ctx; + int nb_vm =3D 0, rc =3D 0, i; + struct xs_handle *xsh =3D NULL; + struct xc_interface_core *xch =3D NULL; + xenforeignmemory_handle *xfh =3D NULL; + + /* TODO reuse libxl xsh connection */ + xsh =3D xs_open(0); + xch =3D xc_interface_open(0, 0, 0); + xfh =3D xenforeignmemory_open(0, 0); + if (xsh =3D=3D NULL || xch =3D=3D NULL || xfh =3D=3D NULL) { + fprintf(stderr, "Cannot open xc/xs/xenforeignmemory interfaces"); + rc =3D -errno; + goto out; + } + + rc =3D libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, NULL); + if (rc) { + fprintf(stderr, "cannot init xl context\n"); + goto out; + } + + info =3D libxl_list_domain(ctx, &nb_vm); + if (!info) { + fprintf(stderr, "libxl_list_vm failed.\n"); + rc =3D -1; + goto out; + } + + for (i =3D 0; i < nb_vm; i++) { + domid_t domid =3D info[i].domid; + + /* Don't need to check for Dom0 */ + if (!domid) + continue; + + printf("Checking domid: %u\n", domid); + if (!domain_exists(xsh, domid)) { + rc =3D init_domain(xsh, xch, xfh, &info[i]); + if (rc < 0) { + fprintf(stderr, "init_domain failed.\n"); + goto out; + } + } else { + printf("Domain %u has already been initialized\n", domid); + } + } +out: + libxl_dominfo_list_free(info, nb_vm); + return rc; +} --=20 2.25.1