From nobody Tue Nov 11 08:31:26 2025 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1569426679; cv=none; d=zoho.com; s=zohoarc; b=dJ/S5ablc8wSOnMM4qDLTxSE4Ck5Z1xH/0GFiraHwl8pjX8/0kNJa13p/x9GnTrvMBMiF87ADLtFFqPOgcQg8dFn+WKBsHUoXF6yDwPj7sU5yag/TfHudkaqVHkXR9/Y3wwdgvqX0kKGwvk6CT88dEYo49s+LisvmACoiWd8eSY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1569426679; h=Content-Type: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:ARC-Authentication-Results; bh=W4/D8d85z06T64SsSHoLZ2J8P912ofJHkYkCtGxpOw0=; b=PyIEchUDhqrVnKYIYxu6QX5Y2Vl0YTtWWW/A5qWxfqbX3WenNCV8tNKeFqPmAYaB6WuF36ItjCfcCZtR+xxXiuAMflae/eklnKtnchInRCCJYMsB36dHUtK6gtkXYZbAvkbZ+5rz8d4iNNnfT54AvUQeprYYYuA4YSYQw1zbCN8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1569426679036609.9197263828878; Wed, 25 Sep 2019 08:51:19 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iD9YF-00015x-SH; Wed, 25 Sep 2019 15:49:59 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iD9YD-000147-UH for xen-devel@lists.xenproject.org; Wed, 25 Sep 2019 15:49:57 +0000 Received: from mga12.intel.com (unknown [192.55.52.136]) by localhost (Halon) with ESMTPS id 15103845-dfac-11e9-9637-12813bfff9fa; Wed, 25 Sep 2019 15:49:40 +0000 (UTC) Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Sep 2019 08:49:39 -0700 Received: from tlengyel-mobl2.amr.corp.intel.com (HELO localhost.localdomain) ([10.252.129.153]) by orsmga006.jf.intel.com with ESMTP; 25 Sep 2019 08:49:39 -0700 X-Inumbo-ID: 15103845-dfac-11e9-9637-12813bfff9fa X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,548,1559545200"; d="scan'208";a="193812722" From: Tamas K Lengyel To: xen-devel@lists.xenproject.org Date: Wed, 25 Sep 2019 08:48:56 -0700 Message-Id: X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Subject: [Xen-devel] [RFC PATCH for-next 18/18] xen/tools: VM forking toolstack side X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , Ian Jackson , Tamas K Lengyel , Wei Liu Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add necessary bits to implement "xl fork-vm" and "xl fork-launch-dm" comman= ds. The process is split in two to allow tools needing access to the new VM as = fast as possible after it was forked. It is expected that under certain use-cases the second command that launches QEMU will be skipped entirely. Signed-off-by: Tamas K Lengyel --- tools/libxc/include/xenctrl.h | 4 + tools/libxc/xc_memshr.c | 12 ++ tools/libxl/libxl.h | 6 + tools/libxl/libxl_create.c | 212 +++++++++++++++++++++++----------- tools/libxl/libxl_dm.c | 2 +- tools/libxl/libxl_dom.c | 83 ++++++++----- tools/libxl/libxl_internal.h | 1 + tools/libxl/libxl_types.idl | 1 + tools/xl/xl.h | 4 + tools/xl/xl_cmdtable.c | 15 +++ tools/xl/xl_saverestore.c | 69 +++++++++++ tools/xl/xl_vmcontrol.c | 8 ++ 12 files changed, 323 insertions(+), 94 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index b7c990aafd..8719893f1b 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2221,6 +2221,10 @@ int xc_memshr_range_share(xc_interface *xch, uint64_t first_gfn, uint64_t last_gfn); =20 +int xc_memshr_fork(xc_interface *xch, + uint32_t source_domain, + uint32_t client_domain); + /* Debug calls: return the number of pages referencing the shared frame ba= cking * the input argument. Should be one or greater. * diff --git a/tools/libxc/xc_memshr.c b/tools/libxc/xc_memshr.c index 5ef56a6933..1e01140e1d 100644 --- a/tools/libxc/xc_memshr.c +++ b/tools/libxc/xc_memshr.c @@ -237,6 +237,18 @@ int xc_memshr_debug_gref(xc_interface *xch, return xc_memshr_memop(xch, domid, &mso); } =20 +int xc_memshr_fork(xc_interface *xch, uint32_t pdomid, uint32_t domid) +{ + xen_mem_sharing_op_t mso; + + memset(&mso, 0, sizeof(mso)); + + mso.op =3D XENMEM_sharing_op_fork; + mso.u.fork.parent_domain =3D pdomid; + + return xc_memshr_memop(xch, domid, &mso); +} + int xc_memshr_audit(xc_interface *xch) { xen_mem_sharing_op_t mso; diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 3421e5aa98..1ceda6f7de 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1494,6 +1494,12 @@ int libxl_domain_create_new(libxl_ctx *ctx, libxl_do= main_config *d_config, const libxl_asyncop_how *ao_how, const libxl_asyncprogress_how *aop_console_how) LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_domain_fork_vm(libxl_ctx *ctx, uint32_t pdomid, uint32_t *domid) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_domain_fork_launch_dm(libxl_ctx *ctx, libxl_domain_config *d_con= fig, + uint32_t domid, + const libxl_asyncprogress_how *aop_console= _how) + LIBXL_EXTERNAL_CALLERS_ONLY; int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_con= fig, uint32_t *domid, int restore_fd, int send_back_fd, diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 93fbe1d740..c38af0a214 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -535,12 +535,12 @@ out: return ret; } =20 -int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, - libxl__domain_build_state *state, - uint32_t *domid) +static int libxl__domain_make_xs_entries(libxl__gc *gc, libxl_domain_confi= g *d_config, + libxl__domain_build_state *state, + uint32_t domid) { libxl_ctx *ctx =3D libxl__gc_owner(gc); - int ret, rc, nb_vm; + int rc, nb_vm; const char *dom_type; char *uuid_string; char *dom_path, *vm_path, *libxl_path; @@ -552,7 +552,6 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_conf= ig *d_config, =20 /* convenience aliases */ libxl_domain_create_info *info =3D &d_config->c_info; - libxl_domain_build_info *b_info =3D &d_config->b_info; =20 uuid_string =3D libxl__uuid2string(gc, info->uuid); if (!uuid_string) { @@ -560,54 +559,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_con= fig *d_config, goto out; } =20 - /* Valid domid here means we're soft resetting. */ - if (!libxl_domid_valid_guest(*domid)) { - struct xen_domctl_createdomain create =3D { - .ssidref =3D info->ssidref, - .max_vcpus =3D b_info->max_vcpus, - .max_evtchn_port =3D b_info->event_channels, - .max_grant_frames =3D b_info->max_grant_frames, - .max_maptrack_frames =3D b_info->max_maptrack_frames, - }; - - if (info->type !=3D LIBXL_DOMAIN_TYPE_PV) { - create.flags |=3D XEN_DOMCTL_CDF_hvm; - create.flags |=3D - libxl_defbool_val(info->hap) ? XEN_DOMCTL_CDF_hap : 0; - create.flags |=3D - libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off; - } - - /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ - libxl_uuid_copy(ctx, (libxl_uuid *)&create.handle, &info->uuid); - - ret =3D libxl__arch_domain_prepare_config(gc, d_config, &create); - if (ret < 0) { - LOGED(ERROR, *domid, "fail to get domain config"); - rc =3D ERROR_FAIL; - goto out; - } - - ret =3D xc_domain_create(ctx->xch, domid, &create); - if (ret < 0) { - LOGED(ERROR, *domid, "domain creation fail"); - rc =3D ERROR_FAIL; - goto out; - } - - rc =3D libxl__arch_domain_save_config(gc, d_config, state, &create= ); - if (rc < 0) - goto out; - } - - ret =3D xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); - if (ret < 0) { - LOGED(ERROR, *domid, "domain move fail"); - rc =3D ERROR_FAIL; - goto out; - } - - dom_path =3D libxl__xs_get_dompath(gc, *domid); + dom_path =3D libxl__xs_get_dompath(gc, domid); if (!dom_path) { rc =3D ERROR_FAIL; goto out; @@ -615,12 +567,12 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_co= nfig *d_config, =20 vm_path =3D GCSPRINTF("/vm/%s", uuid_string); if (!vm_path) { - LOGD(ERROR, *domid, "cannot allocate create paths"); + LOGD(ERROR, domid, "cannot allocate create paths"); rc =3D ERROR_FAIL; goto out; } =20 - libxl_path =3D libxl__xs_libxl_path(gc, *domid); + libxl_path =3D libxl__xs_libxl_path(gc, domid); if (!libxl_path) { rc =3D ERROR_FAIL; goto out; @@ -631,10 +583,10 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_co= nfig *d_config, =20 roperm[0].id =3D 0; roperm[0].perms =3D XS_PERM_NONE; - roperm[1].id =3D *domid; + roperm[1].id =3D domid; roperm[1].perms =3D XS_PERM_READ; =20 - rwperm[0].id =3D *domid; + rwperm[0].id =3D domid; rwperm[0].perms =3D XS_PERM_NONE; =20 retry_transaction: @@ -652,7 +604,7 @@ retry_transaction: noperm, ARRAY_SIZE(noperm)); =20 xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm= _path)); - rc =3D libxl__domain_rename(gc, *domid, 0, info->name, t); + rc =3D libxl__domain_rename(gc, domid, 0, info->name, t); if (rc) goto out; =20 @@ -729,7 +681,7 @@ retry_transaction: =20 vm_list =3D libxl_list_vm(ctx, &nb_vm); if (!vm_list) { - LOGD(ERROR, *domid, "cannot get number of running guests"); + LOGD(ERROR, domid, "cannot get number of running guests"); rc =3D ERROR_FAIL; goto out; } @@ -753,7 +705,7 @@ retry_transaction: t =3D 0; goto retry_transaction; } - LOGED(ERROR, *domid, "domain creation ""xenstore transaction commi= t failed"); + LOGED(ERROR, domid, "domain creation ""xenstore transaction commit= failed"); rc =3D ERROR_FAIL; goto out; } @@ -765,6 +717,70 @@ retry_transaction: return rc; } =20 +int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, + libxl__domain_build_state *state, + uint32_t *domid) +{ + libxl_ctx *ctx =3D libxl__gc_owner(gc); + int ret, rc; + + /* convenience aliases */ + libxl_domain_create_info *info =3D &d_config->c_info; + libxl_domain_build_info *b_info =3D &d_config->b_info; + + /* Valid domid here means we're soft resetting. */ + if (!libxl_domid_valid_guest(*domid)) { + struct xen_domctl_createdomain create =3D { + .ssidref =3D info->ssidref, + .max_vcpus =3D b_info->max_vcpus, + .max_evtchn_port =3D b_info->event_channels, + .max_grant_frames =3D b_info->max_grant_frames, + .max_maptrack_frames =3D b_info->max_maptrack_frames, + }; + + if (info->type !=3D LIBXL_DOMAIN_TYPE_PV) { + create.flags |=3D XEN_DOMCTL_CDF_hvm; + create.flags |=3D + libxl_defbool_val(info->hap) ? XEN_DOMCTL_CDF_hap : 0; + create.flags |=3D + libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off; + } + + /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ + libxl_uuid_copy(ctx, (libxl_uuid *)&create.handle, &info->uuid); + + ret =3D libxl__arch_domain_prepare_config(gc, d_config, &create); + if (ret < 0) { + LOGED(ERROR, *domid, "fail to get domain config"); + rc =3D ERROR_FAIL; + goto out; + } + + ret =3D xc_domain_create(ctx->xch, domid, &create); + if (ret < 0) { + LOGED(ERROR, *domid, "domain creation fail"); + rc =3D ERROR_FAIL; + goto out; + } + + rc =3D libxl__arch_domain_save_config(gc, d_config, state, &create= ); + if (rc < 0) + goto out; + } + + ret =3D xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); + if (ret < 0) { + LOGED(ERROR, *domid, "domain move fail"); + rc =3D ERROR_FAIL; + goto out; + } + + rc =3D libxl__domain_make_xs_entries(gc, d_config, state, *domid); + +out: + return rc; +} + static int store_libxl_entry(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *b_info) { @@ -985,15 +1001,31 @@ static void initiate_domain_create(libxl__egc *egc, goto error_out; } =20 - ret =3D libxl__domain_make(gc, d_config, &dcs->build_state, &domid); - if (ret) { - LOGD(ERROR, domid, "cannot make domain: %d", ret); + if ( !d_config->dm_restore_file ) + { + ret =3D libxl__domain_make(gc, d_config, &dcs->build_state, &domid= ); dcs->guest_domid =3D domid; + + if (ret) { + LOGD(ERROR, domid, "cannot make domain: %d", ret); + ret =3D ERROR_FAIL; + goto error_out; + } + } else if ( dcs->guest_domid !=3D INVALID_DOMID ) { + domid =3D dcs->guest_domid; + + ret =3D libxl__domain_make_xs_entries(gc, d_config, &dcs->build_st= ate, domid); + if (ret) { + LOGD(ERROR, domid, "cannot make domain: %d", ret); + ret =3D ERROR_FAIL; + goto error_out; + } + } else { + LOGD(ERROR, domid, "cannot make domain"); ret =3D ERROR_FAIL; goto error_out; } =20 - dcs->guest_domid =3D domid; dcs->sdss.dm.guest_domid =3D 0; /* means we haven't spawned */ =20 /* @@ -1026,7 +1058,7 @@ static void initiate_domain_create(libxl__egc *egc, if (ret) goto error_out; =20 - if (restore_fd >=3D 0 || dcs->domid_soft_reset !=3D INVALID_DOMID) { + if (restore_fd >=3D 0 || dcs->domid_soft_reset !=3D INVALID_DOMID || d= _config->dm_restore_file) { LOGD(DEBUG, domid, "restoring, not running bootloader"); domcreate_bootloader_done(egc, &dcs->bl, 0); } else { @@ -1102,7 +1134,16 @@ static void domcreate_bootloader_done(libxl__egc *eg= c, dcs->sdss.dm.callback =3D domcreate_devmodel_started; dcs->sdss.callback =3D domcreate_devmodel_started; =20 - if (restore_fd < 0 && dcs->domid_soft_reset =3D=3D INVALID_DOMID) { + if (restore_fd < 0 && dcs->domid_soft_reset =3D=3D INVALID_DOMID && !d= _config->dm_restore_file) { + rc =3D libxl__domain_build(gc, d_config, domid, state); + domcreate_rebuild_done(egc, dcs, rc); + return; + } + + if ( d_config->dm_restore_file ) { + dcs->srs.dcs =3D dcs; + dcs->srs.ao =3D ao; + state->forked_vm =3D true; rc =3D libxl__domain_build(gc, d_config, domid, state); domcreate_rebuild_done(egc, dcs, rc); return; @@ -1300,6 +1341,7 @@ static void domcreate_rebuild_done(libxl__egc *egc, /* convenience aliases */ const uint32_t domid =3D dcs->guest_domid; libxl_domain_config *const d_config =3D dcs->guest_config; + libxl__domain_build_state *const state =3D &dcs->build_state; =20 if (ret) { LOGD(ERROR, domid, "cannot (re-)build domain: %d", ret); @@ -1307,6 +1349,9 @@ static void domcreate_rebuild_done(libxl__egc *egc, goto error_out; } =20 + if ( d_config->dm_restore_file ) + state->saved_state =3D GCSPRINTF("%s", d_config->dm_restore_file); + store_libxl_entry(gc, domid, &d_config->b_info); =20 libxl__multidev_begin(ao, &dcs->multidev); @@ -1708,10 +1753,13 @@ static int do_domain_create(libxl_ctx *ctx, libxl_d= omain_config *d_config, GCNEW(cdcs); cdcs->dcs.ao =3D ao; cdcs->dcs.guest_config =3D d_config; + cdcs->dcs.guest_domid =3D *domid; + libxl_domain_config_init(&cdcs->dcs.guest_config_saved); libxl_domain_config_copy(ctx, &cdcs->dcs.guest_config_saved, d_config); cdcs->dcs.restore_fd =3D cdcs->dcs.libxc_fd =3D restore_fd; cdcs->dcs.send_back_fd =3D send_back_fd; + if (restore_fd > -1) { cdcs->dcs.restore_params =3D *params; rc =3D libxl__fd_flags_modify_save(gc, cdcs->dcs.restore_fd, @@ -1954,6 +2002,38 @@ int libxl_domain_create_new(libxl_ctx *ctx, libxl_do= main_config *d_config, ao_how, aop_console_how); } =20 +int libxl_domain_fork_vm(libxl_ctx *ctx, uint32_t pdomid, uint32_t *domid) +{ + int rc; + struct xen_domctl_createdomain create =3D {0}; + create.flags |=3D XEN_DOMCTL_CDF_hvm; + create.flags |=3D XEN_DOMCTL_CDF_hap; + create.flags |=3D XEN_DOMCTL_CDF_oos_off; + create.arch.emulation_flags =3D (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI); + + create.ssidref =3D SECINITSID_DOMU; + create.max_vcpus =3D 1; // placeholder, will be cloned from pdomid + create.max_evtchn_port =3D 1023; + create.max_grant_frames =3D LIBXL_MAX_GRANT_FRAMES_DEFAULT; + create.max_maptrack_frames =3D LIBXL_MAX_MAPTRACK_FRAMES_DEFAULT; + + if ( (rc =3D xc_domain_create(ctx->xch, domid, &create)) ) + return rc; + + if ( (rc =3D xc_memshr_fork(ctx->xch, pdomid, *domid)) ) + xc_domain_destroy(ctx->xch, *domid); + + return rc; +} + +int libxl_domain_fork_launch_dm(libxl_ctx *ctx, libxl_domain_config *d_con= fig, + uint32_t domid, + const libxl_asyncprogress_how *aop_console= _how) +{ + unset_disk_colo_restore(d_config); + return do_domain_create(ctx, d_config, &domid, -1, -1, 0, 0, aop_conso= le_how); +} + int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_con= fig, uint32_t *domid, int restore_fd, int send_back_fd, diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index c00356a2f1..72c6fb7541 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -2785,7 +2785,7 @@ static void device_model_spawn_outcome(libxl__egc *eg= c, =20 libxl__domain_build_state *state =3D dmss->build_state; =20 - if (state->saved_state) { + if (state->saved_state && !state->forked_vm) { ret2 =3D unlink(state->saved_state); if (ret2) { LOGED(ERROR, dmss->guest_domid, "%s: failed to remove device-m= odel state %s", diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index c5685b061c..6e07893e3e 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -391,9 +391,12 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *const info =3D &d_config->b_info; libxl_ctx *ctx =3D libxl__gc_owner(gc); char *xs_domid, *con_domid; - int rc; + int rc =3D 0; uint64_t size; =20 + if ( state->forked_vm ) + goto skip_fork; + if (xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus) !=3D 0) { LOG(ERROR, "Couldn't set max vcpu count"); return ERROR_FAIL; @@ -498,29 +501,6 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid, } } =20 - - rc =3D libxl__arch_extra_memory(gc, info, &size); - if (rc < 0) { - LOGE(ERROR, "Couldn't get arch extra constant memory size"); - return ERROR_FAIL; - } - - if (xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb + size) < = 0) { - LOGE(ERROR, "Couldn't set max memory"); - return ERROR_FAIL; - } - - xs_domid =3D xs_read(ctx->xsh, XBT_NULL, "/tool/xenstored/domid", NULL= ); - state->store_domid =3D xs_domid ? atoi(xs_domid) : 0; - free(xs_domid); - - con_domid =3D xs_read(ctx->xsh, XBT_NULL, "/tool/xenconsoled/domid", N= ULL); - state->console_domid =3D con_domid ? atoi(con_domid) : 0; - free(con_domid); - - state->store_port =3D xc_evtchn_alloc_unbound(ctx->xch, domid, state->= store_domid); - state->console_port =3D xc_evtchn_alloc_unbound(ctx->xch, domid, state= ->console_domid); - if (info->type !=3D LIBXL_DOMAIN_TYPE_PV) hvm_set_conf_params(ctx->xch, domid, info); =20 @@ -555,8 +535,34 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid, info->altp2m); } =20 + rc =3D libxl__arch_extra_memory(gc, info, &size); + if (rc < 0) { + LOGE(ERROR, "Couldn't get arch extra constant memory size"); + return ERROR_FAIL; + } + + if (xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb + size) < = 0) { + LOGE(ERROR, "Couldn't set max memory"); + return ERROR_FAIL; + } + rc =3D libxl__arch_domain_create(gc, d_config, domid); + if ( rc ) + goto out; =20 +skip_fork: + xs_domid =3D xs_read(ctx->xsh, XBT_NULL, "/tool/xenstored/domid", NULL= ); + state->store_domid =3D xs_domid ? atoi(xs_domid) : 0; + free(xs_domid); + + con_domid =3D xs_read(ctx->xsh, XBT_NULL, "/tool/xenconsoled/domid", N= ULL); + state->console_domid =3D con_domid ? atoi(con_domid) : 0; + free(con_domid); + + state->store_port =3D xc_evtchn_alloc_unbound(ctx->xch, domid, state->= store_domid); + state->console_port =3D xc_evtchn_alloc_unbound(ctx->xch, domid, state= ->console_domid); + +out: return rc; } =20 @@ -614,6 +620,9 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, char **ents; int i, rc; =20 + if ( state->forked_vm ) + goto skip_fork; + if (info->num_vnuma_nodes && !info->num_vcpu_soft_affinity) { rc =3D set_vnuma_affinity(gc, domid, info); if (rc) @@ -638,6 +647,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, } } =20 +skip_fork: ents =3D libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char= *)); ents[0] =3D "memory/static-max"; ents[1] =3D GCSPRINTF("%"PRId64, info->max_memkb); @@ -900,14 +910,16 @@ static int hvm_build_set_params(xc_interface *handle,= uint32_t domid, libxl_domain_build_info *info, int store_evtchn, unsigned long *store_mfn, int console_evtchn, unsigned long *console= _mfn, - domid_t store_domid, domid_t console_domid) + domid_t store_domid, domid_t console_domid, + bool forked_vm) { struct hvm_info_table *va_hvm; uint8_t *va_map, sum; uint64_t str_mfn, cons_mfn; int i; =20 - if (info->type =3D=3D LIBXL_DOMAIN_TYPE_HVM) { + if ( info->type =3D=3D LIBXL_DOMAIN_TYPE_HVM && !forked_vm ) + { va_map =3D xc_map_foreign_range(handle, domid, XC_PAGE_SIZE, PROT_READ | PROT_WRITE, HVM_INFO_PFN); @@ -1223,6 +1235,23 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, struct xc_dom_image *dom =3D NULL; bool device_model =3D info->type =3D=3D LIBXL_DOMAIN_TYPE_HVM ? true := false; =20 + if ( state->forked_vm ) + { + rc =3D hvm_build_set_params(ctx->xch, domid, info, state->store_po= rt, + &state->store_mfn, state->console_port, + &state->console_mfn, state->store_domid, + state->console_domid, state->forked_vm); + + if ( rc ) + return rc; + + return xc_dom_gnttab_seed(ctx->xch, domid, true, + state->console_mfn, + state->store_mfn, + state->console_domid, + state->store_domid); + } + xc_dom_loginit(ctx->xch); =20 /* @@ -1347,7 +1376,7 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, rc =3D hvm_build_set_params(ctx->xch, domid, info, state->store_port, &state->store_mfn, state->console_port, &state->console_mfn, state->store_domid, - state->console_domid); + state->console_domid, false); if (rc !=3D 0) { LOG(ERROR, "hvm build set params failed"); goto out; diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index bfeb38e0ed..0becfc3e31 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1271,6 +1271,7 @@ typedef struct { =20 char *saved_state; int dm_monitor_fd; + bool forked_vm; =20 libxl__file_reference pv_kernel; libxl__file_reference pv_ramdisk; diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 04c9762af1..f12c1882dc 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -946,6 +946,7 @@ libxl_domain_config =3D Struct("domain_config", [ ("on_watchdog", libxl_action_on_shutdown), ("on_crash", libxl_action_on_shutdown), ("on_soft_reset", libxl_action_on_shutdown), + ("dm_restore_file", string, {'const': True}), ], dir=3DDIR_IN) =20 libxl_diskinfo =3D Struct("diskinfo", [ diff --git a/tools/xl/xl.h b/tools/xl/xl.h index 60bdad8ffb..993a63d268 100644 --- a/tools/xl/xl.h +++ b/tools/xl/xl.h @@ -31,6 +31,7 @@ struct cmd_spec { }; =20 struct domain_create { + uint32_t ddomid; /* fork launch dm for this domid */ int debug; int daemonize; int monitor; /* handle guest reboots etc */ @@ -45,6 +46,7 @@ struct domain_create { const char *config_file; char *extra_config; /* extra config string */ const char *restore_file; + const char *dm_restore_file; char *colo_proxy_script; bool userspace_colo_proxy; int migrate_fd; /* -1 means none */ @@ -127,6 +129,8 @@ int main_pciassignable_remove(int argc, char **argv); int main_pciassignable_list(int argc, char **argv); #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME int main_restore(int argc, char **argv); +int main_fork_vm(int argc, char **argv); +int main_fork_launch_dm(int argc, char **argv); int main_migrate_receive(int argc, char **argv); int main_save(int argc, char **argv); int main_migrate(int argc, char **argv); diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c index 5baa6023aa..902b3d7b01 100644 --- a/tools/xl/xl_cmdtable.c +++ b/tools/xl/xl_cmdtable.c @@ -180,6 +180,21 @@ struct cmd_spec cmd_table[] =3D { "-V, --vncviewer Connect to the VNC display after the domai= n is created.\n" "-A, --vncviewer-autopass Pass VNC password to viewer via stdin." }, + { "fork-vm", + &main_fork_vm, 0, 1, + "Fork a domain from the running parent domid", + "[options] ", + "-h Print this help.\n" + "-d Enable debug messages.\n" + }, + { "fork-launch-dm", + &main_fork_launch_dm, 0, 1, + "Launch the device model for a forked VM", + "[options] ", + "-h Print this help.\n" + "-p Do not unpause domain after restoring it.\= n" + "-d Enable debug messages.\n" + }, { "migrate-receive", &main_migrate_receive, 0, 1, "Restore a domain from a saved state", diff --git a/tools/xl/xl_saverestore.c b/tools/xl/xl_saverestore.c index 9be033fe65..ba0e300f2c 100644 --- a/tools/xl/xl_saverestore.c +++ b/tools/xl/xl_saverestore.c @@ -229,6 +229,75 @@ int main_restore(int argc, char **argv) return EXIT_SUCCESS; } =20 +int main_fork_vm(int argc, char **argv) +{ + int debug =3D 0; + uint32_t pdomid =3D 0, domid =3D INVALID_DOMID; + int opt; + + SWITCH_FOREACH_OPT(opt, "d", NULL, "fork-vm", 1) { + case 'd': + debug =3D 1; + break; + } + + if (argc-optind =3D=3D 1) { + pdomid =3D atoi(argv[optind]); + } else { + help("fork-vm"); + return EXIT_FAILURE; + } + + if (libxl_domain_fork_vm(ctx, pdomid, &domid) || domid =3D=3D INVALID_= DOMID) + return EXIT_FAILURE; + + fprintf(stderr, "VM fork created with domid: %u\n", domid); + return EXIT_SUCCESS; +} + +int main_fork_launch_dm(int argc, char **argv) +{ + const char *config_file =3D NULL; + const char *dm_restore_file =3D NULL; + struct domain_create dom_info; + int paused =3D 0, debug =3D 0; + uint32_t ddomid =3D 0; + int opt, rc; + + SWITCH_FOREACH_OPT(opt, "pd", NULL, "fork-launch-dm", 1) { + case 'p': + paused =3D 1; + break; + case 'd': + debug =3D 1; + break; + } + + if (argc-optind =3D=3D 3) { + config_file =3D argv[optind]; + dm_restore_file =3D argv[optind + 1]; + ddomid =3D atoi(argv[optind + 2]); + } else { + help("fork-launch-dm"); + return EXIT_FAILURE; + } + + memset(&dom_info, 0, sizeof(dom_info)); + dom_info.ddomid =3D ddomid; + dom_info.dm_restore_file =3D dm_restore_file; + dom_info.debug =3D debug; + dom_info.paused =3D paused; + dom_info.config_file =3D config_file; + dom_info.migrate_fd =3D -1; + dom_info.send_back_fd =3D -1; + + rc =3D create_domain(&dom_info); + if (rc < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + int main_save(int argc, char **argv) { uint32_t domid; diff --git a/tools/xl/xl_vmcontrol.c b/tools/xl/xl_vmcontrol.c index eb6779a561..f32a4714ee 100644 --- a/tools/xl/xl_vmcontrol.c +++ b/tools/xl/xl_vmcontrol.c @@ -645,6 +645,7 @@ int create_domain(struct domain_create *dom_info) =20 libxl_domain_config d_config; =20 + uint32_t ddomid =3D dom_info->ddomid; // launch dm for this domain iff= set int debug =3D dom_info->debug; int daemonize =3D dom_info->daemonize; int monitor =3D dom_info->monitor; @@ -655,6 +656,7 @@ int create_domain(struct domain_create *dom_info) const char *restore_file =3D dom_info->restore_file; const char *config_source =3D NULL; const char *restore_source =3D NULL; + const char *dm_restore_file =3D dom_info->dm_restore_file; int migrate_fd =3D dom_info->migrate_fd; bool config_in_json; =20 @@ -923,6 +925,12 @@ start: * restore/migrate-receive it again. */ restoring =3D 0; + } else if ( ddomid ) { + d_config.dm_restore_file =3D dm_restore_file; + ret =3D libxl_domain_fork_launch_dm(ctx, &d_config, ddomid, + autoconnect_console_how); + domid =3D ddomid; + ddomid =3D INVALID_DOMID; } else if (domid_soft_reset !=3D INVALID_DOMID) { /* Do soft reset. */ ret =3D libxl_domain_soft_reset(ctx, &d_config, domid_soft_reset, --=20 2.20.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel