예제 #1
0
static int ia64_setup_memmap(struct xc_dom_image *dom)
{
    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
    unsigned long memmap_info_num_pages;
    unsigned long memmap_info_pfn;
    xen_ia64_memmap_info_t* memmap_info;
    unsigned int num_mds;
    efi_memory_desc_t *md;

    char* start_info;
    struct xen_ia64_boot_param* bp;

    /* setup memmap page */
    memmap_info_num_pages = 1;
    memmap_info_pfn = dom->start_info_pfn - 1;
    xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn " pages 0x%lx\n",
                  __FUNCTION__, memmap_info_pfn, memmap_info_num_pages);
    memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
                                       page_size * memmap_info_num_pages,
                                       PROT_READ | PROT_WRITE,
                                       memmap_info_pfn);
    if (NULL == memmap_info)
        return -1;
    /* [0, total_pages) */
    memmap_info->efi_memdesc_size = sizeof(md[0]);
    memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
    num_mds = 0;
    md = (efi_memory_desc_t*)&memmap_info->memdesc;
    md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
    md[num_mds].pad = 0;
    md[num_mds].phys_addr = 0;
    md[num_mds].virt_addr = 0;
    md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
    md[num_mds].attribute = EFI_MEMORY_WB;
    num_mds++;
    memmap_info->efi_memmap_size = num_mds * sizeof(md[0]);
    munmap(memmap_info, page_size * memmap_info_num_pages);
    assert(num_mds <=
           (page_size * memmap_info_num_pages -
            offsetof(typeof(*memmap_info), memdesc))/sizeof(*md));

    /*
     * kludge: we need to pass memmap_info page's pfn and other magic pages
     * somehow.
     * we use xen_ia64_boot_param::efi_memmap::{efi_memmap, efi_memmap_size}
     * for this purpose
     */
    start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
				      page_size,
				      PROT_READ | PROT_WRITE,
				      dom->start_info_pfn);
    if (NULL == start_info)
        return -1;
    bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t));
    memset(bp, 0, sizeof(*bp));
    XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) = memmap_info_num_pages;
    XEN_IA64_MEMMAP_INFO_PFN(bp) = memmap_info_pfn;
    munmap(start_info, page_size);
    return 0;
}
예제 #2
0
//TODO assuming length == page size is safe for now, but isn't the most clean approach
void *
xen_get_memory_pfn(
    vmi_instance_t vmi,
    addr_t pfn,
    int prot)
{
    void *memory = xc_map_foreign_range(xen_get_xchandle(vmi),
                                        xen_get_domainid(vmi),
                                        XC_PAGE_SIZE,
                                        prot,
                                        (unsigned long) pfn);

    if (MAP_FAILED == memory || NULL == memory) {
        dbprint("--xen_get_memory_pfn failed on pfn=0x%"PRIx64"\n", pfn);
        return NULL;
    }

#ifdef VMI_DEBUG
    // copy memory to local address space - handy for examination
    uint8_t buf[XC_PAGE_SIZE];

    memcpy(buf, memory, XC_PAGE_SIZE);
#endif // VMI_DEBUG

    return memory;
}
예제 #3
0
파일: xen_console.c 프로젝트: 0bliv10n/s2e
static int con_initialise(struct XenDevice *xendev)
{
    struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
    int limit;

    if (xenstore_read_int(con->console, "ring-ref", &con->ring_ref) == -1)
	return -1;
    if (xenstore_read_int(con->console, "port", &con->xendev.remote_port) == -1)
	return -1;
    if (xenstore_read_int(con->console, "limit", &limit) == 0)
	con->buffer.max_capacity = limit;

    con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
				      XC_PAGE_SIZE,
				      PROT_READ|PROT_WRITE,
				      con->ring_ref);
    if (!con->sring)
	return -1;

    xen_be_bind_evtchn(&con->xendev);
    if (con->chr)
        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
                              NULL, con);

    xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
		  con->ring_ref,
		  con->xendev.remote_port,
		  con->xendev.local_port,
		  con->buffer.max_capacity);
    return 0;
}
예제 #4
0
static int xenfb_bind(struct xenfb_device *dev)
{
	struct xenfb *xenfb = dev->xenfb;
	unsigned long mfn;
	evtchn_port_t evtchn;

	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
			    &mfn) < 0)
		return -1;
	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
			    &evtchn) < 0)
		return -1;

	dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
					       dev->otherend_id, evtchn);
	if (dev->port == -1)
		return -1;

	dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
			XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
	if (dev->page == NULL)
		return -1;

	return 0;
}
예제 #5
0
파일: xc_tbuf.c 프로젝트: 0day-ci/xen
int xc_tbuf_get_size(xc_interface *xch, unsigned long *size)
{
    struct t_info *t_info;
    int rc;
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;

    rc = xc_sysctl(xch, &sysctl);
    if ( rc != 0 )
        return rc;

    t_info = xc_map_foreign_range(xch, DOMID_XEN,
                    sysctl.u.tbuf_op.size, PROT_READ | PROT_WRITE,
                    sysctl.u.tbuf_op.buffer_mfn);

    if ( t_info == NULL || t_info->tbuf_size == 0 )
        rc = -1;
    else
	*size = t_info->tbuf_size;

    xenforeignmemory_unmap(xch->fmem, t_info, sysctl.u.tbuf_op.size);

    return rc;
}
예제 #6
0
int xc_tbuf_get_size(int xc_handle, unsigned long *size)
{
    struct t_info *t_info;
    int rc;
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;

    rc = xc_sysctl(xc_handle, &sysctl);
    if ( rc != 0 )
        return rc;

    t_info = xc_map_foreign_range(xc_handle, DOMID_XEN,
                    sysctl.u.tbuf_op.size, PROT_READ | PROT_WRITE,
                    sysctl.u.tbuf_op.buffer_mfn);

    if ( t_info == NULL || t_info->tbuf_size == 0 )
        return -1;

    *size = t_info->tbuf_size;

    return 0;
}
예제 #7
0
/**
 * map_tbufs - memory map Xen trace buffers into user space
 * @tbufs_mfn: mfn of the trace buffers
 * @num:       number of trace buffers to map
 * @size:      size of each trace buffer
 *
 * Maps the Xen trace buffers them into process address space.
 */
struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
                        unsigned long size)
{
    int xc_handle;
    struct t_buf *tbufs_mapped;

    xc_handle = xc_interface_open();

    if ( xc_handle < 0 ) 
    {
        exit(EXIT_FAILURE);
    }

    tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN,
                                        size * num, PROT_READ | PROT_WRITE,
                                        tbufs_mfn);

    xc_interface_close(xc_handle);

    if ( tbufs_mapped == 0 ) 
    {
        PERROR("Failed to mmap trace buffers");
        exit(EXIT_FAILURE);
    }

    return tbufs_mapped;
}
예제 #8
0
파일: xc_dom_boot.c 프로젝트: Fantu/Xen
int xc_dom_gnttab_seed(xc_interface *xch, domid_t domid,
                       xen_pfn_t console_gmfn,
                       xen_pfn_t xenstore_gmfn,
                       domid_t console_domid,
                       domid_t xenstore_domid)
{

    xen_pfn_t gnttab_gmfn;
    grant_entry_v1_t *gnttab;

    gnttab_gmfn = xc_dom_gnttab_setup(xch, domid);
    if ( gnttab_gmfn == -1 )
        return -1;

    gnttab = xc_map_foreign_range(xch,
                                  domid,
                                  PAGE_SIZE,
                                  PROT_READ|PROT_WRITE,
                                  gnttab_gmfn);
    if ( gnttab == NULL )
    {
        xc_dom_panic(xch, XC_INTERNAL_ERROR,
                     "%s: failed to map domU grant table "
                     "[errno=%d]\n",
                     __FUNCTION__, errno);
        return -1;
    }

    if ( domid != console_domid  && console_gmfn != -1)
    {
        gnttab[GNTTAB_RESERVED_CONSOLE].flags = GTF_permit_access;
        gnttab[GNTTAB_RESERVED_CONSOLE].domid = console_domid;
        gnttab[GNTTAB_RESERVED_CONSOLE].frame = console_gmfn;
    }
    if ( domid != xenstore_domid && xenstore_gmfn != -1)
    {
        gnttab[GNTTAB_RESERVED_XENSTORE].flags = GTF_permit_access;
        gnttab[GNTTAB_RESERVED_XENSTORE].domid = xenstore_domid;
        gnttab[GNTTAB_RESERVED_XENSTORE].frame = xenstore_gmfn;
    }

    if ( munmap(gnttab, PAGE_SIZE) == -1 )
    {
        xc_dom_panic(xch, XC_INTERNAL_ERROR,
                     "%s: failed to unmap domU grant table "
                     "[errno=%d]\n",
                     __FUNCTION__, errno);
        return -1;
    }

    /* Guest shouldn't really touch its grant table until it has
     * enabled its caches. But lets be nice. */
    xc_domain_cacheflush(xch, domid, gnttab_gmfn, 1);

    return 0;
}
예제 #9
0
int xc_clear_domain_page(int xc_handle,
                         uint32_t domid,
                         unsigned long dst_pfn)
{
    void *vaddr = xc_map_foreign_range(
        xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
    if ( vaddr == NULL )
        return -1;
    memset(vaddr, 0, PAGE_SIZE);
    munmap(vaddr, PAGE_SIZE);
    return 0;
}
예제 #10
0
int xc_copy_to_domain_page(int xc_handle,
                           uint32_t domid,
                           unsigned long dst_pfn,
                           const char *src_page)
{
    void *vaddr = xc_map_foreign_range(
        xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
    if ( vaddr == NULL )
        return -1;
    memcpy(vaddr, src_page, PAGE_SIZE);
    munmap(vaddr, PAGE_SIZE);
    return 0;
}
예제 #11
0
int xc_clear_domain_page(xc_interface *xch,
                         uint32_t domid,
                         unsigned long dst_pfn)
{
    void *vaddr = xc_map_foreign_range(
        xch, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
    if ( vaddr == NULL )
        return -1;
    memset(vaddr, 0, PAGE_SIZE);
    munmap(vaddr, PAGE_SIZE);
    xc_domain_cacheflush(xch, domid, dst_pfn, 1);
    return 0;
}
예제 #12
0
파일: xc_private.c 프로젝트: tklengyel/xen
int xc_copy_to_domain_page(xc_interface *xch,
                           uint32_t domid,
                           unsigned long dst_pfn,
                           const char *src_page)
{
    void *vaddr = xc_map_foreign_range(
        xch, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
    if ( vaddr == NULL )
        return -1;
    memcpy(vaddr, src_page, PAGE_SIZE);
    munmap(vaddr, PAGE_SIZE);
    xc_domain_cacheflush(xch, domid, dst_pfn, 1);
    return 0;
}
예제 #13
0
파일: xc_private.c 프로젝트: tklengyel/xen
int xc_clear_domain_pages(xc_interface *xch,
                          uint32_t domid,
                          unsigned long dst_pfn,
                          int num)
{
    size_t size = num * PAGE_SIZE;
    void *vaddr = xc_map_foreign_range(
        xch, domid, size, PROT_WRITE, dst_pfn);
    if ( vaddr == NULL )
        return -1;
    memset(vaddr, 0, size);
    munmap(vaddr, size);
    xc_domain_cacheflush(xch, domid, dst_pfn, num);
    return 0;
}
static int hvm_build_set_params(int store_evtchn, unsigned long *store_mfn,
                                int console_evtchn, unsigned long *console_mfn,
                                struct flags f)
{
    struct hvm_info_table *va_hvm;
    uint8_t *va_map, sum;
    uint32_t i;
    int rc = 0;

    va_map = xc_map_foreign_range(xch, domid,
                                  XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
                                  HVM_INFO_PFN);
    if (va_map == NULL)
        return -1;

    va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
    va_hvm->apic_mode = f.apic;
    va_hvm->nr_vcpus = f.vcpus;
    memset(va_hvm->vcpu_online, 0, sizeof(va_hvm->vcpu_online));
    for (i = 0; i < f.vcpus_current; i++)
        va_hvm->vcpu_online[i/8] |= 1 << (i % 8);
    va_hvm->checksum = 0;
    for (i = 0, sum = 0; i < va_hvm->length; i++)
        sum += ((uint8_t *) va_hvm)[i];
    va_hvm->checksum = -sum;
    munmap(va_map, XC_PAGE_SIZE);

    xc_get_hvm_param(xch, domid, HVM_PARAM_STORE_PFN, store_mfn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, f.pae);

    if (f.viridian)
        hvm_set_viridian_features(&f);

    xc_set_hvm_param(xch, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_HPET_ENABLED, f.hpet);
    xc_set_hvm_param(xch, domid, HVM_PARAM_NESTEDHVM, f.nested_hvm);
    xc_get_hvm_param(xch, domid, HVM_PARAM_CONSOLE_PFN, console_mfn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_TRIPLE_FAULT_REASON, SHUTDOWN_crash);

#ifdef HAVE_CORES_PER_SOCKET
    if ( f.cores_per_socket > 0 )
        rc = xc_domain_set_cores_per_socket(xch, domid, f.cores_per_socket);
#endif
    
    return rc;
}
예제 #15
0
static int hvm_build_set_params(xc_interface *xch, int domid,
                                int store_evtchn, unsigned long *store_mfn,
                                int console_evtchn, unsigned long *console_mfn,
                                struct flags f)
{
    struct hvm_info_table *va_hvm;
    uint8_t *va_map, sum;
    int i;

    va_map = xc_map_foreign_range(xch, domid,
                                  XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
                                  HVM_INFO_PFN);
    if (va_map == NULL)
        return -1;

    va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
    va_hvm->acpi_enabled = f.acpi;
    va_hvm->apic_mode = f.apic;
    va_hvm->nr_vcpus = f.vcpus;
    memset(va_hvm->vcpu_online, 0, sizeof(va_hvm->vcpu_online));
    for (i = 0; i < f.vcpus_current; i++)
        va_hvm->vcpu_online[i/8] |= 1 << (i % 8);
#if defined(HVM_INFO_TABLE_HAS_S4_ENABLED)
    va_hvm->s4_enabled = f.acpi_s4;
#endif
#if defined(HVM_INFO_TABLE_HAS_S3_ENABLED)
    va_hvm->s3_enabled = f.acpi_s3;
#endif
    va_hvm->checksum = 0;
    for (i = 0, sum = 0; i < va_hvm->length; i++)
        sum += ((uint8_t *) va_hvm)[i];
    va_hvm->checksum = -sum;
    munmap(va_map, XC_PAGE_SIZE);

    xc_get_hvm_param(xch, domid, HVM_PARAM_STORE_PFN, store_mfn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, f.pae);
#ifdef HVM_PARAM_VIRIDIAN
    xc_set_hvm_param(xch, domid, HVM_PARAM_VIRIDIAN, f.viridian);
#endif
    xc_set_hvm_param(xch, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
#ifndef XEN_UNSTABLE
    xc_set_hvm_param(xch, domid, HVM_PARAM_NX_ENABLED, f.nx);
    xc_get_hvm_param(xch, domid, HVM_PARAM_CONSOLE_PFN, console_mfn);
    xc_set_hvm_param(xch, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
#endif
    return 0;
}
예제 #16
0
int arch_setup_bootlate(struct xc_dom_image *dom)
{
    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
    shared_info_t *shared_info;

    /* setup shared_info page */
    xc_dom_printf("%s: shared_info: mfn 0x%" PRIpfn "\n",
                  __FUNCTION__, dom->shared_info_mfn);
    shared_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
                                       page_size,
                                       PROT_READ | PROT_WRITE,
                                       dom->shared_info_mfn);
    if ( shared_info == NULL )
        return -1;
    dom->arch_hooks->shared_info(dom, shared_info);
    munmap(shared_info, page_size);
    return 0;
}
예제 #17
0
static int
read_page(int xc_handle, int io_fd, uint32_t dom, unsigned long pfn)
{
    void *mem;

    mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                               PROT_READ|PROT_WRITE, pfn);
    if (mem == NULL) {
        ERROR("cannot map page");
        return -1;
    }
    if (read_exact(io_fd, mem, PAGE_SIZE)) {
        ERROR("Error when reading from state file (5)");
        munmap(mem, PAGE_SIZE);
        return -1;
    }
    munmap(mem, PAGE_SIZE);
    return 0;
}
예제 #18
0
static int
xc_ia64_pv_recv_shared_info(int xc_handle, int io_fd, int32_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)
{
    unsigned long gmfn;

    /* A temporary mapping of the guest's start_info page. */
    start_info_t *start_info;
    
    /* Read shared info.  */
    if (xc_ia64_recv_shared_info(xc_handle, io_fd, dom,
                                 shared_info_frame, &gmfn))
        return -1;

    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
    if (populate_page_if_necessary(xc_handle, dom, gmfn, p2m_table)) {
        ERROR("cannot populate page 0x%lx", gmfn);
        return -1;
    }
    start_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                      PROT_READ | PROT_WRITE, gmfn);
    if (start_info == NULL) {
        ERROR("cannot map start_info page");
        return -1;
    }
    start_info->nr_pages = p2m_size;
    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
    start_info->flags = 0;
    *store_mfn = start_info->store_mfn;
    start_info->store_evtchn = store_evtchn;
    *console_mfn = start_info->console.domU.mfn;
    start_info->console.domU.evtchn = console_evtchn;
    munmap(start_info, PAGE_SIZE);

    return 0;
}
예제 #19
0
static int common_bind(struct common *c)
{
    int mfn;

    if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
	return -1;
    if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
	return -1;

    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
				   XC_PAGE_SIZE,
				   PROT_READ | PROT_WRITE, mfn);
    if (c->page == NULL)
	return -1;

    xen_be_bind_evtchn(&c->xendev);
    xen_be_printf(&c->xendev, 1, "ring mfn %d, remote-port %d, local-port %d\n",
		  mfn, c->xendev.remote_port, c->xendev.local_port);

    return 0;
}
예제 #20
0
/* Read shared info.  */
static int
xc_ia64_recv_shared_info(int xc_handle, int io_fd, uint32_t dom,
                         unsigned long shared_info_frame,
                         unsigned long *start_info_pfn)
{
    unsigned int i;

    /* The new domain's shared-info frame. */
    shared_info_t *shared_info;
    
    /* Read shared info.  */
    shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ|PROT_WRITE,
                                       shared_info_frame);
    if (shared_info == NULL) {
        ERROR("cannot map page");
        return -1;
    }

    if (read_exact(io_fd, shared_info, PAGE_SIZE)) {
        ERROR("Error when reading shared_info page");
        munmap(shared_info, PAGE_SIZE);
        return -1;
    }

    /* clear any pending events and the selector */
    memset(&(shared_info->evtchn_pending[0]), 0,
           sizeof (shared_info->evtchn_pending));
    for (i = 0; i < MAX_VIRT_CPUS; i++)
        shared_info->vcpu_info[i].evtchn_pending_sel = 0;

    if (start_info_pfn != NULL)
        *start_info_pfn = shared_info->arch.start_info_pfn;

    munmap (shared_info, PAGE_SIZE);

    return 0;
}
예제 #21
0
void *xa_map_page (xa_instance_t *instance, int prot, unsigned long frame_num)
{
    void *memory = NULL;

    if (XA_MODE_XEN == instance->mode){
#ifdef ENABLE_XEN
        memory = xc_map_foreign_range(
            instance->m.xen.xch,
            instance->m.xen.domain_id,
            1,
            prot,
            frame_num);
#endif /* ENABLE_XEN */
    }
    else if (XA_MODE_FILE == instance->mode){
        memory = xa_map_file_range(instance, prot, frame_num);
    }
    else{
        xa_dbprint("BUG: invalid mode\n");
    }

    return memory;
}
예제 #22
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));
}
예제 #23
0
/**
 * map_tbufs - memory map Xen trace buffers into user space
 * @tbufs_mfn: mfn of the trace buffers
 * @num:       number of trace buffers to map
 * @size:      size of each trace buffer
 *
 * Maps the Xen trace buffers them into process address space.
 */
static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
                                  unsigned long tinfo_size)
{
    int xc_handle;
    static struct t_struct tbufs = { 0 };
    int i;

    xc_handle = xc_interface_open();
    if ( xc_handle < 0 ) 
    {
        exit(EXIT_FAILURE);
    }

    /* Map t_info metadata structure */
    tbufs.t_info = xc_map_foreign_range(xc_handle, DOMID_XEN, tinfo_size,
                                        PROT_READ, tbufs_mfn);

    if ( tbufs.t_info == 0 ) 
    {
        PERROR("Failed to mmap trace buffers");
        exit(EXIT_FAILURE);
    }

    if ( tbufs.t_info->tbuf_size == 0 )
    {
        fprintf(stderr, "%s: tbuf_size 0!\n", __func__);
        exit(EXIT_FAILURE);
    }

    /* Map per-cpu buffers */
    tbufs.meta = (struct t_buf **)calloc(num, sizeof(struct t_buf *));
    tbufs.data = (unsigned char **)calloc(num, sizeof(unsigned char *));
    if ( tbufs.meta == NULL || tbufs.data == NULL )
    {
        PERROR( "Failed to allocate memory for buffer pointers\n");
        exit(EXIT_FAILURE);
    }

    for(i=0; i<num; i++)
    {
        
        const uint32_t *mfn_list = (const uint32_t *)tbufs.t_info
                                   + tbufs.t_info->mfn_offset[i];
        int j;
        xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];

        for ( j=0; j<tbufs.t_info->tbuf_size; j++)
            pfn_list[j] = (xen_pfn_t)mfn_list[j];

        tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
                                             PROT_READ | PROT_WRITE,
                                             pfn_list,
                                             tbufs.t_info->tbuf_size);
        if ( tbufs.meta[i] == NULL )
        {
            PERROR("Failed to map cpu buffer!");
            exit(EXIT_FAILURE);
        }
        tbufs.data[i] = (unsigned char *)(tbufs.meta[i]+1);
    }

    xc_interface_close(xc_handle);

    return &tbufs;
}