aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/xc_dom.h16
-rw-r--r--tools/libxc/xc_dom_boot.c156
-rw-r--r--tools/libxc/xc_dom_compat_linux.c2
-rw-r--r--tools/libxc/xc_domain_restore.c19
-rw-r--r--tools/libxc/xenguest.h3
-rw-r--r--tools/libxl/libxl_dom.c18
-rw-r--r--tools/xcutils/xc_restore.c4
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 )