diff --git a/.hgignore b/.hgignore index e3bca07c23..e44cc82784 100644 --- a/.hgignore +++ b/.hgignore @@ -22,7 +22,7 @@ ^\.pc ^TAGS$ ^tags$ -^build.*$ +^build-.*$ ^dist/.*$ ^docs/.*\.aux$ ^docs/.*\.dvi$ diff --git a/README b/README index c382918db4..705cec5db3 100644 --- a/README +++ b/README @@ -199,3 +199,7 @@ Xend (the Xen daemon) has the following runtime dependencies: * For optional PAM support, PyPAM: URL: http://www.pangalactic.org/PyPAM/ Debian: python-pam + + * For optional XenAPI support in XM, PyXML: + URL: http://pyxml.sourceforge.net + YUM: PyXML diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index d2abc56fd4..11b8edbfe8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -622,14 +622,14 @@ static int network_open(struct net_device *dev) memset(&np->stats, 0, sizeof(np->stats)); - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (netfront_carrier_ok(np)) { network_alloc_rx_buffers(dev); np->rx.sring->rsp_event = np->rx.rsp_cons + 1; if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) netif_rx_schedule(dev); } - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); network_maybe_wake_tx(dev); @@ -1307,7 +1307,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) int pages_flipped = 0; int err; - spin_lock(&np->rx_lock); + spin_lock(&np->rx_lock); /* no need for spin_lock_bh() in ->poll() */ if (unlikely(!netfront_carrier_ok(np))) { spin_unlock(&np->rx_lock); @@ -1520,7 +1520,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) skb_queue_head_init(&free_list); - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); for (id = 0; id < NET_RX_RING_SIZE; id++) { if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) { @@ -1588,7 +1588,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) while ((skb = __skb_dequeue(&free_list)) != NULL) dev_kfree_skb(skb); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); } static int network_close(struct net_device *dev) @@ -1708,8 +1708,8 @@ static int network_connect(struct net_device *dev) IPRINTK("device %s has %sing receive path.\n", dev->name, np->copying_receiver ? "copy" : "flipp"); + spin_lock_bh(&np->rx_lock); spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); /* * Recovery procedure: @@ -1761,8 +1761,8 @@ static int network_connect(struct net_device *dev) network_tx_buf_gc(dev); network_alloc_rx_buffers(dev); - spin_unlock(&np->rx_lock); spin_unlock_irq(&np->tx_lock); + spin_unlock_bh(&np->rx_lock); return 0; } @@ -1818,7 +1818,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd, if (target > RX_MAX_TARGET) target = RX_MAX_TARGET; - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (target > np->rx_max_target) np->rx_max_target = target; np->rx_min_target = target; @@ -1827,7 +1827,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd, network_alloc_rx_buffers(netdev); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return len; } @@ -1861,7 +1861,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd, if (target > RX_MAX_TARGET) target = RX_MAX_TARGET; - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (target < np->rx_min_target) np->rx_min_target = target; np->rx_max_target = target; @@ -1870,7 +1870,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd, network_alloc_rx_buffers(netdev); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return len; } @@ -2033,11 +2033,11 @@ inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) static void netif_disconnect_backend(struct netfront_info *info) { /* Stop old i/f to prevent errors whilst we rebuild the state. */ + spin_lock_bh(&info->rx_lock); spin_lock_irq(&info->tx_lock); - spin_lock(&info->rx_lock); netfront_carrier_off(info); - spin_unlock(&info->rx_lock); spin_unlock_irq(&info->tx_lock); + spin_unlock_bh(&info->rx_lock); if (info->irq) unbind_from_irqhandler(info->irq, info->netdev); diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 1159776f4f..aaabed6d42 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -688,33 +688,22 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, ERROR("error zeroing magic pages"); goto out; } - - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, magic_pfns[0]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, magic_pfns[2]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn); - *store_mfn = magic_pfns[2]; - - /* Read vcpu contexts */ - for ( i = 0; i <= max_vcpu_id; i++ ) + + if ( (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_IOREQ_PFN, magic_pfns[0])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_PFN, magic_pfns[2])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_PAE_ENABLED, pae)) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_EVTCHN, store_evtchn)) ) { - if ( !(vcpumap & (1ULL << i)) ) - continue; - - if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) ) - { - ERROR("error read vcpu context.\n"); - goto out; - } - - if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) - { - ERROR("Could not set vcpu context, rc=%d", rc); - goto out; - } - rc = 1; + ERROR("error setting HVM params: %i", rc); + goto out; } + *store_mfn = magic_pfns[2]; /* Read HVM context */ if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) ) diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index f8b51c2713..ba7e005819 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -378,8 +378,7 @@ static int analysis_phase(int xc_handle, uint32_t domid, int p2m_size, static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, - int dom, xc_dominfo_t *info, - vcpu_guest_context_t *ctxt) + int dom, xc_dominfo_t *info) { int i = 0; @@ -397,10 +396,6 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, return -1; } - if ( xc_vcpu_getcontext(xc_handle, dom, 0, ctxt) ) - ERROR("Could not get vcpu context"); - - if ( info->dying ) { ERROR("domain is dying"); @@ -663,10 +658,11 @@ static xen_pfn_t *xc_map_m2p(int xc_handle, static xen_pfn_t *map_and_save_p2m_table(int xc_handle, int io_fd, uint32_t dom, - vcpu_guest_context_t *ctxt, unsigned long p2m_size, shared_info_t *live_shinfo) { + vcpu_guest_context_t ctxt; + /* Double and single indirect references to the live P2M table */ xen_pfn_t *live_p2m_frame_list_list = NULL; xen_pfn_t *live_p2m_frame_list = NULL; @@ -730,13 +726,19 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, } } + if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) + { + ERROR("Could not get vcpu context"); + goto out; + } + /* * Write an extended-info structure to inform the restore code that * a PAE guest understands extended CR3 (PDPTs above 4GB). Turns off * slow paths in the restore code. */ if ( (pt_levels == 3) && - (ctxt->vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) ) + (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) ) { unsigned long signature = ~0UL; uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8; @@ -746,7 +748,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) || !write_exact(io_fd, &chunk_sig, 4) || !write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) || - !write_exact(io_fd, ctxt, sizeof(*ctxt)) ) + !write_exact(io_fd, &ctxt, sizeof(ctxt)) ) { ERROR("write: extended info"); goto out; @@ -853,11 +855,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, return 1; } - if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) - { - ERROR("Could not get vcpu context"); - goto out; - } shared_info_frame = info.shared_info_frame; /* Map the shared info frame */ @@ -900,7 +897,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, else { /* This is a non-live suspend. Suspend the domain .*/ - if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) ) + if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) ) { ERROR("Domain appears not to have suspended"); goto out; @@ -999,7 +996,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Map the P2M table, and write the list of P2M frames */ live_p2m = map_and_save_p2m_table(xc_handle, io_fd, dom, - &ctxt, p2m_size, live_shinfo); + p2m_size, live_shinfo); if ( live_p2m == NULL ) { ERROR("Failed to map/save the p2m frame list"); @@ -1304,17 +1301,13 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("Start last iteration\n"); last_iter = 1; - if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, - &ctxt) ) + if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) ) { ERROR("Domain appears not to have suspended"); goto out; } - DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n", - info.shared_info_frame, - (unsigned long)ctxt.user_regs.eip, - (unsigned long)ctxt.user_regs.edx); + DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame); } if ( xc_shadow_control(xc_handle, dom, @@ -1410,27 +1403,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* Save vcpu contexts */ - - for ( i = 0; i <= info.max_vcpu_id; i++ ) - { - if ( !(vcpumap & (1ULL << i)) ) - continue; - - if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) ) - { - ERROR("HVM:Could not get vcpu context"); - goto out; - } - - DPRINTF("write vcpu %d context.\n", i); - if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) - { - ERROR("write vcpu context failed!\n"); - goto out; - } - } - /* Get HVM context from Xen and save it too */ if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, hvm_buf_size)) == -1 ) @@ -1494,6 +1466,12 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } } + if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) + { + ERROR("Could not get vcpu context"); + goto out; + } + /* Canonicalise the suspend-record frame number. */ if ( !translate_mfn_to_pfn(&ctxt.user_regs.edx) ) { diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index e3e0658842..37bc587477 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -198,18 +198,6 @@ __attribute__((weak)) return -1; } -__attribute__((weak)) int xc_get_hvm_param( - int handle, domid_t dom, int param, unsigned long *value) -{ - return -ENOSYS; -} - -__attribute__((weak)) int xc_set_hvm_param( - int handle, domid_t dom, int param, unsigned long value) -{ - return -ENOSYS; -} - /* * Local variables: * mode: C diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 0e3cd4701d..76eb313c30 100644 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -61,13 +61,6 @@ def get_active_partition(file): if struct.unpack(" 0: @@ -494,7 +510,7 @@ class sxp2xml: # Make version tag version = document.createElement("version") - version.appendChild(document.createTextNode("1.0")) + version.appendChild(document.createTextNode("0")) vm.appendChild(version) # Make pv or hvm tag diff --git a/xen/arch/powerpc/0opt.c b/xen/arch/powerpc/0opt.c index 6d85e63c9e..e029ed11eb 100644 --- a/xen/arch/powerpc/0opt.c +++ b/xen/arch/powerpc/0opt.c @@ -21,6 +21,12 @@ #include #include +extern void __xchg_called_with_bad_pointer(void); +void __xchg_called_with_bad_pointer(void) +{ + BUG(); +} + extern void __cmpxchg_called_with_bad_pointer(void); void __cmpxchg_called_with_bad_pointer(void) { diff --git a/xen/arch/powerpc/domain_build.c b/xen/arch/powerpc/domain_build.c index 92e3c20217..d9ff09617c 100644 --- a/xen/arch/powerpc/domain_build.c +++ b/xen/arch/powerpc/domain_build.c @@ -229,7 +229,7 @@ int construct_dom0(struct domain *d, /* Load the dom0 kernel. */ elf.dest = (void *)dst; elf_load_binary(&elf); - v->arch.ctxt.pc = dst - rma; + v->arch.ctxt.pc = dst - rma + (parms.virt_entry - parms.virt_kstart); dst = ALIGN_UP(dst + parms.virt_kend, PAGE_SIZE); /* Load the initrd. */ diff --git a/xen/arch/powerpc/ofd_fixup.c b/xen/arch/powerpc/ofd_fixup.c index 453ce4be17..2d2ff11244 100644 --- a/xen/arch/powerpc/ofd_fixup.c +++ b/xen/arch/powerpc/ofd_fixup.c @@ -264,7 +264,7 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline) ofdn_t n; ofdn_t p; static const char path[] = "/chosen"; - char bootargs[256]; + char bootargs[256] = { 0, }; int bsz; int sz; int rm; @@ -276,7 +276,8 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline) &path[1], sizeof (path) - 1); } - strlcpy(bootargs, cmdline, sizeof(bootargs)); + if (cmdline) + strlcpy(bootargs, cmdline, sizeof(bootargs)); bsz = strlen(bootargs) + 1; rm = sizeof (bootargs) - bsz; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index af43de2328..612fec0876 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1540,8 +1540,10 @@ void domain_relinquish_resources(struct domain *d) relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table); relinquish_memory(d, &d->page_list, PGT_l2_page_table); - /* Free page used by xen oprofile buffer */ + /* Free page used by xen oprofile buffer. */ free_xenoprof_pages(d); + + hvm_domain_relinquish_resources(d); } void arch_dump_domain_info(struct domain *d) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 5cb283bf2e..d8ef1ae258 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -101,7 +101,7 @@ void hvm_set_guest_time(struct vcpu *v, u64 gtime) u64 hvm_get_guest_time(struct vcpu *v) { - u64 host_tsc; + u64 host_tsc; rdtscll(host_tsc); return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset; @@ -125,7 +125,7 @@ void hvm_do_resume(struct vcpu *v) pt_thaw_time(v); /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */ - p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + p = &get_ioreq(v)->vp_ioreq; while ( p->state != STATE_IOREQ_NONE ) { switch ( p->state ) @@ -146,6 +146,73 @@ void hvm_do_resume(struct vcpu *v) } } +static void hvm_init_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp) +{ + memset(iorp, 0, sizeof(*iorp)); + spin_lock_init(&iorp->lock); + domain_pause(d); +} + +static void hvm_destroy_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp) +{ + spin_lock(&iorp->lock); + + ASSERT(d->is_dying); + + if ( iorp->va != NULL ) + { + unmap_domain_page_global(iorp->va); + put_page_and_type(iorp->page); + iorp->va = NULL; + } + + spin_unlock(&iorp->lock); +} + +static int hvm_set_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn) +{ + struct page_info *page; + unsigned long mfn; + void *va; + + mfn = gmfn_to_mfn(d, gmfn); + if ( !mfn_valid(mfn) ) + return -EINVAL; + + page = mfn_to_page(mfn); + if ( !get_page_and_type(page, d, PGT_writable_page) ) + return -EINVAL; + + va = map_domain_page_global(mfn); + if ( va == NULL ) + { + put_page_and_type(page); + return -ENOMEM; + } + + spin_lock(&iorp->lock); + + if ( (iorp->va != NULL) || d->is_dying ) + { + spin_unlock(&iorp->lock); + unmap_domain_page_global(va); + put_page_and_type(mfn_to_page(mfn)); + return -EINVAL; + } + + iorp->va = va; + iorp->page = page; + + spin_unlock(&iorp->lock); + + domain_unpause(d); + + return 0; +} + int hvm_domain_initialise(struct domain *d) { int rc; @@ -158,10 +225,8 @@ int hvm_domain_initialise(struct domain *d) } spin_lock_init(&d->arch.hvm_domain.pbuf_lock); - spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); spin_lock_init(&d->arch.hvm_domain.irq_lock); - /* paging support will be determined inside paging.c */ rc = paging_enable(d, PG_refcounts|PG_translate|PG_external); if ( rc != 0 ) return rc; @@ -169,28 +234,31 @@ int hvm_domain_initialise(struct domain *d) vpic_init(d); vioapic_init(d); + hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq); + hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq); + return 0; } +void hvm_domain_relinquish_resources(struct domain *d) +{ + hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.ioreq); + hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq); +} + void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); pmtimer_deinit(d); hpet_deinit(d); - - if ( d->arch.hvm_domain.shared_page_va ) - unmap_domain_page_global( - (void *)d->arch.hvm_domain.shared_page_va); - - if ( d->arch.hvm_domain.buffered_io_va ) - unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va); } static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { struct vcpu *v; struct hvm_hw_cpu ctxt; + struct vcpu_guest_context *vc; for_each_vcpu(d, v) { @@ -199,7 +267,40 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) if ( test_bit(_VPF_down, &v->pause_flags) ) continue; + /* Architecture-specific vmcs/vmcb bits */ hvm_funcs.save_cpu_ctxt(v, &ctxt); + + /* Other vcpu register state */ + vc = &v->arch.guest_context; + if ( vc->flags & VGCF_i387_valid ) + memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs)); + else + memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs)); + ctxt.rax = vc->user_regs.eax; + ctxt.rbx = vc->user_regs.ebx; + ctxt.rcx = vc->user_regs.ecx; + ctxt.rdx = vc->user_regs.edx; + ctxt.rbp = vc->user_regs.ebp; + ctxt.rsi = vc->user_regs.esi; + ctxt.rdi = vc->user_regs.edi; + /* %rsp handled by arch-specific call above */ +#ifdef __x86_64__ + ctxt.r8 = vc->user_regs.r8; + ctxt.r9 = vc->user_regs.r9; + ctxt.r10 = vc->user_regs.r10; + ctxt.r11 = vc->user_regs.r11; + ctxt.r12 = vc->user_regs.r12; + ctxt.r13 = vc->user_regs.r13; + ctxt.r14 = vc->user_regs.r14; + ctxt.r15 = vc->user_regs.r15; +#endif + ctxt.dr0 = vc->debugreg[0]; + ctxt.dr1 = vc->debugreg[1]; + ctxt.dr2 = vc->debugreg[2]; + ctxt.dr3 = vc->debugreg[3]; + ctxt.dr6 = vc->debugreg[6]; + ctxt.dr7 = vc->debugreg[7]; + if ( hvm_save_entry(CPU, v->vcpu_id, h, &ctxt) != 0 ) return 1; } @@ -208,9 +309,10 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { - int vcpuid; + int vcpuid, rc; struct vcpu *v; struct hvm_hw_cpu ctxt; + struct vcpu_guest_context *vc; /* Which vcpu is this? */ vcpuid = hvm_load_instance(h); @@ -219,13 +321,52 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid); return -EINVAL; } + vc = &v->arch.guest_context; + + /* Need to init this vcpu before loading its contents */ + LOCK_BIGLOCK(d); + if ( !v->is_initialised ) + if ( (rc = boot_vcpu(d, vcpuid, vc)) != 0 ) + return rc; + UNLOCK_BIGLOCK(d); if ( hvm_load_entry(CPU, h, &ctxt) != 0 ) return -EINVAL; + /* Architecture-specific vmcs/vmcb bits */ if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 ) return -EINVAL; + /* Other vcpu register state */ + memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs)); + vc->user_regs.eax = ctxt.rax; + vc->user_regs.ebx = ctxt.rbx; + vc->user_regs.ecx = ctxt.rcx; + vc->user_regs.edx = ctxt.rdx; + vc->user_regs.ebp = ctxt.rbp; + vc->user_regs.esi = ctxt.rsi; + vc->user_regs.edi = ctxt.rdi; + vc->user_regs.esp = ctxt.rsp; +#ifdef __x86_64__ + vc->user_regs.r8 = ctxt.r8; + vc->user_regs.r9 = ctxt.r9; + vc->user_regs.r10 = ctxt.r10; + vc->user_regs.r11 = ctxt.r11; + vc->user_regs.r12 = ctxt.r12; + vc->user_regs.r13 = ctxt.r13; + vc->user_regs.r14 = ctxt.r14; + vc->user_regs.r15 = ctxt.r15; +#endif + vc->debugreg[0] = ctxt.dr0; + vc->debugreg[1] = ctxt.dr1; + vc->debugreg[2] = ctxt.dr2; + vc->debugreg[3] = ctxt.dr3; + vc->debugreg[6] = ctxt.dr6; + vc->debugreg[7] = ctxt.dr7; + + vc->flags = VGCF_i387_valid | VGCF_online; + v->fpu_initialised = 1; + /* Auxiliary processors should be woken immediately. */ if ( test_and_clear_bit(_VPF_down, &v->pause_flags) ) vcpu_wake(v); @@ -250,10 +391,20 @@ int hvm_vcpu_initialise(struct vcpu *v) } /* Create ioreq event channel. */ - v->arch.hvm_vcpu.xen_port = alloc_unbound_xen_event_channel(v, 0); - if ( get_sp(v->domain) && get_vio(v->domain, v->vcpu_id) ) - get_vio(v->domain, v->vcpu_id)->vp_eport = - v->arch.hvm_vcpu.xen_port; + rc = alloc_unbound_xen_event_channel(v, 0); + if ( rc < 0 ) + { + hvm_funcs.vcpu_destroy(v); + vlapic_destroy(v); + return rc; + } + + /* Register ioreq event channel. */ + v->arch.hvm_vcpu.xen_port = rc; + spin_lock(&v->domain->arch.hvm_domain.ioreq.lock); + if ( v->domain->arch.hvm_domain.ioreq.va != NULL ) + get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port; + spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock); INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list); @@ -334,7 +485,7 @@ void hvm_send_assist_req(struct vcpu *v) if ( unlikely(!vcpu_start_shutdown_deferral(v)) ) return; /* implicitly bins the i/o operation */ - p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + p = &get_ioreq(v)->vp_ioreq; if ( unlikely(p->state != STATE_IOREQ_NONE) ) { /* This indicates a bug in the device model. Crash the domain. */ @@ -852,10 +1003,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) case HVMOP_get_param: { struct xen_hvm_param a; + struct hvm_ioreq_page *iorp; struct domain *d; struct vcpu *v; - unsigned long mfn; - void *p; if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; @@ -882,30 +1032,18 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) switch ( a.index ) { case HVM_PARAM_IOREQ_PFN: - if ( d->arch.hvm_domain.shared_page_va ) - goto param_fail; - mfn = gmfn_to_mfn(d, a.value); - if ( mfn == INVALID_MFN ) - goto param_fail; - p = map_domain_page_global(mfn); - if ( p == NULL ) - goto param_fail; - d->arch.hvm_domain.shared_page_va = (unsigned long)p; - /* Initialise evtchn port info if VCPUs already created. */ - for_each_vcpu ( d, v ) - get_vio(d, v->vcpu_id)->vp_eport = - v->arch.hvm_vcpu.xen_port; + iorp = &d->arch.hvm_domain.ioreq; + rc = hvm_set_ioreq_page(d, iorp, a.value); + spin_lock(&iorp->lock); + if ( (rc == 0) && (iorp->va != NULL) ) + /* Initialise evtchn port info if VCPUs already created. */ + for_each_vcpu ( d, v ) + get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port; + spin_unlock(&iorp->lock); break; - case HVM_PARAM_BUFIOREQ_PFN: - if ( d->arch.hvm_domain.buffered_io_va ) - goto param_fail; - mfn = gmfn_to_mfn(d, a.value); - if ( mfn == INVALID_MFN ) - goto param_fail; - p = map_domain_page_global(mfn); - if ( p == NULL ) - goto param_fail; - d->arch.hvm_domain.buffered_io_va = (unsigned long)p; + case HVM_PARAM_BUFIOREQ_PFN: + iorp = &d->arch.hvm_domain.buf_ioreq; + rc = hvm_set_ioreq_page(d, iorp, a.value); break; case HVM_PARAM_CALLBACK_IRQ: hvm_set_callback_via(d, a.value); diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index fb8497a996..91749b676b 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -158,34 +158,26 @@ static inline void hvm_mmio_access(struct vcpu *v, int hvm_buffered_io_send(ioreq_t *p) { struct vcpu *v = current; - spinlock_t *buffered_io_lock; - buffered_iopage_t *buffered_iopage = - (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va); - unsigned long tmp_write_pointer = 0; + struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq; + buffered_iopage_t *pg = iorp->va; - buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock; - spin_lock(buffered_io_lock); + spin_lock(&iorp->lock); - if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer == - (unsigned int)IOREQ_BUFFER_SLOT_NUM ) { - /* the queue is full. - * send the iopacket through the normal path. - * NOTE: The arithimetic operation could handle the situation for - * write_pointer overflow. - */ - spin_unlock(buffered_io_lock); + if ( (pg->write_pointer - pg->read_pointer) == IOREQ_BUFFER_SLOT_NUM ) + { + /* The queue is full: send the iopacket through the normal path. */ + spin_unlock(&iorp->lock); return 0; } - tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM; + memcpy(&pg->ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM], + p, sizeof(ioreq_t)); - memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t)); - - /*make the ioreq_t visible before write_pointer*/ + /* Make the ioreq_t visible /before/ write_pointer. */ wmb(); - buffered_iopage->write_pointer++; + pg->write_pointer++; - spin_unlock(buffered_io_lock); + spin_unlock(&iorp->lock); return 1; } diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 03820f0ebd..f0f8ea8ecb 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -832,7 +832,7 @@ void hvm_io_assist(void) io_opp = &v->arch.hvm_vcpu.io_op; regs = &io_opp->io_context; - vio = get_vio(d, v->vcpu_id); + vio = get_ioreq(v); p = &vio->vp_ioreq; if ( p->state != STATE_IORESP_READY ) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index d333a92ace..8bb3e3439b 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -221,7 +221,6 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst inst++; //skip ModR/M byte if ( ad_size != WORD && mod != 3 && rm == 4 ) { - rm = *inst & 7; inst++; //skip SIB byte } @@ -257,6 +256,33 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst return val; } +/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require + * the src immediate operand be sign-extented befere the op is executed. Here + * we always sign-extend the operand to a "unsigned long" variable. + * + * Note: to simplify the logic here, the sign-extension here may be performed + * redundantly against some instructions, like "MOV $imm16, r/m16" -- however + * this is harmless, since we always remember the operand's size. + */ +static inline unsigned long get_immediate_sign_ext(int ad_size, + const unsigned char *inst, + int op_size) +{ + unsigned long result = get_immediate(ad_size, inst, op_size); + + if ( op_size == QUAD ) + op_size = LONG; + + ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG ); + + if ( result & (1UL << ((8*op_size) - 1)) ) + { + unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size)); + result = ~mask | (result & mask); + } + return result; +} + static inline int get_index(const unsigned char *inst, unsigned char rex) { int mod, reg, rm; @@ -394,7 +420,9 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, case 8: if ( *op_size == 0 ) *op_size = rex & 0x8 ? QUAD : LONG; - if ( *ad_size == 0 ) + if ( *ad_size == WORD ) + *ad_size = LONG; + else if ( *ad_size == 0 ) *ad_size = QUAD; break; #endif @@ -520,10 +548,10 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, /* opcode 0x83 always has a single byte operand */ if ( opcode[0] == 0x83 ) mmio_op->immediate = - (signed char)get_immediate(*ad_size, opcode + 1, BYTE); + get_immediate_sign_ext(*ad_size, opcode + 1, BYTE); else mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); @@ -677,7 +705,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE); mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY); return DECODE_success; @@ -699,7 +727,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); return DECODE_success; @@ -838,7 +866,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size, port, count, size, value, dir, value_is_ptr); } - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if ( vio == NULL ) { printk("bad shared page: %lx\n", (unsigned long) vio); domain_crash_synchronous(); @@ -887,7 +915,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa, type, gpa, count, size, value, dir, value_is_ptr); } - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if (vio == NULL) { printk("bad shared page\n"); domain_crash_synchronous(); @@ -948,7 +976,7 @@ void send_invalidate_req(void) vcpu_iodata_t *vio; ioreq_t *p; - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if ( vio == NULL ) { printk("bad shared page: %lx\n", (unsigned long) vio); diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index ae0b42ae66..5f06d09c08 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -233,7 +233,7 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - c->eip = vmcb->rip; + c->rip = vmcb->rip; #ifdef HVM_DEBUG_SUSPEND printk("%s: eip=0x%"PRIx64".\n", @@ -241,10 +241,11 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) inst_len, c->eip); #endif - c->esp = vmcb->rsp; - c->eflags = vmcb->rflags; + c->rsp = vmcb->rsp; + c->rflags = vmcb->rflags; c->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; + c->cr2 = v->arch.hvm_svm.cpu_cr2; c->cr3 = v->arch.hvm_svm.cpu_cr3; c->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; @@ -315,14 +316,14 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) unsigned long mfn, old_base_mfn; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - vmcb->rip = c->eip; - vmcb->rsp = c->esp; - vmcb->rflags = c->eflags; + vmcb->rip = c->rip; + vmcb->rsp = c->rsp; + vmcb->rflags = c->rflags; v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0; - vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET; - if ( !paging_mode_hap(v->domain) ) - vmcb->cr0 |= X86_CR0_PG; + vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET | X86_CR0_PG; + + v->arch.hvm_svm.cpu_cr2 = c->cr2; #ifdef HVM_DEBUG_SUSPEND printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", @@ -421,6 +422,19 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; + /* update VMCB for nested paging restore */ + if ( paging_mode_hap(v->domain) ) { + vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; + vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; + vmcb->cr3 = c->cr3; + vmcb->np_enable = 1; + vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */ + vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); + } + + vmcb->dr6 = c->dr6; + vmcb->dr7 = c->dr7; + paging_update_paging_modes(v); return 0; @@ -440,6 +454,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) data->msr_cstar = vmcb->cstar; data->msr_syscall_mask = vmcb->sfmask; data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer; + data->msr_flags = -1ULL; data->tsc = hvm_get_guest_time(v); } diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index b4cfe17b29..1c47aadebc 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -370,11 +370,12 @@ static inline void __restore_debug_registers(struct vcpu *v) int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) { - c->eip = __vmread(GUEST_RIP); - c->esp = __vmread(GUEST_RSP); - c->eflags = __vmread(GUEST_RFLAGS); + c->rip = __vmread(GUEST_RIP); + c->rsp = __vmread(GUEST_RSP); + c->rflags = __vmread(GUEST_RFLAGS); c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; + c->cr2 = v->arch.hvm_vmx.cpu_cr2; c->cr3 = v->arch.hvm_vmx.cpu_cr3; c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4; @@ -444,13 +445,15 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmx_vmcs_enter(v); - __vmwrite(GUEST_RIP, c->eip); - __vmwrite(GUEST_RSP, c->esp); - __vmwrite(GUEST_RFLAGS, c->eflags); + __vmwrite(GUEST_RIP, c->rip); + __vmwrite(GUEST_RSP, c->rsp); + __vmwrite(GUEST_RFLAGS, c->rflags); v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0; __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0); + v->arch.hvm_vmx.cpu_cr2 = c->cr2; + #ifdef HVM_DEBUG_SUSPEND printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", c->cr3, @@ -555,6 +558,8 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) __vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp); __vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip); + __vmwrite(GUEST_DR7, c->dr7); + vmx_vmcs_exit(v); paging_update_paging_modes(v); @@ -590,7 +595,7 @@ void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) data->shadow_gs = guest_state->shadow_gs; /* save msrs */ - data->flags = guest_flags; + data->msr_flags = guest_flags; data->msr_lstar = guest_state->msrs[VMX_INDEX_MSR_LSTAR]; data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR]; data->msr_cstar = guest_state->msrs[VMX_INDEX_MSR_CSTAR]; @@ -607,7 +612,7 @@ void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state; /* restore msrs */ - guest_state->flags = data->flags; + guest_state->flags = data->msr_flags; guest_state->msrs[VMX_INDEX_MSR_LSTAR] = data->msr_lstar; guest_state->msrs[VMX_INDEX_MSR_STAR] = data->msr_star; guest_state->msrs[VMX_INDEX_MSR_CSTAR] = data->msr_cstar; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index fac87bcf02..ce49f743fe 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2041,7 +2041,7 @@ int do_mmuext_op( MEM_LOG("Error while pinning mfn %lx", mfn); break; } - + if ( unlikely(test_and_set_bit(_PGT_pinned, &page->u.inuse.type_info)) ) { @@ -2054,14 +2054,18 @@ int do_mmuext_op( /* A page is dirtied when its pin status is set. */ mark_dirty(d, mfn); - /* - * We can race domain destruction (domain_relinquish_resources). - * NB. The dying-flag test must happen /after/ setting PGT_pinned. - */ - if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) && - this_cpu(percpu_mm_info).foreign->is_dying && - test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) - put_page_and_type(page); + /* We can race domain destruction (domain_relinquish_resources). */ + if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) ) + { + int drop_ref; + spin_lock(&FOREIGNDOM->page_alloc_lock); + drop_ref = (FOREIGNDOM->is_dying && + test_and_clear_bit(_PGT_pinned, + &page->u.inuse.type_info)); + spin_unlock(&FOREIGNDOM->page_alloc_lock); + if ( drop_ref ) + put_page_and_type(page); + } break; diff --git a/xen/common/domain.c b/xen/common/domain.c index b876984869..8ade10f4ab 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -313,9 +313,6 @@ void domain_kill(struct domain *d) return; } - /* Tear down state /after/ setting the dying flag. */ - smp_wmb(); - gnttab_release_mappings(d); domain_relinquish_resources(d); put_domain(d); diff --git a/xen/include/asm-powerpc/system.h b/xen/include/asm-powerpc/system.h index 7eb41c9325..c0f21c64d0 100644 --- a/xen/include/asm-powerpc/system.h +++ b/xen/include/asm-powerpc/system.h @@ -28,7 +28,11 @@ #include #include -#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +#define xchg(ptr,x) \ +({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ +}) static __inline__ unsigned long __xchg_u32(volatile int *m, unsigned long val) diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h index ce1a2fc8ad..880e988b96 100644 --- a/xen/include/asm-x86/hvm/domain.h +++ b/xen/include/asm-x86/hvm/domain.h @@ -28,10 +28,16 @@ #include #include +struct hvm_ioreq_page { + spinlock_t lock; + struct page_info *page; + void *va; +}; + struct hvm_domain { - unsigned long shared_page_va; - unsigned long buffered_io_va; - spinlock_t buffered_io_lock; + struct hvm_ioreq_page ioreq; + struct hvm_ioreq_page buf_ioreq; + s64 tsc_frequency; struct pl_time pl_time; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 60f44194c8..2a3802423f 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -145,6 +145,7 @@ struct hvm_function_table { extern struct hvm_function_table hvm_funcs; int hvm_domain_initialise(struct domain *d); +void hvm_domain_relinquish_resources(struct domain *d); void hvm_domain_destroy(struct domain *d); int hvm_vcpu_initialise(struct vcpu *v); diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 1d331ef5da..efbc2b39b0 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -32,14 +32,13 @@ #define HVM_DEBUG 1 #endif -static inline shared_iopage_t *get_sp(struct domain *d) +static inline vcpu_iodata_t *get_ioreq(struct vcpu *v) { - return (shared_iopage_t *) d->arch.hvm_domain.shared_page_va; -} - -static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) -{ - return &get_sp(d)->vcpu_iodata[cpu]; + struct domain *d = v->domain; + shared_iopage_t *p = d->arch.hvm_domain.ioreq.va; + ASSERT((v == current) || spin_is_locked(&d->arch.hvm_domain.ioreq.lock)); + ASSERT(d->arch.hvm_domain.ioreq.va != NULL); + return &p->vcpu_iodata[v->vcpu_id]; } /* XXX these are really VMX specific */ diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index c921b50a78..14f120f9a6 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -87,13 +87,40 @@ DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); */ struct hvm_hw_cpu { - uint64_t eip; - uint64_t esp; - uint64_t eflags; + uint8_t fpu_regs[512]; + + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + + uint64_t rip; + uint64_t rflags; + uint64_t cr0; + uint64_t cr2; uint64_t cr3; uint64_t cr4; + uint64_t dr0; + uint64_t dr1; + uint64_t dr2; + uint64_t dr3; + uint64_t dr6; + uint64_t dr7; + uint32_t cs_sel; uint32_t ds_sel; uint32_t es_sel; @@ -142,9 +169,9 @@ struct hvm_hw_cpu { /* msr for em64t */ uint64_t shadow_gs; - uint64_t flags; /* msr content saved/restored. */ + uint64_t msr_flags; uint64_t msr_lstar; uint64_t msr_star; uint64_t msr_cstar; diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 7067f33ff7..cd2226678b 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -96,10 +96,10 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #else /* !CONFIG_DOMAIN_PAGE */ -#define map_domain_page(mfn) maddr_to_virt((mfn)<