diff options
-rw-r--r-- | tools/libxc/xc_dom.h | 16 | ||||
-rw-r--r-- | tools/libxc/xc_dom_boot.c | 156 | ||||
-rw-r--r-- | tools/libxc/xc_dom_compat_linux.c | 2 | ||||
-rw-r--r-- | tools/libxc/xc_domain_restore.c | 19 | ||||
-rw-r--r-- | tools/libxc/xenguest.h | 3 | ||||
-rw-r--r-- | tools/libxl/libxl_dom.c | 18 | ||||
-rw-r--r-- | tools/xcutils/xc_restore.c | 4 |
7 files changed, 211 insertions, 7 deletions
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index e72f066f5d..2aef64af26 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -18,6 +18,9 @@ #define INVALID_P2M_ENTRY ((xen_pfn_t)-1) +/* Scrach PFN for temporary mappings in HVM */ +#define SCRATCH_PFN_GNTTAB 0xFFFFE + /* --- typedefs and structs ---------------------------------------- */ typedef uint64_t xen_vaddr_t; @@ -107,6 +110,8 @@ struct xc_dom_image { unsigned long flags; unsigned int console_evtchn; unsigned int xenstore_evtchn; + domid_t console_domid; + domid_t xenstore_domid; xen_pfn_t shared_info_mfn; xc_interface *xch; @@ -200,6 +205,17 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count); int xc_dom_boot_image(struct xc_dom_image *dom); int xc_dom_compat_check(struct xc_dom_image *dom); +int xc_dom_gnttab_init(struct xc_dom_image *dom); +int xc_dom_gnttab_hvm_seed(xc_interface *xch, domid_t domid, + xen_pfn_t console_gmfn, + xen_pfn_t xenstore_gmfn, + domid_t console_domid, + domid_t xenstore_domid); +int xc_dom_gnttab_seed(xc_interface *xch, domid_t domid, + xen_pfn_t console_gmfn, + xen_pfn_t xenstore_gmfn, + domid_t console_domid, + domid_t xenstore_domid); /* --- debugging bits ---------------------------------------------- */ diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c index 65f60df32f..a9a868c06e 100644 --- a/tools/libxc/xc_dom_boot.c +++ b/tools/libxc/xc_dom_boot.c @@ -34,6 +34,7 @@ #include "xg_private.h" #include "xc_dom.h" #include <xen/hvm/params.h> +#include <xen/grant_table.h> /* ------------------------------------------------------------------------ */ @@ -275,6 +276,161 @@ int xc_dom_boot_image(struct xc_dom_image *dom) return rc; } +static xen_pfn_t xc_dom_gnttab_setup(xc_interface *xch, domid_t domid) +{ + gnttab_setup_table_t setup; + DECLARE_HYPERCALL_BUFFER(xen_pfn_t, gmfnp); + int rc; + xen_pfn_t gmfn; + + gmfnp = xc_hypercall_buffer_alloc(xch, gmfnp, sizeof(*gmfnp)); + if (gmfnp == NULL) + return -1; + + setup.dom = domid; + setup.nr_frames = 1; + set_xen_guest_handle(setup.frame_list, gmfnp); + setup.status = 0; + + rc = xc_gnttab_op(xch, GNTTABOP_setup_table, &setup, sizeof(setup), 1); + gmfn = *gmfnp; + xc_hypercall_buffer_free(xch, gmfnp); + + if ( rc != 0 || setup.status != GNTST_okay ) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to setup domU grant table " + "[errno=%d, status=%" PRId16 "]\n", + __FUNCTION__, rc != 0 ? errno : 0, setup.status); + return -1; + } + + return gmfn; +} + +int xc_dom_gnttab_seed(xc_interface *xch, domid_t domid, + xen_pfn_t console_gmfn, + xen_pfn_t xenstore_gmfn, + domid_t console_domid, + domid_t xenstore_domid) +{ + + xen_pfn_t gnttab_gmfn; + grant_entry_v1_t *gnttab; + + gnttab_gmfn = xc_dom_gnttab_setup(xch, domid); + if ( gnttab_gmfn == -1 ) + return -1; + + gnttab = xc_map_foreign_range(xch, + domid, + PAGE_SIZE, + PROT_READ|PROT_WRITE, + gnttab_gmfn); + if ( gnttab == NULL ) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to map domU grant table " + "[errno=%d]\n", + __FUNCTION__, errno); + return -1; + } + + if ( domid != console_domid && console_gmfn != -1) + { + gnttab[GNTTAB_RESERVED_CONSOLE].flags = GTF_permit_access; + gnttab[GNTTAB_RESERVED_CONSOLE].domid = console_domid; + gnttab[GNTTAB_RESERVED_CONSOLE].frame = console_gmfn; + } + if ( domid != xenstore_domid && xenstore_gmfn != -1) + { + gnttab[GNTTAB_RESERVED_XENSTORE].flags = GTF_permit_access; + gnttab[GNTTAB_RESERVED_XENSTORE].domid = xenstore_domid; + gnttab[GNTTAB_RESERVED_XENSTORE].frame = xenstore_gmfn; + } + + if ( munmap(gnttab, PAGE_SIZE) == -1 ) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to unmap domU grant table " + "[errno=%d]\n", + __FUNCTION__, errno); + return -1; + } + + return 0; +} + +int xc_dom_gnttab_hvm_seed(xc_interface *xch, domid_t domid, + xen_pfn_t console_gpfn, + xen_pfn_t xenstore_gpfn, + domid_t console_domid, + domid_t xenstore_domid) +{ + int rc; + struct xen_add_to_physmap xatp = { + .domid = domid, + .space = XENMAPSPACE_grant_table, + .idx = 0, + .gpfn = SCRATCH_PFN_GNTTAB + }; + struct xen_remove_from_physmap xrfp = { + .domid = domid, + .gpfn = SCRATCH_PFN_GNTTAB + }; + + rc = do_memory_op(xch, XENMEM_add_to_physmap, &xatp, sizeof(xatp)); + if ( rc != 0 ) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to add gnttab to physmap " + "[errno=%d]\n", + __FUNCTION__, errno); + return -1; + } + + rc = xc_dom_gnttab_seed(xch, domid, + console_gpfn, xenstore_gpfn, + console_domid, xenstore_domid); + if (rc != 0) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to seed gnttab entries\n", + __FUNCTION__); + (void) do_memory_op(xch, XENMEM_remove_from_physmap, &xrfp, sizeof(xrfp)); + return -1; + } + + rc = do_memory_op(xch, XENMEM_remove_from_physmap, &xrfp, sizeof(xrfp)); + if (rc != 0) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, + "%s: failed to remove gnttab from physmap " + "[errno=%d]\n", + __FUNCTION__, errno); + return -1; + } + + return 0; +} + +int xc_dom_gnttab_init(struct xc_dom_image *dom) +{ + xen_pfn_t console_gmfn; + xen_pfn_t xenstore_gmfn; + int autotranslated; + + autotranslated = xc_dom_feature_translated(dom); + console_gmfn = autotranslated ? + dom->console_pfn : xc_dom_p2m_host(dom, dom->console_pfn); + xenstore_gmfn = autotranslated ? + dom->xenstore_pfn : xc_dom_p2m_host(dom, dom->xenstore_pfn); + + return xc_dom_gnttab_seed(dom->xch, dom->guest_domid, + console_gmfn, xenstore_gmfn, + dom->console_domid, dom->xenstore_domid); +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_dom_compat_linux.c b/tools/libxc/xc_dom_compat_linux.c index 0e78842ef7..2183a3be23 100644 --- a/tools/libxc/xc_dom_compat_linux.c +++ b/tools/libxc/xc_dom_compat_linux.c @@ -62,6 +62,8 @@ static int xc_linux_build_internal(struct xc_dom_image *dom, goto out; if ( (rc = xc_dom_boot_image(dom)) != 0 ) goto out; + if ( (rc = xc_dom_gnttab_init(dom)) != 0) + goto out; *console_mfn = xc_dom_p2m_host(dom, dom->console_pfn); *store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn); diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 3fda6f8c68..06bea86718 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -1259,7 +1259,8 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx, int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, + domid_t store_domid, unsigned int console_evtchn, + unsigned long *console_mfn, domid_t console_domid, unsigned int hvm, unsigned int pae, int superpages, int no_incr_generationid, unsigned long *vm_generationid_addr) @@ -2018,6 +2019,14 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, memcpy(ctx->live_p2m, ctx->p2m, dinfo->p2m_size * sizeof(xen_pfn_t)); munmap(ctx->live_p2m, P2M_FL_ENTRIES * PAGE_SIZE); + rc = xc_dom_gnttab_seed(xch, dom, *console_mfn, *store_mfn, + console_domid, store_domid); + if (rc != 0) + { + ERROR("error seeding grant table"); + goto out; + } + DPRINTF("Domain ready to be built.\n"); rc = 0; goto out; @@ -2076,6 +2085,14 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, goto out; } + rc = xc_dom_gnttab_hvm_seed(xch, dom, *console_mfn, *store_mfn, + console_domid, store_domid); + if (rc != 0) + { + ERROR("error seeding grant table"); + goto out; + } + /* HVM success! */ rc = 0; diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 60263709ce..533e70279b 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -79,7 +79,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter */ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, + domid_t store_domid, unsigned int console_evtchn, + unsigned long *console_mfn, domid_t console_domid, unsigned int hvm, unsigned int pae, int superpages, int no_incr_generationid, unsigned long *vm_generationid_addr); diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index e4961ebb52..60ed1d55ad 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -225,7 +225,9 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, dom->flags = flags; dom->console_evtchn = state->console_port; + dom->console_domid = state->console_domid; dom->xenstore_evtchn = state->store_port; + dom->xenstore_domid = state->store_domid; if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_boot_xen_init failed"); @@ -251,6 +253,10 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_boot_image failed"); goto out; } + if ( (ret = xc_dom_gnttab_init(dom)) != 0 ) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_gnttab_init failed"); + goto out; + } state->console_mfn = xc_dom_p2m_host(dom, dom->console_pfn); state->store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn); @@ -271,7 +277,8 @@ static unsigned long timer_mode(const libxl_domain_build_info *info) 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) + int console_evtchn, unsigned long *console_mfn, + domid_t store_domid, domid_t console_domid) { struct hvm_info_table *va_hvm; uint8_t *va_map, sum; @@ -304,6 +311,8 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid, xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM, info->u.hvm.nested_hvm); xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn); xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn); + + xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid); return 0; } @@ -355,7 +364,9 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, goto out; } ret = hvm_build_set_params(ctx->xch, domid, info, state->store_port, - &state->store_mfn, state->console_port, &state->console_mfn); + &state->store_mfn, state->console_port, + &state->console_mfn, state->store_domid, + state->console_domid); if (ret) { LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm build set params failed"); goto out; @@ -402,7 +413,8 @@ int libxl__domain_restore_common(libxl__gc *gc, uint32_t domid, } rc = xc_domain_restore(ctx->xch, fd, domid, state->store_port, &state->store_mfn, - state->console_port, &state->console_mfn, + state->store_domid, state->console_port, + &state->console_mfn, state->console_domid, hvm, pae, superpages, no_incr_generationid, &state->vm_generationid_addr); if ( rc ) { diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 63d53a88b0..e41a133732 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -45,8 +45,8 @@ main(int argc, char **argv) else superpages = !!hvm; - ret = xc_domain_restore(xch, io_fd, domid, store_evtchn, &store_mfn, - console_evtchn, &console_mfn, hvm, pae, superpages, + ret = xc_domain_restore(xch, io_fd, domid, store_evtchn, &store_mfn, 0, + console_evtchn, &console_mfn, 0, hvm, pae, superpages, 0, NULL); if ( ret == 0 ) |