[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC/WIPv2 3/6] libxc: introduce soft reset
Add new xc_domain_soft_reset() function which performs so-called soft-reset for a domain. During soft reset all source domain's memory is being reassigned to the destination domain, cpu contexts are being copied,... The behavior is similar to save/restore except for memory reassigning. Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> --- tools/libxc/Makefile | 1 + tools/libxc/xc_domain_soft_reset.c | 300 +++++++++++++++++++++++++++++++++++++ tools/libxc/xenguest.h | 19 +++ 3 files changed, 320 insertions(+) create mode 100644 tools/libxc/xc_domain_soft_reset.c diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 3b04027..b5d4b60 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -49,6 +49,7 @@ GUEST_SRCS-y += xc_offline_page.c xc_compression.c else GUEST_SRCS-y += xc_nomigrate.c endif +GUEST_SRCS-y += xc_domain_soft_reset.c vpath %.c ../../xen/common/libelf CFLAGS += -I../../xen/common/libelf diff --git a/tools/libxc/xc_domain_soft_reset.c b/tools/libxc/xc_domain_soft_reset.c new file mode 100644 index 0000000..c5d9873 --- /dev/null +++ b/tools/libxc/xc_domain_soft_reset.c @@ -0,0 +1,300 @@ +/****************************************************************************** + * xc_domain_soft_reset.c + * + * Do soft reset. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <inttypes.h> +#include <time.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/time.h> + +#include "xc_private.h" +#include "xc_core.h" +#include "xc_bitops.h" +#include "xc_dom.h" +#include "xg_private.h" +#include "xg_save_restore.h" + +#include <xen/hvm/params.h> + +static unsigned long saverestore_hvm_param(xc_interface *xch, uint32_t source_dom, + uint32_t dest_dom, int param) +{ + uint64_t val = 0; + xc_hvm_param_get(xch, source_dom, param, &val); + + if ( val ) + xc_hvm_param_set(xch, dest_dom, param, val); + + return val; +} + +int xc_domain_soft_reset(xc_interface *xch, uint32_t source_dom, + uint32_t dest_dom, int hvm, domid_t console_domid, + unsigned int console_evtchn, + unsigned long *console_mfn, + domid_t store_domid, unsigned int store_evtchn, + unsigned long *store_mfn) +{ + DECLARE_DOMCTL; + xc_dominfo_t info; + int rc = 1, i; + + /* A copy of the CPU context of the guest. */ + vcpu_guest_context_any_t _ctxt; + vcpu_guest_context_any_t *ctxt = &_ctxt; + + /* HVM: a buffer for holding HVM context */ + uint32_t hvm_buf_size = 0; + uint8_t *hvm_buf = NULL; + unsigned long console_pfn, store_pfn, io_pfn, buffio_pfn; + unsigned long mfn, pfn, max_pfn, pagetype; + start_info_any_t *start_info; + struct xc_domain_meminfo minfo; + + DPRINTF("%s: soft reset domid %u -> %u", __func__, source_dom, dest_dom); + + if ( xc_domain_getinfo(xch, source_dom, 1, &info) != 1 ) + { + PERROR("Could not get domain info"); + return 1; + } + + max_pfn = xc_domain_maximum_gpfn(xch, source_dom); + + if (!hvm) + { + memset(&minfo, 0, sizeof(minfo)); + if ( xc_map_domain_meminfo(xch, source_dom, &minfo) ) + { + PERROR("Could not map domain %d memory information\n", source_dom); + goto out; + } + for (pfn = 0; pfn < minfo.p2m_size; pfn++) + { + rc = xc_domain_transfer_pages(xch, source_dom, dest_dom, minfo.p2m_table[pfn], 1); + if ( rc != 0 ) + { + PERROR("failed to transfer pfn %lx, rc=%d\n", pfn, rc); + goto out; + } + } + } + + if (hvm) { + rc = xc_domain_transfer_pages(xch, source_dom, dest_dom, 0, max_pfn + 1); + if ( rc != 0 ) + { + PERROR("failed to transfer pages, rc=%d\n", rc); + goto out; + } + + hvm_buf_size = xc_domain_hvm_getcontext(xch, source_dom, 0, 0); + if ( hvm_buf_size == -1 ) + { + PERROR("Couldn't get HVM context size from Xen"); + goto out; + } + + hvm_buf = malloc(hvm_buf_size); + if ( !hvm_buf ) + { + ERROR("Couldn't allocate memory"); + goto out; + } + + if ( xc_domain_hvm_getcontext(xch, source_dom, hvm_buf, + hvm_buf_size) == -1 ) + { + PERROR("HVM:Could not get hvm buffer"); + goto out; + } + + if ( xc_domain_hvm_setcontext(xch, dest_dom, hvm_buf, + hvm_buf_size) == -1 ) + { + PERROR("HVM:Could not set hvm buffer"); + goto out; + } + + store_pfn = saverestore_hvm_param(xch, source_dom, dest_dom, + HVM_PARAM_STORE_PFN); + if ( store_pfn ) + xc_clear_domain_page(xch, dest_dom, store_pfn); + *store_mfn = store_pfn; + + console_pfn = saverestore_hvm_param(xch, source_dom, dest_dom, + HVM_PARAM_CONSOLE_PFN); + if ( console_pfn ) + xc_clear_domain_page(xch, dest_dom, console_pfn); + *console_mfn = console_pfn; + + buffio_pfn = saverestore_hvm_param(xch, source_dom, dest_dom, + HVM_PARAM_BUFIOREQ_PFN); + if ( buffio_pfn ) + xc_clear_domain_page(xch, dest_dom, buffio_pfn); + + io_pfn = saverestore_hvm_param(xch, source_dom, dest_dom, + HVM_PARAM_IOREQ_PFN); + if ( io_pfn ) + xc_clear_domain_page(xch, dest_dom, buffio_pfn); + + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_IDENT_PT); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_PAGING_RING_PFN); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_ACCESS_RING_PFN); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_VM86_TSS); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_ACPI_IOPORTS_LOCATION); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_VIRIDIAN); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_PAE_ENABLED); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_STORE_EVTCHN); + + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_IOREQ_SERVER_PFN); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES); + saverestore_hvm_param(xch, source_dom, dest_dom, HVM_PARAM_VM_GENERATION_ID_ADDR); + + if (xc_dom_gnttab_hvm_seed(xch, dest_dom, console_pfn, store_pfn, + console_domid, store_domid)) + { + PERROR("error seeding hvm grant table"); + goto out; + } + + } + else + { + for ( i = 0; i <= info.max_vcpu_id; i++ ) + { + if ( xc_vcpu_getcontext(xch, source_dom, i, ctxt) ) + { + PERROR("No context for VCPU%d", i); + goto out; + } + domctl.cmd = XEN_DOMCTL_get_ext_vcpucontext; + domctl.domain = source_dom; + memset(&domctl.u, 0, sizeof(domctl.u)); + domctl.u.ext_vcpucontext.vcpu = i; + if ( xc_domctl(xch, &domctl) < 0 ) + { + PERROR("No extended context for VCPU%d", i); + goto out; + } + + if ( xc_vcpu_setcontext(xch, dest_dom, i, ctxt) ) + { + PERROR("Failed to set vcpu context for VCPU%d", i); + goto out; + } + + domctl.cmd = XEN_DOMCTL_set_ext_vcpucontext; + domctl.domain = dest_dom; + if ( xc_domctl(xch, &domctl) < 0 ) + { + PERROR("Failed to set extended context for VCPU%d", i); + goto out; + } + + if ( i == 0 ) + { + /* Mounting start_info for PV guest */ + pfn = GET_FIELD(ctxt, user_regs.edx, minfo.guest_width); + pagetype = minfo.pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + if ( (pfn >= minfo.p2m_size) || + (pagetype != XEN_DOMCTL_PFINFO_NOTAB) ) + { + ERROR("start_info frame number is bad"); + goto out; + } + + mfn = minfo.p2m_table[pfn]; + SET_FIELD(ctxt, user_regs.edx, mfn, minfo.guest_width); + start_info = xc_map_foreign_range( + xch, dest_dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn); + if ( start_info == NULL ) + { + PERROR("xc_map_foreign_range failed (for start_info)"); + goto out; + } + + SET_FIELD(start_info, nr_pages, minfo.p2m_size, + minfo.guest_width); + SET_FIELD(start_info, shared_info, + info.shared_info_frame<<PAGE_SHIFT, minfo.guest_width); + SET_FIELD(start_info, flags, 0, minfo.guest_width); + if ( GET_FIELD(start_info, store_mfn, minfo.guest_width) > + minfo.p2m_size ) + { + ERROR("Suspend record xenstore frame number is bad"); + munmap(start_info, PAGE_SIZE); + goto out; + } + *store_mfn = minfo.p2m_table[GET_FIELD(start_info, store_mfn, + minfo.guest_width)]; + SET_FIELD(start_info, store_mfn, *store_mfn, + minfo.guest_width); + SET_FIELD(start_info, store_evtchn, store_evtchn, + minfo.guest_width); + if ( GET_FIELD(start_info, console.domU.mfn, + minfo.guest_width) > minfo.p2m_size ) + { + ERROR("Suspend record console frame number is bad"); + munmap(start_info, PAGE_SIZE); + goto out; + } + console_pfn = GET_FIELD(start_info, console.domU.mfn, + minfo.guest_width); + *console_mfn = minfo.p2m_table[console_pfn]; + SET_FIELD(start_info, console.domU.mfn, *console_mfn, + minfo.guest_width); + SET_FIELD(start_info, console.domU.evtchn, console_evtchn, + minfo.guest_width); + munmap(start_info, PAGE_SIZE); + } + } + + if (xc_dom_gnttab_seed(xch, dest_dom, *console_mfn, *store_mfn, + console_domid, store_domid)) + { + PERROR("error seeding grant table"); + goto out; + } + } + rc = 0; +out: + if (!hvm) + xc_unmap_domain_meminfo(xch, &minfo); + + if (hvm_buf) free(hvm_buf); + + if ( (rc != 0) && (dest_dom != 0) ) { + PERROR("Faled to perform soft reset, destroying domain %d", dest_dom); + xc_domain_destroy(xch, dest_dom); + } + + return !!rc; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 40bbac8..c1dbabd 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -131,6 +131,25 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, * of the new domain is automatically appended to the filename, * separated by a ".". */ + +/** + * This function doest soft reset for a domain. During soft reset all + * source domain's memory is being reassigned to the destination domain, + * cpu contexts are being copied,... + * + * @parm xch a handle to an open hypervisor interface + * @parm source_dom the id of the source domain + * @parm dest_dom the id of the destination domain + * @parm hvm non-zero if this is an HVM domain + * @return 0 on success, -1 on failure + */ +int xc_domain_soft_reset(xc_interface *xch, uint32_t source_dom, + uint32_t dest_dom, int hvm, domid_t console_domid, + unsigned int console_evtchn, + unsigned long *console_mfn, + domid_t store_domid, unsigned int store_evtchn, + unsigned long *store_mfn); + #define XC_DEVICE_MODEL_RESTORE_FILE "/var/lib/xen/qemu-resume" /** -- 1.9.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |