예제 #1
0
static int
xc_ia64_recv_vcpu_context(int xc_handle, int io_fd, uint32_t dom,
                          uint32_t vcpu, vcpu_guest_context_any_t *ctxt_any)
{
    vcpu_guest_context_t *ctxt = &ctxt_any->c;
    if (read_exact(io_fd, ctxt, sizeof(*ctxt))) {
        ERROR("Error when reading ctxt");
        return -1;
    }

    fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt->regs.ip, ctxt->regs.b[0]);

    /* Initialize and set registers.  */
    ctxt->flags = VGCF_EXTRA_REGS | VGCF_SET_CR_IRR | VGCF_online;
    if (xc_vcpu_setcontext(xc_handle, dom, vcpu, ctxt_any) != 0) {
        ERROR("Couldn't set vcpu context");
        return -1;
    }

    /* Just a check.  */
    ctxt->flags = 0;
    if (xc_vcpu_getcontext(xc_handle, dom, vcpu, ctxt_any)) {
        ERROR("Could not get vcpu context");
        return -1;
    }

    return 0;
}
예제 #2
0
파일: xc_resume.c 프로젝트: Fantu/Xen
static int modify_returncode(xc_interface *xch, uint32_t domid)
{
    vcpu_guest_context_any_t ctxt;
    xc_dominfo_t info;
    xen_capabilities_info_t caps;
    struct domain_info_context _dinfo = {};
    struct domain_info_context *dinfo = &_dinfo;
    int rc;

    if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ||
         info.domid != domid )
    {
        PERROR("Could not get domain info");
        return -1;
    }

    if ( !info.shutdown || (info.shutdown_reason != SHUTDOWN_suspend) )
    {
        ERROR("Dom %d not suspended: (shutdown %d, reason %d)", domid,
              info.shutdown, info.shutdown_reason);
        errno = EINVAL;
        return -1;
    }

    if ( info.hvm )
    {
        /* HVM guests without PV drivers have no return code to modify. */
        uint64_t irq = 0;
        xc_hvm_param_get(xch, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
        if ( !irq )
            return 0;

        /* HVM guests have host address width. */
        if ( xc_version(xch, XENVER_capabilities, &caps) != 0 )
        {
            PERROR("Could not get Xen capabilities");
            return -1;
        }
        dinfo->guest_width = strstr(caps, "x86_64") ? 8 : 4;
    }
    else
    {
        /* Probe PV guest address width. */
        if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) )
            return -1;
    }

    if ( (rc = xc_vcpu_getcontext(xch, domid, 0, &ctxt)) != 0 )
        return rc;

    SET_FIELD(&ctxt, user_regs.eax, 1, dinfo->guest_width);

    if ( (rc = xc_vcpu_setcontext(xch, domid, 0, &ctxt)) != 0 )
        return rc;

    return 0;
}
예제 #3
0
파일: xc_dom_boot.c 프로젝트: Fantu/Xen
static int launch_vm(xc_interface *xch, domid_t domid,
                     vcpu_guest_context_any_t *ctxt)
{
    int rc;

    xc_dom_printf(xch, "%s: called, ctxt=%p", __FUNCTION__, ctxt);
    rc = xc_vcpu_setcontext(xch, domid, 0, ctxt);
    if ( rc != 0 )
        xc_dom_panic(xch, XC_INTERNAL_ERROR,
                     "%s: SETVCPUCONTEXT failed (rc=%d)", __FUNCTION__, rc);
    return rc;
}
예제 #4
0
static int modify_returncode(int xc_handle, uint32_t domid)
{
    vcpu_guest_context_any_t ctxt;
    xc_dominfo_t info;
    xen_capabilities_info_t caps;
    struct domain_info_context _dinfo = {};
    struct domain_info_context *dinfo = &_dinfo;
    int rc;

    if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
    {
        PERROR("Could not get domain info");
        return -1;
    }

    if ( info.hvm )
    {
        /* HVM guests without PV drivers have no return code to modify. */
        unsigned long irq = 0;
        xc_get_hvm_param(xc_handle, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
        if ( !irq )
            return 0;

        /* HVM guests have host address width. */
        if ( xc_version(xc_handle, XENVER_capabilities, &caps) != 0 )
        {
            PERROR("Could not get Xen capabilities\n");
            return -1;
        }
        dinfo->guest_width = strstr(caps, "x86_64") ? 8 : 4;
    }
    else
    {
        /* Probe PV guest address width. */
        dinfo->guest_width = pv_guest_width(xc_handle, domid);
        if ( dinfo->guest_width < 0 )
            return -1;
    }

    if ( (rc = xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt)) != 0 )
        return rc;

    SET_FIELD(&ctxt, user_regs.eax, 1);

    if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt)) != 0 )
        return rc;

    return 0;
}
예제 #5
0
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;
}
예제 #6
0
파일: xc_resume.c 프로젝트: Fantu/Xen
static int xc_domain_resume_any(xc_interface *xch, uint32_t domid)
{
    DECLARE_DOMCTL;
    xc_dominfo_t info;
    int i, rc = -1;
#if defined(__i386__) || defined(__x86_64__)
    struct domain_info_context _dinfo = { .guest_width = 0,
                                          .p2m_size = 0 };
    struct domain_info_context *dinfo = &_dinfo;
    unsigned long mfn;
    vcpu_guest_context_any_t ctxt;
    start_info_t *start_info;
    shared_info_t *shinfo = NULL;
    xen_pfn_t *p2m_frame_list_list = NULL;
    xen_pfn_t *p2m_frame_list = NULL;
    xen_pfn_t *p2m = NULL;
#endif

    if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
    {
        PERROR("Could not get domain info");
        return rc;
    }

    /*
     * (x86 only) Rewrite store_mfn and console_mfn back to MFN (from PFN).
     */
#if defined(__i386__) || defined(__x86_64__)
    if ( info.hvm )
    {
        ERROR("Cannot resume uncooperative HVM guests");
        return rc;
    }

    if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) != 0 )
    {
        PERROR("Could not get domain width");
        return rc;
    }
    if ( dinfo->guest_width != sizeof(long) )
    {
        ERROR("Cannot resume uncooperative cross-address-size guests");
        return rc;
    }

    /* Map the shared info frame */
    shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE,
                                  PROT_READ, info.shared_info_frame);
    if ( shinfo == NULL )
    {
        ERROR("Couldn't map shared info");
        goto out;
    }

    dinfo->p2m_size = shinfo->arch.max_pfn;

    p2m_frame_list_list =
        xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ,
                             shinfo->arch.pfn_to_mfn_frame_list_list);
    if ( p2m_frame_list_list == NULL )
    {
        ERROR("Couldn't map p2m_frame_list_list");
        goto out;
    }

    p2m_frame_list = xc_map_foreign_pages(xch, domid, PROT_READ,
                                          p2m_frame_list_list,
                                          P2M_FLL_ENTRIES);
    if ( p2m_frame_list == NULL )
    {
        ERROR("Couldn't map p2m_frame_list");
        goto out;
    }

    /* Map all the frames of the pfn->mfn table. For migrate to succeed,
       the guest must not change which frames are used for this purpose.
       (its not clear why it would want to change them, and we'll be OK
       from a safety POV anyhow. */
    p2m = xc_map_foreign_pages(xch, domid, PROT_READ,
                               p2m_frame_list,
                               P2M_FL_ENTRIES);
    if ( p2m == NULL )
    {
        ERROR("Couldn't map p2m table");
        goto out;
    }

    if ( xc_vcpu_getcontext(xch, domid, 0, &ctxt) )
    {
        ERROR("Could not get vcpu context");
        goto out;
    }

    mfn = GET_FIELD(&ctxt, user_regs.edx, dinfo->guest_width);

    start_info = xc_map_foreign_range(xch, domid, PAGE_SIZE,
                                      PROT_READ | PROT_WRITE, mfn);
    if ( start_info == NULL )
    {
        ERROR("Couldn't map start_info");
        goto out;
    }

    start_info->store_mfn        = p2m[start_info->store_mfn];
    start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];

    munmap(start_info, PAGE_SIZE);
#endif /* defined(__i386__) || defined(__x86_64__) */

    /* Reset all secondary CPU states. */
    for ( i = 1; i <= info.max_vcpu_id; i++ )
        if ( xc_vcpu_setcontext(xch, domid, i, NULL) != 0 )
        {
            ERROR("Couldn't reset vcpu state");
            goto out;
        }

    /* Ready to resume domain execution now. */
    domctl.cmd = XEN_DOMCTL_resumedomain;
    domctl.domain = domid;
    rc = do_domctl(xch, &domctl);

out:
#if defined(__i386__) || defined(__x86_64__)
    if (p2m)
        munmap(p2m, P2M_FL_ENTRIES*PAGE_SIZE);
    if (p2m_frame_list)
        munmap(p2m_frame_list, P2M_FLL_ENTRIES*PAGE_SIZE);
    if (p2m_frame_list_list)
        munmap(p2m_frame_list_list, PAGE_SIZE);
    if (shinfo)
        munmap(shinfo, PAGE_SIZE);
#endif

    return rc;
}

/*
 * Resume execution of a domain after suspend shutdown.
 * This can happen in one of two ways:
 *  1. Resume with special return code.
 *  2. Reset guest environment so it believes it is resumed in a new
 *     domain context.
 * (2) should be used only for guests which cannot handle the special
 * new return code. (1) is always safe (but slower).
 */
int xc_domain_resume(xc_interface *xch, uint32_t domid, int fast)
{
    return (fast
            ? xc_domain_resume_cooperative(xch, domid)
            : xc_domain_resume_any(xch, domid));
}