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_gnttab_get_version(xc_interface *xch, int domid) { struct gnttab_get_version query; int rc; query.dom = domid; rc = xc_gnttab_op(xch, GNTTABOP_get_version, &query, sizeof(query), 1); if ( rc < 0 ) return rc; else return query.version; }
static void *_gnttab_map_table(xc_interface *xch, int domid, int *gnt_num) { int rc, i; struct gnttab_query_size query; struct gnttab_setup_table setup; DECLARE_HYPERCALL_BUFFER(unsigned long, frame_list); xen_pfn_t *pfn_list = NULL; grant_entry_v1_t *gnt = NULL; if ( !gnt_num ) return NULL; query.dom = domid; rc = xc_gnttab_op(xch, GNTTABOP_query_size, &query, sizeof(query), 1); if ( rc || (query.status != GNTST_okay) ) { ERROR("Could not query dom's grant size\n", domid); return NULL; } *gnt_num = query.nr_frames * (PAGE_SIZE / sizeof(grant_entry_v1_t) ); frame_list = xc_hypercall_buffer_alloc(xch, frame_list, query.nr_frames * sizeof(unsigned long)); if ( !frame_list ) { ERROR("Could not allocate frame_list in xc_gnttab_map_table\n"); return NULL; } pfn_list = malloc(query.nr_frames * sizeof(xen_pfn_t)); if ( !pfn_list ) { ERROR("Could not allocate pfn_list in xc_gnttab_map_table\n"); goto err; } setup.dom = domid; setup.nr_frames = query.nr_frames; set_xen_guest_handle(setup.frame_list, frame_list); /* XXX Any race with other setup_table hypercall? */ rc = xc_gnttab_op(xch, GNTTABOP_setup_table, &setup, sizeof(setup), 1); if ( rc || (setup.status != GNTST_okay) ) { ERROR("Could not get grant table frame list\n"); goto err; } for ( i = 0; i < setup.nr_frames; i++ ) pfn_list[i] = frame_list[i]; gnt = xc_map_foreign_pages(xch, domid, PROT_READ, pfn_list, setup.nr_frames); if ( !gnt ) { ERROR("Could not map grant table\n"); goto err; } err: if ( frame_list ) xc_hypercall_buffer_free(xch, frame_list); if ( pfn_list ) free(pfn_list); return gnt; }