static int alloc_magic_pages(struct xc_dom_image *dom) { int rc, i; xen_pfn_t p2m[NR_MAGIC_PAGES]; DOMPRINTF_CALLED(dom->xch); for (i = 0; i < NR_MAGIC_PAGES; i++) p2m[i] = dom->rambase_pfn + dom->total_pages + i; rc = xc_domain_populate_physmap_exact( dom->xch, dom->guest_domid, NR_MAGIC_PAGES, 0, 0, p2m); if ( rc < 0 ) return rc; dom->console_pfn = dom->rambase_pfn + dom->total_pages + CONSOLE_PFN_OFFSET; dom->xenstore_pfn = dom->rambase_pfn + dom->total_pages + XENSTORE_PFN_OFFSET; xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn); xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN, dom->console_pfn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN, dom->xenstore_pfn); /* allocated by toolstack */ xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN, dom->console_evtchn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN, dom->xenstore_evtchn); return 0; }
/* * Process an HVM_PARAMS record from the stream. */ static int handle_hvm_params(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; struct xc_sr_rec_hvm_params *hdr = rec->data; struct xc_sr_rec_hvm_params_entry *entry = hdr->param; unsigned int i; int rc; if ( rec->length < sizeof(*hdr) || rec->length < sizeof(*hdr) + hdr->count * sizeof(*entry) ) { ERROR("hvm_params record is too short"); return -1; } for ( i = 0; i < hdr->count; i++, entry++ ) { switch ( entry->index ) { case HVM_PARAM_CONSOLE_PFN: ctx->restore.console_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_STORE_PFN: ctx->restore.xenstore_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: xc_clear_domain_page(xch, ctx->domid, entry->value); break; } rc = xc_hvm_param_set(xch, ctx->domid, entry->index, entry->value); if ( rc < 0 ) { PERROR("set HVM param %"PRId64" = 0x%016"PRIx64, entry->index, entry->value); return rc; } } return 0; }
static int clear_page(struct xc_dom_image *dom, xen_pfn_t pfn) { xen_pfn_t dst; int rc; if ( pfn == 0 ) return 0; dst = xc_dom_p2m_host(dom, pfn); xc_dom_printf("%s: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n", __FUNCTION__, pfn, dst); rc = xc_clear_domain_page(dom->guest_xc, dom->guest_domid, dst); if ( rc != 0 ) xc_dom_panic(XC_INTERNAL_ERROR, "%s: xc_clear_domain_page failed (pfn 0x%" PRIpfn ", rc=%d)\n", __FUNCTION__, pfn, rc); return rc; }
/* * Process an HVM_PARAMS record from the stream. */ static int handle_hvm_params(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; struct xc_sr_rec_hvm_params *hdr = rec->data; struct xc_sr_rec_hvm_params_entry *entry = hdr->param; unsigned int i; int rc; if ( rec->length < sizeof(*hdr) ) { ERROR("HVM_PARAMS record truncated: length %u, header size %zu", rec->length, sizeof(*hdr)); return -1; } if ( rec->length != (sizeof(*hdr) + hdr->count * sizeof(*entry)) ) { ERROR("HVM_PARAMS record truncated: header %zu, count %u, " "expected len %zu, got %u", sizeof(*hdr), hdr->count, hdr->count * sizeof(*entry), rec->length); return -1; } /* * Tolerate empty records. Older sending sides used to accidentally * generate them. */ if ( hdr->count == 0 ) { DBGPRINTF("Skipping empty HVM_PARAMS record\n"); return 0; } for ( i = 0; i < hdr->count; i++, entry++ ) { switch ( entry->index ) { case HVM_PARAM_CONSOLE_PFN: ctx->restore.console_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_STORE_PFN: ctx->restore.xenstore_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: xc_clear_domain_page(xch, ctx->domid, entry->value); break; } rc = xc_hvm_param_set(xch, ctx->domid, entry->index, entry->value); if ( rc < 0 ) { PERROR("set HVM param %"PRId64" = 0x%016"PRIx64, entry->index, entry->value); return rc; } } return 0; }
static int xc_ia64_hvm_recv_context(int xc_handle, int io_fd, uint32_t dom, unsigned long shared_info_frame, struct xen_ia64_p2m_table *p2m_table, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int console_evtchn, unsigned long *console_mfn) { int rc = -1; xc_dominfo_t info; unsigned int i; /* cpumap */ uint64_t *vcpumap = NULL; /* HVM: magic frames for ioreqs and xenstore comms */ const int hvm_params[] = { HVM_PARAM_STORE_PFN, HVM_PARAM_IOREQ_PFN, HVM_PARAM_BUFIOREQ_PFN, HVM_PARAM_BUFPIOREQ_PFN, }; const int NR_PARAMS = sizeof(hvm_params) / sizeof(hvm_params[0]); /* ioreq_pfn, bufioreq_pfn, store_pfn */ uint64_t magic_pfns[NR_PARAMS]; /* HVM: a buffer for holding HVM contxt */ uint64_t rec_size = 0; uint8_t *hvm_buf = NULL; /* Read shared info. */ if (xc_ia64_recv_shared_info(xc_handle, io_fd, dom, shared_info_frame, NULL)) goto out; /* vcpu map */ if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) { ERROR("Could not get domain info"); goto out; } if (xc_ia64_recv_vcpumap(&info, io_fd, &vcpumap)) goto out; /* vcpu context */ for (i = 0; i <= info.max_vcpu_id; i++) { /* A copy of the CPU context of the guest. */ vcpu_guest_context_any_t ctxt_any; if (!__test_bit(i, vcpumap)) continue; if (xc_ia64_recv_vcpu_context(xc_handle, io_fd, dom, i, &ctxt_any)) goto out; /* system context of vcpu is recieved as hvm context. */ } /* Set HVM-specific parameters */ if (read_exact(io_fd, magic_pfns, sizeof(magic_pfns))) { ERROR("error reading magic page addresses"); goto out; } /* These comms pages need to be zeroed at the start of day */ for (i = 0; i < NR_PARAMS; i++) { rc = xc_clear_domain_page(xc_handle, dom, magic_pfns[i]); if (rc != 0) { ERROR("error zeroing magic pages: %i", rc); goto out; } rc = xc_set_hvm_param(xc_handle, dom, hvm_params[i], magic_pfns[i]); if (rc != 0) { ERROR("error setting HVM params: %i", rc); goto out; } } rc = xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn); if (rc != 0) { ERROR("error setting HVM params: %i", rc); goto out; } rc = -1; *store_mfn = magic_pfns[0]; /* Read HVM context */ if (read_exact(io_fd, &rec_size, sizeof(rec_size))) { ERROR("error read hvm context size!\n"); goto out; } hvm_buf = malloc(rec_size); if (hvm_buf == NULL) { ERROR("memory alloc for hvm context buffer failed"); errno = ENOMEM; goto out; } if (read_exact(io_fd, hvm_buf, rec_size)) { ERROR("error loading the HVM context"); goto out; } rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_size); if (rc != 0) { ERROR("error setting the HVM context"); goto out; } rc = 0; out: if (vcpumap != NULL) free(vcpumap); if (hvm_buf != NULL) free(hvm_buf); return rc; }