uint64_t xen_memshare(xen_interface_t *xen, domid_t domID, domid_t cloneID) { uint64_t shared = 0; #if __XEN_INTERFACE_VERSION__ < 0x00040600 uint64_t page, max_page = xc_domain_maximum_gpfn(xen->xc, domID); #else xen_pfn_t page, max_page; if (xc_domain_maximum_gpfn(xen->xc, domID, &max_page)) { printf("Failed to get max gpfn from Xen!\n"); goto done; } #endif if (!max_page) { printf("Failed to get max gpfn!\n"); goto done; } if (xc_memshr_control(xen->xc, domID, 1)) { printf("Failed to enable memsharing on origin!\n"); goto done; } if (xc_memshr_control(xen->xc, cloneID, 1)) { printf("Failed to enable memsharing on clone!\n"); goto done; } /* * page will underflow when done */ for (page = max_page; page <= max_page; page--) { uint64_t shandle, chandle; if (xc_memshr_nominate_gfn(xen->xc, domID, page, &shandle)) continue; if (xc_memshr_nominate_gfn(xen->xc, cloneID, page, &chandle)) continue; if (xc_memshr_share_gfns(xen->xc, domID, page, shandle, cloneID, page, chandle)) continue; shared++; } done: return shared; }
int main(int argc, char **argv) { if (argc < 3) { printf("Usage: %s origin-domID clone-domID\n", argv[0]); return 1; } domid_t origin = atoi(argv[1]), clone = atoi(argv[2]); xc_interface *xc = xc_interface_open(0, 0, 0); vcpu_guest_context_any_t vcpu_context; uint32_t hvm_context_size; uint8_t *hvm_context; if (xc == NULL) { fprintf(stderr, "xc_interface_open() failed!\n"); return 0; } if (xc_vcpu_getcontext(xc, origin, 0, &vcpu_context)) { printf("Failed to get the VCPU context of domain %u\n", origin); return 1; } printf("Setting VCPU context of clone\n"); if (xc_vcpu_setcontext(xc, clone, 0, &vcpu_context)) { printf("Failed to set the VCPU context of domain %u\n", clone); } /*printf("Setting HVM parameters of clone\n"); int hvm_param_copy = 0; while (hvm_param_copy < HVM_PARAM_COUNT) { unsigned long value = 0; xc_get_hvm_param(xc, origin, hvm_params[hvm_param_copy], &value); if (value) { switch (hvm_params[hvm_param_copy]) { case HVM_PARAM_CONSOLE_PFN: case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: case HVM_PARAM_STORE_PFN: break; default: printf("Setting HVM param %i with value %lu\n", hvm_params[hvm_param_copy], value); xc_set_hvm_param(xc, clone, hvm_params[hvm_param_copy], value); break; } } hvm_param_copy++; }*/ hvm_context_size = xc_domain_hvm_getcontext(xc, origin, NULL, 0); if (hvm_context_size <= 0) { printf("HVM context size <= 0. Not an HVM domain?\n"); return 1; } hvm_context = malloc(hvm_context_size * sizeof(uint8_t)); if (xc_domain_hvm_getcontext(xc, origin, hvm_context, hvm_context_size) <= 0) { printf("Failed to get HVM context.\n"); return 1; } xc_dominfo_t info; xc_domain_getinfo(xc, origin, 1, &info); int page = xc_domain_maximum_gpfn(xc, origin) + 1; printf("Sharing memory.. Origin domain has %lu kb ram and %i pages.\n", info.max_memkb, page); xc_memshr_control(xc, origin, 1); xc_memshr_control(xc, clone, 1); uint64_t shandle, chandle; int shared = 0; while (page >= 0) { page--; if (xc_memshr_nominate_gfn(xc, origin, page, &shandle)) { continue; } if (xc_memshr_nominate_gfn(xc, clone, page, &chandle)) { continue; } if (xc_memshr_share_gfns(xc, origin, page, shandle, clone, page, chandle)) continue; shared++; } printf("Shared %i pages\n", shared); /*hvm_param_copy = 0; while (hvm_param_copy < HVM_PARAM_COUNT) { unsigned long value = 0; switch(hvm_params[hvm_param_copy]) { case HVM_PARAM_CONSOLE_PFN: case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: case HVM_PARAM_STORE_PFN: xc_get_hvm_param(xc, origin, hvm_params[hvm_param_copy], &value); if (value) { printf("Setting HVM param %i with value %lu\n", hvm_params[hvm_param_copy], value); xc_clear_domain_page(xc, clone, hvm_params[hvm_param_copy]); xc_set_hvm_param(xc, clone, hvm_params[hvm_param_copy], value); } break; } hvm_param_copy++; }*/ /*printf("Setting HVM context of clone\n"); if (xc_domain_hvm_setcontext(xc, clone, hvm_context, hvm_context_size)) { printf("Failed to set HVM context.\n"); return 1; }*/ xc_interface_close(xc); return 0; }