ivc_connection_t *acceptConnection(libIVC_t *iface, char *name, ivc_contype_t type, uint32_t num_pages, float per) { char *key, *val, *domStr = NULL; uint32_t me, other, *gs, ps; unsigned int len; void *buffer; /* we can only do this if we create grant references */ if(!iface->gs) return NULL; /* other <- read `fmap` waitForKey xs (targetPath ++ "/LeftDomId) */ ASPRINTF(&key, "/rendezvous/%s/LeftDomId", name); while(!domStr) { domStr = xs_read(iface->xs, 0, key, &len); } sscanf(domStr, "dom%d", &other); /* me <- xsGetDomId */ me = getMyDomId(iface); /* (gs, ps, confirm) <- makeConnection other extra */ gs = calloc(num_pages, sizeof(uint32_t)); buffer = xc_gntshr_share_pages(iface->gs, other, num_pages, gs, 1); assert(buffer); ps = xc_evtchn_bind_unbound_port(iface->ec, other); assert(ps); /* xsWrite xs (targetPath ++ "/RightDomId") (show me) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightDomId", name); free(val), ASPRINTF(&val, "dom%d", me); xs_write(iface->xs, 0, key, val, strlen(val)); /* xsWrite xs (targetPath ++ "/RightGrantRefs") (show gs) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightGrantRefs", name); free(val), val = showGrantRefList(gs, num_pages); xs_write(iface->xs, 0, key, val, strlen(val)); /* xsWrite xs (targetPath ++ "/RightPorts") (show ps) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightPorts", name); free(val), ASPRINTF(&val, "[echan:%d]", ps); xs_write(iface->xs, 0, key, val, strlen(val)); /* _ <- waitForKey xs (targetPath ++ "/LeftConnectionConfirmed") */ free(key), ASPRINTF(&key, "/rendezvous/%s/LeftConnectionConfirmed", name); free(val), val = NULL; while(!val) { val = xs_read(iface->xs, 0, key, &len); } /* removePath xs targetPath */ free(key), ASPRINTF(&key, "/rendezvous/%s", name); xs_rm(iface->xs, 0, key); /* confirm */ return buildChannel(iface, other, type, ps, buffer, 4096 * num_pages, per, 1); }
CAMLprim value stub_xc_gntshr_share_pages(value xgh, value domid, value count, value writeable) { CAMLparam4(xgh, domid, count, writeable); CAMLlocal4(result, ml_refs, ml_refs_cons, ml_map); #ifdef HAVE_GNTSHR void *map; uint32_t *refs; uint32_t c_domid; int c_count; int i; c_count = Int_val(count); c_domid = Int32_val(domid); result = caml_alloc(2, 0); refs = (uint32_t *) malloc(c_count * sizeof(uint32_t)); map = xc_gntshr_share_pages(_G(xgh), c_domid, c_count, refs, Bool_val(writeable)); if(NULL == map) { free(refs); failwith_xc(_G(xgh)); } // Construct the list of grant references. ml_refs = Val_emptylist; for(i = c_count - 1; i >= 0; i--) { ml_refs_cons = caml_alloc(2, 0); Store_field(ml_refs_cons, 0, caml_copy_int32(refs[i])); Store_field(ml_refs_cons, 1, ml_refs); ml_refs = ml_refs_cons; } ml_map = caml_ba_alloc_dims(XC_GNTTAB_BIGARRAY, 1, map, c_count << XC_PAGE_SHIFT); Store_field(result, 0, ml_refs); Store_field(result, 1, ml_map); free(refs); #else gntshr_missing(); #endif CAMLreturn(result); }
static int init_gnt_srv(struct libxenvchan *ctrl, int domain) { int pages_left = ctrl->read.order >= PAGE_SHIFT ? 1 << (ctrl->read.order - PAGE_SHIFT) : 0; int pages_right = ctrl->write.order >= PAGE_SHIFT ? 1 << (ctrl->write.order - PAGE_SHIFT) : 0; uint32_t ring_ref = -1; void *ring; ring = xc_gntshr_share_page_notify(ctrl->gntshr, domain, &ring_ref, 1, offsetof(struct vchan_interface, srv_live), ctrl->event_port); if (!ring) goto out; memset(ring, 0, PAGE_SIZE); ctrl->ring = ring; ctrl->read.shr = &ctrl->ring->left; ctrl->write.shr = &ctrl->ring->right; ctrl->ring->left_order = ctrl->read.order; ctrl->ring->right_order = ctrl->write.order; ctrl->ring->cli_live = 2; ctrl->ring->srv_live = 1; ctrl->ring->cli_notify = VCHAN_NOTIFY_WRITE; switch (ctrl->read.order) { case SMALL_RING_SHIFT: ctrl->read.buffer = ((void*)ctrl->ring) + SMALL_RING_OFFSET; break; case LARGE_RING_SHIFT: ctrl->read.buffer = ((void*)ctrl->ring) + LARGE_RING_OFFSET; break; default: ctrl->read.buffer = xc_gntshr_share_pages(ctrl->gntshr, domain, pages_left, ctrl->ring->grants, 1); if (!ctrl->read.buffer) goto out_ring; } switch (ctrl->write.order) { case SMALL_RING_SHIFT: ctrl->write.buffer = ((void*)ctrl->ring) + SMALL_RING_OFFSET; break; case LARGE_RING_SHIFT: ctrl->write.buffer = ((void*)ctrl->ring) + LARGE_RING_OFFSET; break; default: ctrl->write.buffer = xc_gntshr_share_pages(ctrl->gntshr, domain, pages_right, ctrl->ring->grants + pages_left, 1); if (!ctrl->write.buffer) goto out_unmap_left; } out: return ring_ref; out_unmap_left: if (pages_left) xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left); out_ring: xc_gntshr_munmap(ctrl->gntshr, ring, 1); ring_ref = -1; ctrl->ring = NULL; ctrl->write.order = ctrl->read.order = 0; goto out; }
/* Open an interface to gntshr or gnttab each time it is needed. */ int test_open_multiple() { xc_gntshr *gntshr_if; xc_gnttab *gnttab_if; uint32_t refs[PAGE_COUNT]; uint32_t domids[PAGE_COUNT]; void* local_share; void* remote_share; int i; int err; gntshr_if = xc_gntshr_open(NULL, 0); if(!gntshr_if) { printf("Failed to open gntshr interface.\n"); return 1; } gnttab_if = xc_gnttab_open(NULL, 0); if(!gnttab_if) { printf("Failed to open gnttab interface.\n"); return 1; } local_share = xc_gntshr_share_pages(gntshr_if, DOMID, PAGE_COUNT, refs, 0); if(!local_share) { printf("Failed to share memory.\n"); return 1; } for(i = 0; i < PAGE_COUNT; i++) { printf("Sharing page with ref %d.\n", refs[i]); } for(i = 0; i < PAGE_COUNT; i++) { domids[i] = DOMID; } remote_share = xc_gnttab_map_grant_refs( gnttab_if, PAGE_COUNT, domids, refs, PROT_READ); if(!remote_share) { printf("Failed to map memory.\n"); return 1; } if(xc_gntshr_close(gntshr_if)) { printf("Failed to close gntshr interface.\n"); return 1; } if(xc_gnttab_close(gnttab_if)) { printf("Failed to close gnttab interface.\n"); return 1; } gntshr_if = xc_gntshr_open(NULL, 0); if(!gntshr_if) { printf("Failed to open gntshr interface.\n"); return 1; } gnttab_if = xc_gnttab_open(NULL, 0); if(!gnttab_if) { printf("Failed to open gnttab interface.\n"); return 1; } err = xc_gnttab_munmap(gnttab_if, remote_share, 1); if(err) { printf("Failed to unmap memory - got error code %d.\n", err); return 1; } err = xc_gntshr_munmap(gntshr_if, local_share, 1); if(err) { printf("Failed to unshare memory - got error code %d.\n", err); return 1; } if(xc_gntshr_close(gntshr_if)) { printf("Failed to close gntshr interface.\n"); return 1; } if(xc_gnttab_close(gnttab_if)) { printf("Failed to close gnttab interface.\n"); return 1; } return 0; }