#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;
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;
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 ---------------------------------------------- */
#include "xg_private.h"
#include "xc_dom.h"
#include <xen/hvm/params.h>
+#include <xen/grant_table.h>
/* ------------------------------------------------------------------------ */
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
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);
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)
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;
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;
*/
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);
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");
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);
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;
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;
}
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;
}
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 ) {
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 )