diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-09-13 14:28:46 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-09-13 14:28:46 +0200 |
commit | c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278 (patch) | |
tree | 0004587285d811993caeb1cc6d99e3934ffbbcff | |
parent | a54dc5f4fe1eae6b1beb21326ef0338cd3969cd1 (diff) | |
parent | 255d252c0afafd0d2b6a9e4c2ad4dadbd2f00051 (diff) | |
download | xen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.tar.gz xen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.tar.bz2 xen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.zip |
Merge.
32 files changed, 788 insertions, 292 deletions
diff --git a/.gitignore b/.gitignore index c82a372f02..8e539b42b6 100644 --- a/.gitignore +++ b/.gitignore @@ -230,10 +230,11 @@ tools/remus/kmod/*(.cmd|.mod|.ko|.mod.c|.symvers|.xen) tools/security/secpol_tool tools/security/xen/* tools/security/xensec_tool -tools/tests/blowfish.bin -tools/tests/blowfish.h -tools/tests/test_x86_emulator -tools/tests/x86_emulate +tools/tests/x86_emulator/blowfish.bin +tools/tests/x86_emulator/blowfish.h +tools/tests/x86_emulator/test_x86_emulator +tools/tests/x86_emulator/x86_emulate +tools/tests/xen-access/xen-access tools/tests/regression/installed/* tools/tests/regression/build/* tools/tests/regression/downloads/* diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index 08d6cc45db..769767b02d 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -1130,6 +1130,20 @@ Specify the ticket password which is used by a client for connection. Whether SPICE agent is used for client mouse mode. The default is true (1) (turn on) +=item B<spicevdagent=BOOLEAN> + +Enables spice vdagent. The Spice vdagent is an optional component for +enhancing user experience and performing guest-oriented management +tasks. Its features includes: client mouse mode (no need to grab mouse +by client, no mouse lag), automatic adjustment of screen resolution, +copy and paste (text and image) between client and domU. It also +requires vdagent service installed on domU o.s. to work. The default is 0. + +=item B<spice_clipboard_sharing=BOOLEAN> + +Enables Spice clipboard sharing (copy/paste). It requires spicevdagent +enabled. The default is false (0). + =back =head3 Miscellaneous Emulated Hardware diff --git a/docs/misc/arm/booting.txt b/docs/misc/arm/booting.txt new file mode 100644 index 0000000000..9802e5e20f --- /dev/null +++ b/docs/misc/arm/booting.txt @@ -0,0 +1,30 @@ +Booting Xen +=========== + +Xen follows the zImage protocol defined for 32-bit ARM Linux[1] and the +Image protocol defined for ARM64 Linux[2]. + +In both cases the recommendation to boot in HYP/EL2 mode is a strict +requirement for Xen. + +The exceptions to this on 32-bit ARM are as follows: + + Xen does not require the machine type to be passed in r1. This + register is ignored (so may be invalid or the actual machine type). + + Xen does not support the ATAG list and requires Device + Tree. Therefore r2 must point to the physical address of device tree + block (dtb) in system RAM. + + NOTE: although Xen uses the zImage protocol there is no compression + actually used. This should be transparent to the bootloader. The + zImage protocol should still be used and not the stricter "raw + (non-zImage)" protocol described in arm/Booting. + +There are no exception on 64-bit ARM. + +[1] linux/Documentation/arm/Booting +Latest version: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm/Booting + +[2] linux/Documentation/arm64/booting.txt +Latest version: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/booting.txt diff --git a/extras/mini-os/console/xenbus.c b/extras/mini-os/console/xenbus.c index 23d4d32aea..41949824af 100644 --- a/extras/mini-os/console/xenbus.c +++ b/extras/mini-os/console/xenbus.c @@ -70,8 +70,10 @@ struct consfront_dev *init_consfront(char *_nodename) if (!_nodename) snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends); - else - strncpy(nodename, _nodename, sizeof(nodename)); + else { + strncpy(nodename, _nodename, sizeof(nodename) - 1); + nodename[sizeof(nodename) - 1] = 0; + } printk("******************* CONSFRONT for %s **********\n\n\n", nodename); diff --git a/extras/mini-os/lib/xs.c b/extras/mini-os/lib/xs.c index a2a122098c..c603d178bf 100644 --- a/extras/mini-os/lib/xs.c +++ b/extras/mini-os/lib/xs.c @@ -29,9 +29,12 @@ struct xs_handle *xs_daemon_open() void xs_daemon_close(struct xs_handle *h) { int fd = _xs_fileno(h); - struct xenbus_event *event; - for (event = files[fd].xenbus.events; event; event = event->next) + struct xenbus_event *event, *next; + for (event = files[fd].xenbus.events; event; event = next) + { + next = event->next; free(event); + } files[fd].type = FTYPE_NONE; } diff --git a/tools/debugger/kdd/kdd-xen.c b/tools/debugger/kdd/kdd-xen.c index 4fbea7df73..f3f9529f9f 100644 --- a/tools/debugger/kdd/kdd-xen.c +++ b/tools/debugger/kdd/kdd-xen.c @@ -619,7 +619,6 @@ void kdd_guest_teardown(kdd_guest *g) { flush_maps(g); xc_interface_close(g->xc_handle); - free(g->id); free(g->hvm_buf); free(g); } diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 4207eed6dc..4bc1abb441 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -417,24 +417,6 @@ elfnote_dump_format_version(xc_interface *xch, return dump_rtn(xch, args, (char*)&format_version, sizeof(format_version)); } -static int -get_guest_width(xc_interface *xch, - uint32_t domid, - unsigned int *guest_width) -{ - DECLARE_DOMCTL; - - memset(&domctl, 0, sizeof(domctl)); - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - - if ( do_domctl(xch, &domctl) != 0 ) - return 1; - - *guest_width = domctl.u.address_size.size / 8; - return 0; -} - int xc_domain_dumpcore_via_callback(xc_interface *xch, uint32_t domid, @@ -478,7 +460,7 @@ xc_domain_dumpcore_via_callback(xc_interface *xch, struct xc_core_section_headers *sheaders = NULL; Elf64_Shdr *shdr; - if ( get_guest_width(xch, domid, &dinfo->guest_width) != 0 ) + if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) != 0 ) { PERROR("Could not get address size for domain"); return sts; diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index fa47787d3e..bbbf9b80eb 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -436,17 +436,15 @@ static void xc_cpuid_pv_policy( const unsigned int *input, unsigned int *regs) { DECLARE_DOMCTL; + unsigned int guest_width; int guest_64bit, xen_64bit = hypervisor_is_64bit(xch); char brand[13]; uint64_t xfeature_mask; xc_cpuid_brand_get(brand); - memset(&domctl, 0, sizeof(domctl)); - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - do_domctl(xch, &domctl); - guest_64bit = (domctl.u.address_size.size == 64); + xc_domain_get_guest_width(xch, domid, &guest_width); + guest_64bit = (guest_width == 8); /* Detecting Xen's atitude towards XSAVE */ memset(&domctl, 0, sizeof(domctl)); diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c index d4d57b4649..71e1897bb5 100644 --- a/tools/libxc/xc_dom_boot.c +++ b/tools/libxc/xc_dom_boot.c @@ -62,19 +62,13 @@ static int setup_hypercall_page(struct xc_dom_image *dom) return rc; } -static int launch_vm(xc_interface *xch, domid_t domid, xc_hypercall_buffer_t *ctxt) +static int launch_vm(xc_interface *xch, domid_t domid, + vcpu_guest_context_any_t *ctxt) { - DECLARE_DOMCTL; - DECLARE_HYPERCALL_BUFFER_ARGUMENT(ctxt); int rc; xc_dom_printf(xch, "%s: called, ctxt=%p", __FUNCTION__, ctxt); - memset(&domctl, 0, sizeof(domctl)); - domctl.cmd = XEN_DOMCTL_setvcpucontext; - domctl.domain = domid; - domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); - rc = do_domctl(xch, &domctl); + 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); @@ -203,8 +197,8 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, int xc_dom_boot_image(struct xc_dom_image *dom) { - DECLARE_DOMCTL; DECLARE_HYPERCALL_BUFFER(vcpu_guest_context_any_t, ctxt); + xc_dominfo_t info; int rc; ctxt = xc_hypercall_buffer_alloc(dom->xch, ctxt, sizeof(*ctxt)); @@ -218,23 +212,22 @@ int xc_dom_boot_image(struct xc_dom_image *dom) return rc; /* collect some info */ - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = dom->guest_domid; - rc = do_domctl(dom->xch, &domctl); - if ( rc != 0 ) + rc = xc_domain_getinfo(dom->xch, dom->guest_domid, 1, &info); + if ( rc < 0 ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: getdomaininfo failed (rc=%d)", __FUNCTION__, rc); return rc; } - if ( domctl.domain != dom->guest_domid ) + if ( rc == 0 || info.domid != dom->guest_domid ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, - "%s: Huh? domid mismatch (%d != %d)", __FUNCTION__, - domctl.domain, dom->guest_domid); + "%s: Huh? No domains found (nr_domains=%d) " + "or domid mismatch (%d != %d)", __FUNCTION__, + rc, info.domid, dom->guest_domid); return -1; } - dom->shared_info_mfn = domctl.u.getdomaininfo.shared_info_frame; + dom->shared_info_mfn = info.shared_info_frame; /* sanity checks */ if ( !xc_dom_compat_check(dom) ) @@ -270,7 +263,7 @@ int xc_dom_boot_image(struct xc_dom_image *dom) if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 ) return rc; xc_dom_unmap_all(dom); - rc = launch_vm(dom->xch, dom->guest_domid, HYPERCALL_BUFFER(ctxt)); + rc = launch_vm(dom->xch, dom->guest_domid, ctxt); xc_hypercall_buffer_free(dom->xch, ctxt); return rc; diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index 41f59d3dd1..7cc2ff2411 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -54,24 +54,17 @@ const char *xc_domain_get_native_protocol(xc_interface *xch, int ret; uint32_t guest_width; const char *protocol; - DECLARE_DOMCTL; - memset(&domctl, 0, sizeof(domctl)); - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - - ret = do_domctl(xch, &domctl); + ret = xc_domain_get_guest_width(xch, domid, &guest_width); if ( ret ) return NULL; - guest_width = domctl.u.address_size.size; - switch (guest_width) { - case 32: /* 32 bit guest */ + case 4: /* 32 bit guest */ protocol = XEN_IO_PROTO_ABI_X86_32; break; - case 64: /* 64 bit guest */ + case 8: /* 64 bit guest */ protocol = XEN_IO_PROTO_ABI_X86_64; break; default: diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 3257e2af94..81316d3c7f 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -21,6 +21,8 @@ */ #include "xc_private.h" +#include "xc_core.h" +#include "xg_private.h" #include "xg_save_restore.h" #include <xen/memory.h> #include <xen/hvm/hvm_op.h> @@ -270,6 +272,22 @@ out: return ret; } +int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid, + unsigned int *guest_width) +{ + DECLARE_DOMCTL; + + memset(&domctl, 0, sizeof(domctl)); + domctl.domain = domid; + domctl.cmd = XEN_DOMCTL_get_address_size; + + if ( do_domctl(xch, &domctl) != 0 ) + return 1; + + /* We want the result in bytes */ + *guest_width = domctl.u.address_size.size / 8; + return 0; +} int xc_domain_getinfo(xc_interface *xch, uint32_t first_domid, @@ -1125,12 +1143,6 @@ int xc_vcpu_setcontext(xc_interface *xch, DECLARE_HYPERCALL_BOUNCE(ctxt, sizeof(vcpu_guest_context_any_t), XC_HYPERCALL_BUFFER_BOUNCE_IN); int rc; - if (ctxt == NULL) - { - errno = EINVAL; - return -1; - } - if ( xc_hypercall_bounce_pre(xch, ctxt) ) return -1; @@ -1467,6 +1479,131 @@ int xc_domain_bind_pt_isa_irq( PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq)); } +int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *minfo) +{ + struct domain_info_context _di = { .guest_width = minfo->guest_width }; + struct domain_info_context *dinfo = &_di; + + free(minfo->pfn_type); + if ( minfo->p2m_table ) + munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE); + minfo->p2m_table = NULL; + + return 0; +} + +int xc_map_domain_meminfo(xc_interface *xch, int domid, + struct xc_domain_meminfo *minfo) +{ + struct domain_info_context _di; + struct domain_info_context *dinfo = &_di; + + xc_dominfo_t info; + shared_info_any_t *live_shinfo; + xen_capabilities_info_t xen_caps = ""; + int i; + + /* Only be initialized once */ + if ( minfo->pfn_type || minfo->p2m_table ) + { + errno = EINVAL; + return -1; + } + + if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ) + { + PERROR("Could not get domain info"); + return -1; + } + + if ( xc_domain_get_guest_width(xch, domid, &minfo->guest_width) ) + { + PERROR("Could not get domain address size"); + return -1; + } + _di.guest_width = minfo->guest_width; + + /* Get page table levels (see get_platform_info() in xg_save_restore.h */ + if ( xc_version(xch, XENVER_capabilities, &xen_caps) ) + { + PERROR("Could not get Xen capabilities (for page table levels)"); + return -1; + } + if ( strstr(xen_caps, "xen-3.0-x86_64") ) + /* Depends on whether it's a compat 32-on-64 guest */ + minfo->pt_levels = ( (minfo->guest_width == 8) ? 4 : 3 ); + else if ( strstr(xen_caps, "xen-3.0-x86_32p") ) + minfo->pt_levels = 3; + else if ( strstr(xen_caps, "xen-3.0-x86_32") ) + minfo->pt_levels = 2; + else + { + errno = EFAULT; + return -1; + } + + /* We need the shared info page for mapping the P2M */ + live_shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ, + info.shared_info_frame); + if ( !live_shinfo ) + { + PERROR("Could not map the shared info frame (MFN 0x%lx)", + info.shared_info_frame); + return -1; + } + + if ( xc_core_arch_map_p2m_writable(xch, minfo->guest_width, &info, + live_shinfo, &minfo->p2m_table, + &minfo->p2m_size) ) + { + PERROR("Could not map the P2M table"); + munmap(live_shinfo, PAGE_SIZE); + return -1; + } + munmap(live_shinfo, PAGE_SIZE); + _di.p2m_size = minfo->p2m_size; + + /* Make space and prepare for getting the PFN types */ + minfo->pfn_type = calloc(sizeof(*minfo->pfn_type), minfo->p2m_size); + if ( !minfo->pfn_type ) + { + PERROR("Could not allocate memory for the PFN types"); + goto failed; + } + for ( i = 0; i < minfo->p2m_size; i++ ) + minfo->pfn_type[i] = pfn_to_mfn(i, minfo->p2m_table, + minfo->guest_width); + + /* Retrieve PFN types in batches */ + for ( i = 0; i < minfo->p2m_size ; i+=1024 ) + { + int count = ((minfo->p2m_size - i ) > 1024 ) ? + 1024: (minfo->p2m_size - i); + + if ( xc_get_pfn_type_batch(xch, domid, count, minfo->pfn_type + i) ) + { + PERROR("Could not get %d-eth batch of PFN types", (i+1)/1024); + goto failed; + } + } + + return 0; + +failed: + if ( minfo->pfn_type ) + { + free(minfo->pfn_type); + minfo->pfn_type = NULL; + } + if ( minfo->p2m_table ) + { + munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE); + minfo->p2m_table = NULL; + } + + return -1; +} + int xc_domain_memory_mapping( xc_interface *xch, uint32_t domid, diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 63d36cd63f..b418963e4b 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -1406,6 +1406,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, struct restore_callbacks *callbacks) { DECLARE_DOMCTL; + xc_dominfo_t info; int rc = 1, frc, i, j, n, m, pae_extended_cr3 = 0, ext_vcpucontext = 0; int vcpuextstate = 0; uint32_t vcpuextstate_size = 0; @@ -1562,14 +1563,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, ROUNDUP(MAX_BATCH_SIZE * sizeof(xen_pfn_t), PAGE_SHIFT)); /* Get the domain's shared-info frame. */ - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)dom; - if ( xc_domctl(xch, &domctl) < 0 ) + if ( xc_domain_getinfo(xch, (domid_t)dom, 1, &info) != 1 ) { PERROR("Could not get information on new domain"); goto out; } - shared_info_frame = domctl.u.getdomaininfo.shared_info_frame; + shared_info_frame = info.shared_info_frame; /* Mark all PFNs as invalid; we allocate on demand */ for ( pfn = 0; pfn < dinfo->p2m_size; pfn++ ) @@ -2113,11 +2112,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, } ctxt->x64.ctrlreg[1] = FOLD_CR3(ctx->p2m[pfn]); } - domctl.cmd = XEN_DOMCTL_setvcpucontext; - domctl.domain = (domid_t)dom; - domctl.u.vcpucontext.vcpu = i; - set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); - frc = xc_domctl(xch, &domctl); + frc = xc_vcpu_setcontext(xch, dom, i, ctxt); if ( frc != 0 ) { PERROR("Couldn't build vcpu%d", i); diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c index 36b981285c..fbb53f5f0f 100644 --- a/tools/libxc/xc_offline_page.c +++ b/tools/libxc/xc_offline_page.c @@ -33,17 +33,6 @@ #include "xg_private.h" #include "xg_save_restore.h" -struct domain_mem_info{ - int domid; - unsigned int pt_level; - unsigned int guest_width; - xen_pfn_t *pfn_type; - xen_pfn_t *p2m_table; - unsigned long p2m_size; - xen_pfn_t *m2p_table; - int max_mfn; -}; - struct pte_backup_entry { xen_pfn_t table_mfn; @@ -180,146 +169,6 @@ static int xc_is_page_granted_v2(xc_interface *xch, xen_pfn_t gpfn, return (i != gnt_num); } -static xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth) -{ - return ((xen_pfn_t) ((gwidth==8)? - (((uint64_t *)p2m)[(pfn)]): - ((((uint32_t *)p2m)[(pfn)]) == 0xffffffffU ? - (-1UL) : - (((uint32_t *)p2m)[(pfn)])))); -} - -static int get_pt_level(xc_interface *xch, uint32_t domid, - unsigned int *pt_level, - unsigned int *gwidth) -{ - DECLARE_DOMCTL; - xen_capabilities_info_t xen_caps = ""; - - if (xc_version(xch, XENVER_capabilities, &xen_caps) != 0) - return -1; - - memset(&domctl, 0, sizeof(domctl)); - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - - if ( do_domctl(xch, &domctl) != 0 ) - return -1; - - *gwidth = domctl.u.address_size.size / 8; - - if (strstr(xen_caps, "xen-3.0-x86_64")) - /* Depends on whether it's a compat 32-on-64 guest */ - *pt_level = ( (*gwidth == 8) ? 4 : 3 ); - else if (strstr(xen_caps, "xen-3.0-x86_32p")) - *pt_level = 3; - else if (strstr(xen_caps, "xen-3.0-x86_32")) - *pt_level = 2; - else - return -1; - - return 0; -} - -static int close_mem_info(xc_interface *xch, struct domain_mem_info *minfo) -{ - if (minfo->pfn_type) - free(minfo->pfn_type); - munmap(minfo->m2p_table, M2P_SIZE(minfo->max_mfn)); - munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE); - minfo->p2m_table = minfo->m2p_table = NULL; - - return 0; -} - -static int init_mem_info(xc_interface *xch, int domid, - struct domain_mem_info *minfo, - xc_dominfo_t *info) -{ - uint64_aligned_t shared_info_frame; - shared_info_any_t *live_shinfo = NULL; - int i, rc; - - /* Only be initialized once */ - if (minfo->pfn_type || minfo->m2p_table || minfo->p2m_table) - return -EINVAL; - - if ( get_pt_level(xch, domid, &minfo->pt_level, - &minfo->guest_width) ) - { - ERROR("Unable to get PT level info."); - return -EFAULT; - } - dinfo->guest_width = minfo->guest_width; - - shared_info_frame = info->shared_info_frame; - - live_shinfo = xc_map_foreign_range(xch, domid, - PAGE_SIZE, PROT_READ, shared_info_frame); - if ( !live_shinfo ) - { - ERROR("Couldn't map live_shinfo"); - return -EFAULT; - } - - if ( (rc = xc_core_arch_map_p2m_writable(xch, minfo->guest_width, - info, live_shinfo, &minfo->p2m_table, &minfo->p2m_size)) ) - { - ERROR("Couldn't map p2m table %x\n", rc); - goto failed; - } - munmap(live_shinfo, PAGE_SIZE); - live_shinfo = NULL; - - dinfo->p2m_size = minfo->p2m_size; - - minfo->max_mfn = xc_maximum_ram_page(xch); - if ( !(minfo->m2p_table = - xc_map_m2p(xch, minfo->max_mfn, PROT_READ, NULL)) ) - { - ERROR("Failed to map live M2P table"); - goto failed; - } - - /* Get pfn type */ - minfo->pfn_type = calloc(sizeof(*minfo->pfn_type), minfo->p2m_size); - if (!minfo->pfn_type) - { - ERROR("Failed to malloc pfn_type\n"); - goto failed; - } - - for (i = 0; i < minfo->p2m_size; i++) - minfo->pfn_type[i] = pfn_to_mfn(i, minfo->p2m_table, - minfo->guest_width); - - for (i = 0; i < minfo->p2m_size ; i+=1024) - { - int count = ((dinfo->p2m_size - i ) > 1024 ) ? 1024: (dinfo->p2m_size - i); - if ( ( rc = xc_get_pfn_type_batch(xch, domid, count, - minfo->pfn_type + i)) ) - { - ERROR("Failed to get pfn_type %x\n", rc); - goto failed; - } - } - return 0; - -failed: - if (minfo->pfn_type) - { - free(minfo->pfn_type); - minfo->pfn_type = NULL; - } - if (live_shinfo) - munmap(live_shinfo, PAGE_SIZE); - munmap(minfo->m2p_table, M2P_SIZE(minfo->max_mfn)); - munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE); - minfo->p2m_table = minfo->m2p_table = NULL; - - return -1; -} - static int backup_ptes(xen_pfn_t table_mfn, int offset, struct pte_backup *backup) { @@ -409,7 +258,7 @@ static int __update_pte(xc_interface *xch, } static int change_pte(xc_interface *xch, int domid, - struct domain_mem_info *minfo, + struct xc_domain_meminfo *minfo, struct pte_backup *backup, struct xc_mmu *mmu, pte_func func, @@ -419,7 +268,7 @@ static int change_pte(xc_interface *xch, int domid, uint64_t i; void *content = NULL; - pte_num = PAGE_SIZE / ((minfo->pt_level == 2) ? 4 : 8); + pte_num = PAGE_SIZE / ((minfo->pt_levels == 2) ? 4 : 8); for (i = 0; i < minfo->p2m_size; i++) { @@ -442,7 +291,7 @@ static int change_pte(xc_interface *xch, int domid, for (j = 0; j < pte_num; j++) { - if ( minfo->pt_level == 2 ) + if ( minfo->pt_levels == 2 ) pte = ((const uint32_t*)content)[j]; else pte = ((const uint64_t*)content)[j]; @@ -454,7 +303,7 @@ static int change_pte(xc_interface *xch, int domid, case 1: if ( xc_add_mmu_update(xch, mmu, table_mfn << PAGE_SHIFT | - j * ( (minfo->pt_level == 2) ? + j * ( (minfo->pt_levels == 2) ? sizeof(uint32_t): sizeof(uint64_t)) | MMU_PT_UPDATE_PRESERVE_AD, new_pte) ) @@ -487,7 +336,7 @@ failed: } static int update_pte(xc_interface *xch, int domid, - struct domain_mem_info *minfo, + struct xc_domain_meminfo *minfo, struct pte_backup *backup, struct xc_mmu *mmu, unsigned long new_mfn) @@ -497,7 +346,7 @@ static int update_pte(xc_interface *xch, int domid, } static int clear_pte(xc_interface *xch, int domid, - struct domain_mem_info *minfo, + struct xc_domain_meminfo *minfo, struct pte_backup *backup, struct xc_mmu *mmu, xen_pfn_t mfn) @@ -545,7 +394,7 @@ static int is_page_exchangable(xc_interface *xch, int domid, xen_pfn_t mfn, int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn) { xc_dominfo_t info; - struct domain_mem_info minfo; + struct xc_domain_meminfo minfo; struct xc_mmu *mmu = NULL; struct pte_backup old_ptes = {NULL, 0, 0}; grant_entry_v1_t *gnttab_v1 = NULL; @@ -556,6 +405,8 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn) int rc, result = -1; uint32_t status; xen_pfn_t new_mfn, gpfn; + xen_pfn_t *m2p_table; + int max_mfn; if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ) { @@ -575,10 +426,26 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn) return -EINVAL; } - /* Get domain's memory information */ + /* Map M2P and obtain gpfn */ + max_mfn = xc_maximum_ram_page(xch); + if ( !(m2p_table = xc_map_m2p(xch, max_mfn, PROT_READ, NULL)) ) + { + PERROR("Failed to map live M2P table"); + return -EFAULT; + } + gpfn = m2p_table[mfn]; + + /* Map domain's memory information */ memset(&minfo, 0, sizeof(minfo)); - init_mem_info(xch, domid, &minfo, &info); - gpfn = minfo.m2p_table[mfn]; + if ( xc_map_domain_meminfo(xch, domid, &minfo) ) + { + PERROR("Could not map domain's memory information\n"); + return -EFAULT; + } + + /* For translation macros */ + dinfo->guest_width = minfo.guest_width; + dinfo->p2m_size = minfo.p2m_size; /* Don't exchange CR3 for PAE guest in PAE host environment */ if (minfo.guest_width > sizeof(long)) @@ -773,7 +640,8 @@ failed: if (gnttab_v2) munmap(gnttab_v2, gnt_num / (PAGE_SIZE/sizeof(grant_entry_v2_t))); - close_mem_info(xch, &minfo); + xc_unmap_domain_meminfo(xch, &minfo); + munmap(m2p_table, M2P_SIZE(max_mfn)); return result; } diff --git a/tools/libxc/xc_pagetab.c b/tools/libxc/xc_pagetab.c index 27c4e9fcbc..8525967527 100644 --- a/tools/libxc/xc_pagetab.c +++ b/tools/libxc/xc_pagetab.c @@ -51,15 +51,13 @@ unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom, pt_levels = (ctx.msr_efer&EFER_LMA) ? 4 : (ctx.cr4&CR4_PAE) ? 3 : 2; paddr = ctx.cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull); } else { - DECLARE_DOMCTL; + unsigned int gwidth; vcpu_guest_context_any_t ctx; if (xc_vcpu_getcontext(xch, dom, vcpu, &ctx) != 0) return 0; - domctl.domain = dom; - domctl.cmd = XEN_DOMCTL_get_address_size; - if ( do_domctl(xch, &domctl) != 0 ) + if (xc_domain_get_guest_width(xch, dom, &gwidth) != 0) return 0; - if (domctl.u.address_size.size == 64) { + if (gwidth == 8) { pt_levels = 4; paddr = (uint64_t)xen_cr3_to_pfn_x86_64(ctx.x64.ctrlreg[3]) << PAGE_SHIFT; diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index acaf9e0e1e..a260257cd5 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -609,11 +609,9 @@ int xc_get_pfn_list(xc_interface *xch, long xc_get_tot_pages(xc_interface *xch, uint32_t domid) { - DECLARE_DOMCTL; - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)domid; - return (do_domctl(xch, &domctl) < 0) ? - -1 : domctl.u.getdomaininfo.tot_pages; + xc_dominfo_t info; + return (xc_domain_getinfo(xch, domid, 1, &info) != 1) ? + -1 : info.nr_pages; } int xc_copy_to_domain_page(xc_interface *xch, diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c index 1c43ec612d..cb6165049f 100644 --- a/tools/libxc/xc_resume.c +++ b/tools/libxc/xc_resume.c @@ -24,19 +24,6 @@ #include <xen/foreign/x86_64.h> #include <xen/hvm/params.h> -static int pv_guest_width(xc_interface *xch, uint32_t domid) -{ - DECLARE_DOMCTL; - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - if ( xc_domctl(xch, &domctl) != 0 ) - { - PERROR("Could not get guest address size"); - return -1; - } - return domctl.u.address_size.size / 8; -} - static int modify_returncode(xc_interface *xch, uint32_t domid) { vcpu_guest_context_any_t ctxt; @@ -71,8 +58,7 @@ static int modify_returncode(xc_interface *xch, uint32_t domid) else { /* Probe PV guest address width. */ - dinfo->guest_width = pv_guest_width(xch, domid); - if ( dinfo->guest_width < 0 ) + if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) ) return -1; } @@ -120,7 +106,8 @@ static int xc_domain_resume_any(xc_interface *xch, uint32_t domid) xc_dominfo_t info; int i, rc = -1; #if defined(__i386__) || defined(__x86_64__) - struct domain_info_context _dinfo = { .p2m_size = 0 }; + 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; @@ -147,7 +134,7 @@ static int xc_domain_resume_any(xc_interface *xch, uint32_t domid) return rc; } - dinfo->guest_width = pv_guest_width(xch, domid); + xc_domain_get_guest_width(xch, domid, &dinfo->guest_width); if ( dinfo->guest_width != sizeof(long) ) { ERROR("Cannot resume uncooperative cross-address-size guests"); diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index f2cebafc9d..58d51f353a 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -560,6 +560,19 @@ int xc_vcpu_getaffinity(xc_interface *xch, int vcpu, xc_cpumap_t cpumap); + +/** + * This function will return the guest_width (in bytes) for the + * specified domain. + * + * @param xch a handle to an open hypervisor interface. + * @param domid the domain id one wants the address size width of. + * @param addr_size the address size. + */ +int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid, + unsigned int *guest_width); + + /** * This function will return information about one or more domains. It is * designed to iterate over the list of domains. If a single domain is diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 4714bd2249..c12091f52b 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -276,6 +276,23 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn); /** + * Memory related information, such as PFN types, the P2M table, + * the guest word width and the guest page table levels. + */ +struct xc_domain_meminfo { + unsigned int pt_levels; + unsigned int guest_width; + xen_pfn_t *pfn_type; + xen_pfn_t *p2m_table; + unsigned long p2m_size; +}; + +int xc_map_domain_meminfo(xc_interface *xch, int domid, + struct xc_domain_meminfo *minfo); + +int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *mem); + +/** * This function map m2p table * @parm xch a handle to an open hypervisor interface * @parm max_mfn the max pfn diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index db02ccf470..5ff2124346 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -136,6 +136,15 @@ struct domain_info_context { unsigned long p2m_size; }; +static inline xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth) +{ + return ((xen_pfn_t) ((gwidth==8)? + (((uint64_t *)p2m)[(pfn)]): + ((((uint32_t *)p2m)[(pfn)]) == 0xffffffffU ? + (-1UL) : + (((uint32_t *)p2m)[(pfn)])))); +} + /* Number of xen_pfn_t in a page */ #define FPP (PAGE_SIZE/(dinfo->guest_width)) diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index 651200339b..f859621f62 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -301,7 +301,6 @@ static inline int get_platform_info(xc_interface *xch, uint32_t dom, { xen_capabilities_info_t xen_caps = ""; xen_platform_parameters_t xen_params; - DECLARE_DOMCTL; if (xc_version(xch, XENVER_platform_parameters, &xen_params) != 0) return 0; @@ -313,15 +312,9 @@ static inline int get_platform_info(xc_interface *xch, uint32_t dom, *hvirt_start = xen_params.virt_start; - memset(&domctl, 0, sizeof(domctl)); - domctl.domain = dom; - domctl.cmd = XEN_DOMCTL_get_address_size; - - if ( do_domctl(xch, &domctl) != 0 ) + if ( xc_domain_get_guest_width(xch, dom, guest_width) != 0) return 0; - *guest_width = domctl.u.address_size.size / 8; - /* 64-bit tools will see the 64-bit hvirt_start, but 32-bit guests * will be using the compat one. */ if ( *guest_width < sizeof (unsigned long) ) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 1bce4bb46f..0879f2331f 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -122,8 +122,8 @@ static void free_disable_deaths(libxl__gc *gc, static void discard_events(struct libxl__event_list *l) { /* doesn't bother unlinking from the list, so l is corrupt on return */ - libxl_event *ev; - LIBXL_TAILQ_FOREACH(ev, l, link) + libxl_event *ev, *next; + LIBXL_TAILQ_FOREACH_SAFE(ev, l, link, next) libxl_event_free(0, ev); } @@ -2234,9 +2234,16 @@ static int libxl__device_disk_from_xs_be(libxl__gc *gc, libxl_ctx *ctx = libxl__gc_owner(gc); unsigned int len; char *tmp; + int rc; libxl_device_disk_init(disk); + rc = sscanf(be_path, "/local/domain/%d/", &disk->backend_domid); + if (rc != 1) { + LOG(ERROR, "Unable to fetch device backend domid from %s", be_path); + goto cleanup; + } + /* "params" may not be present; but everything else must be. */ tmp = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "%s/params", be_path), &len); diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index be19bf5186..4cab2947e7 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -344,6 +344,17 @@ */ #define LIBXL_HAVE_DOMINFO_OUTSTANDING_MEMKB 1 +/* + * LIBXL_HAVE_SPICE_VDAGENT + * + * If defined, then the libxl_spice_info structure will contain a boolean type: + * vdagent and clipboard_sharing. These values define if Spice vdagent and + * clipboard sharing are enabled. + * + * If this is not defined, the Spice vdagent support is ignored. + */ +#define LIBXL_HAVE_SPICE_VDAGENT 1 + /* Functions annotated with LIBXL_EXTERNAL_CALLERS_ONLY may not be * called from within libxl itself. Callers outside libxl, who * do not #include libxl_internal.h, are fine. */ diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 0c32d0b143..7567238f75 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -272,6 +272,9 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc, libxl_defbool_setdefault(&b_info->u.hvm.spice.disable_ticketing, false); libxl_defbool_setdefault(&b_info->u.hvm.spice.agent_mouse, true); + libxl_defbool_setdefault(&b_info->u.hvm.spice.vdagent, false); + libxl_defbool_setdefault(&b_info->u.hvm.spice.clipboard_sharing, + false); } libxl_defbool_setdefault(&b_info->u.hvm.nographic, false); diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 4035b6db62..43c3becc7a 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -351,6 +351,10 @@ static char *dm_spice_options(libxl__gc *gc, opt = libxl__sprintf(gc, "%s,password=%s", opt, spice->passwd); opt = libxl__sprintf(gc, "%s,agent-mouse=%s", opt, libxl_defbool_val(spice->agent_mouse) ? "on" : "off"); + + if (!libxl_defbool_val(spice->clipboard_sharing)) + opt = libxl__sprintf(gc, "%s,disable-copy-paste", opt); + return opt; } @@ -472,6 +476,12 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc, flexarray_append(dm_args, "-spice"); flexarray_append(dm_args, spiceoptions); + if (libxl_defbool_val(b_info->u.hvm.spice.vdagent)) { + flexarray_vappend(dm_args, "-device", "virtio-serial", + "-chardev", "spicevmc,id=vdagent,name=vdagent", "-device", + "virtserialport,chardev=vdagent,name=com.redhat.spice.0", + NULL); + } } switch (b_info->u.hvm.vga.kind) { diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c index 98bfd716ac..7eddaef2e3 100644 --- a/tools/libxl/libxl_exec.c +++ b/tools/libxl/libxl_exec.c @@ -33,7 +33,7 @@ static void check_open_fds(const char *what) for (i = 4; i < 256; i++) { #ifdef __linux__ - size_t len; + ssize_t len; char path[PATH_MAX]; char linkpath[PATH_MAX+1]; #endif diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 10f95f42e3..049dbb50b5 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -181,6 +181,8 @@ libxl_spice_info = Struct("spice_info", [ ("disable_ticketing", libxl_defbool), ("passwd", string), ("agent_mouse", libxl_defbool), + ("vdagent", libxl_defbool), + ("clipboard_sharing", libxl_defbool), ]) libxl_sdl_info = Struct("sdl_info", [ diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 884f050644..3d7eaad5e0 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -1495,6 +1495,10 @@ skip_vfb: &b_info->u.hvm.spice.passwd, 0); xlu_cfg_get_defbool(config, "spiceagent_mouse", &b_info->u.hvm.spice.agent_mouse, 0); + xlu_cfg_get_defbool(config, "spicevdagent", + &b_info->u.hvm.spice.vdagent, 0); + xlu_cfg_get_defbool(config, "spice_clipboard_sharing", + &b_info->u.hvm.spice.clipboard_sharing, 0); xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0); xlu_cfg_get_defbool(config, "gfx_passthru", &b_info->u.hvm.gfx_passthru, 0); @@ -6570,7 +6574,7 @@ int main_cpupoollist(int argc, char **argv) char *name; int ret = 0; - SWITCH_FOREACH_OPT(opt, "hc", opts, "cpupool-list", 1) { + SWITCH_FOREACH_OPT(opt, "hc", opts, "cpupool-list", 0) { case 'c': opt_cpus = 1; break; diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 59def7af94..17aeda57d1 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -10,7 +10,7 @@ CFLAGS += $(CFLAGS_libxenstore) HDRS = $(wildcard *.h) TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xencov -TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd +TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd xen-mfndump TARGETS-$(CONFIG_MIGRATE) += xen-hptool TARGETS := $(TARGETS-y) @@ -22,7 +22,7 @@ INSTALL_BIN := $(INSTALL_BIN-y) INSTALL_SBIN-y := xen-bugtool xen-python-path xenperf xenpm xen-tmem-list-parse gtraceview \ gtracestat xenlockprof xenwatchdogd xen-ringwatch xencov -INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash xen-lowmemd +INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash xen-lowmemd xen-mfndump INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool INSTALL_SBIN := $(INSTALL_SBIN-y) @@ -75,6 +75,9 @@ xenlockprof: xenlockprof.o xen-hptool: xen-hptool.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) +xen-mfndump: xen-mfndump.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) + xenwatchdogd: xenwatchdogd.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) diff --git a/tools/misc/xen-mfndump.c b/tools/misc/xen-mfndump.c new file mode 100644 index 0000000000..3e8302eb05 --- /dev/null +++ b/tools/misc/xen-mfndump.c @@ -0,0 +1,425 @@ +#include <xenctrl.h> +#include <xc_private.h> +#include <xc_core.h> +#include <errno.h> +#include <unistd.h> + +#include "xg_save_restore.h" + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +static xc_interface *xch; + +int help_func(int argc, char *argv[]) +{ + fprintf(stderr, + "Usage: xen-mfndump <command> [args]\n" + "Commands:\n" + " help show this help\n" + " dump-m2p show M2P\n" + " dump-p2m <domid> show P2M of <domid>\n" + " dump-ptes <domid> <mfn> show the PTEs in <mfn>\n" + " lookup-pte <domid> <mfn> find the PTE mapping <mfn>\n" + " memcmp-mfns <domid1> <mfn1> <domid2> <mfn2>\n" + " compare content of <mfn1> & <mfn2>\n" + ); + + return 0; +} + +int dump_m2p_func(int argc, char *argv[]) +{ + unsigned long i, max_mfn; + xen_pfn_t *m2p_table; + + if ( argc > 0 ) + { + help_func(0, NULL); + return 1; + } + + /* Map M2P and obtain gpfn */ + max_mfn = xc_maximum_ram_page(xch); + if ( !(m2p_table = xc_map_m2p(xch, max_mfn, PROT_READ, NULL)) ) + { + ERROR("Failed to map live M2P table"); + return -1; + } + + printf(" --- Dumping M2P ---\n"); + printf(" Max MFN: %lu\n", max_mfn); + for ( i = 0; i < max_mfn; i++ ) + { + printf(" mfn=0x%lx ==> pfn=0x%lx\n", i, m2p_table[i]); + } + printf(" --- End of M2P ---\n"); + + munmap(m2p_table, M2P_SIZE(max_mfn)); + return 0; +} + +int dump_p2m_func(int argc, char *argv[]) +{ + struct xc_domain_meminfo minfo; + xc_dominfo_t info; + unsigned long i; + int domid; + + if ( argc < 1 ) + { + help_func(0, NULL); + return 1; + } + domid = atoi(argv[0]); + + if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 || + info.domid != domid ) + { + ERROR("Failed to obtain info for domain %d\n", domid); + return -1; + } + + /* Retrieve all the info about the domain's memory */ + memset(&minfo, 0, sizeof(minfo)); + if ( xc_map_domain_meminfo(xch, domid, &minfo) ) + { + ERROR("Could not map domain %d memory information\n", domid); + return -1; + } + + printf(" --- Dumping P2M for domain %d ---\n", domid); + printf(" Guest Width: %u, PT Levels: %u P2M size: = %lu\n", + minfo.guest_width, minfo.pt_levels, minfo.p2m_size); + for ( i = 0; i < minfo.p2m_size; i++ ) + { + unsigned long pagetype = minfo.pfn_type[i] & + XEN_DOMCTL_PFINFO_LTAB_MASK; + + printf(" pfn=0x%lx ==> mfn=0x%lx (type 0x%lx)", i, minfo.p2m_table[i], + pagetype >> XEN_DOMCTL_PFINFO_LTAB_SHIFT); + + if ( is_mapped(minfo.p2m_table[i]) ) + printf(" [mapped]"); + + if ( pagetype & XEN_DOMCTL_PFINFO_LPINTAB ) + printf (" [pinned]"); + + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) + printf(" [xtab]"); + if ( pagetype == XEN_DOMCTL_PFINFO_BROKEN ) + printf(" [broken]"); + if ( pagetype == XEN_DOMCTL_PFINFO_XALLOC ) + printf( " [xalloc]"); + + switch ( pagetype & XEN_DOMCTL_PFINFO_LTABTYPE_MASK ) + { + case XEN_DOMCTL_PFINFO_L1TAB: + printf(" L1 table"); + break; + + case XEN_DOMCTL_PFINFO_L2TAB: + printf(" L2 table"); + break; + + case XEN_DOMCTL_PFINFO_L3TAB: + printf(" L3 table"); + break; + + case XEN_DOMCTL_PFINFO_L4TAB: + printf(" L4 table"); + break; + } + + printf("\n"); + } + printf(" --- End of P2M for domain %d ---\n", domid); + + xc_unmap_domain_meminfo(xch, &minfo); + return 0; +} + +int dump_ptes_func(int argc, char *argv[]) +{ + struct xc_domain_meminfo minfo; + xc_dominfo_t info; + void *page = NULL; + unsigned long i, max_mfn; + int domid, pte_num, rc = 0; + xen_pfn_t pfn, mfn, *m2p_table; + + if ( argc < 2 ) + { + help_func(0, NULL); + return 1; + } + domid = atoi(argv[0]); + mfn = strtoul(argv[1], NULL, 16); + + if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 || + info.domid != domid ) + { + ERROR("Failed to obtain info for domain %d\n", domid); + return -1; + } + + /* Retrieve all the info about the domain's memory */ + memset(&minfo, 0, sizeof(minfo)); + if ( xc_map_domain_meminfo(xch, domid, &minfo) ) + { + ERROR("Could not map domain %d memory information\n", domid); + return -1; + } + + /* Map M2P and obtain gpfn */ + max_mfn = xc_maximum_ram_page(xch); + if ( (mfn > max_mfn) || + !(m2p_table = xc_map_m2p(xch, max_mfn, PROT_READ, NULL)) ) + { + xc_unmap_domain_meminfo(xch, &minfo); + ERROR("Failed to map live M2P table"); + return -1; + } + + pfn = m2p_table[mfn]; + if ( pfn >= minfo.p2m_size ) + { + ERROR("pfn 0x%lx out of range for domain %d\n", pfn, domid); + rc = -1; + goto out; + } + + if ( !(minfo.pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ) + { + ERROR("pfn 0x%lx for domain %d is not a PT\n", pfn, domid); + rc = -1; + goto out; + } + + page = xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ, + minfo.p2m_table[pfn]); + if ( !page ) + { + ERROR("Failed to map 0x%lx\n", minfo.p2m_table[pfn]); + rc = -1; + goto out; + } + + pte_num = PAGE_SIZE / 8; + + printf(" --- Dumping %d PTEs for domain %d ---\n", pte_num, domid); + printf(" Guest Width: %u, PT Levels: %u P2M size: = %lu\n", + minfo.guest_width, minfo.pt_levels, minfo.p2m_size); + printf(" pfn: 0x%lx, mfn: 0x%lx", + pfn, minfo.p2m_table[pfn]); + switch ( minfo.pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK ) + { + case XEN_DOMCTL_PFINFO_L1TAB: + printf(", L1 table"); + break; + case XEN_DOMCTL_PFINFO_L2TAB: + printf(", L2 table"); + break; + case XEN_DOMCTL_PFINFO_L3TAB: + printf(", L3 table"); + break; + case XEN_DOMCTL_PFINFO_L4TAB: + printf(", L4 table"); + break; + } + if ( minfo.pfn_type[pfn] & XEN_DOMCTL_PFINFO_LPINTAB ) + printf (" [pinned]"); + if ( is_mapped(minfo.p2m_table[pfn]) ) + printf(" [mapped]"); + printf("\n"); + + for ( i = 0; i < pte_num; i++ ) + printf(" pte[%lu]: 0x%lx\n", i, ((const uint64_t*)page)[i]); + + printf(" --- End of PTEs for domain %d, pfn=0x%lx (mfn=0x%lx) ---\n", + domid, pfn, minfo.p2m_table[pfn]); + + out: + munmap(page, PAGE_SIZE); + xc_unmap_domain_meminfo(xch, &minfo); + munmap(m2p_table, M2P_SIZE(max_mfn)); + return rc; +} + +int lookup_pte_func(int argc, char *argv[]) +{ + struct xc_domain_meminfo minfo; + xc_dominfo_t info; + void *page = NULL; + unsigned long i, j; + int domid, pte_num; + xen_pfn_t mfn; + + if ( argc < 2 ) + { + help_func(0, NULL); + return 1; + } + domid = atoi(argv[0]); + mfn = strtoul(argv[1], NULL, 16); + + if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 || + info.domid != domid ) + { + ERROR("Failed to obtain info for domain %d\n", domid); + return -1; + } + + /* Retrieve all the info about the domain's memory */ + memset(&minfo, 0, sizeof(minfo)); + if ( xc_map_domain_meminfo(xch, domid, &minfo) ) + { + ERROR("Could not map domain %d memory information\n", domid); + return -1; + } + + pte_num = PAGE_SIZE / 8; + + printf(" --- Lookig for PTEs mapping mfn 0x%lx for domain %d ---\n", + mfn, domid); + printf(" Guest Width: %u, PT Levels: %u P2M size: = %lu\n", + minfo.guest_width, minfo.pt_levels, minfo.p2m_size); + + for ( i = 0; i < minfo.p2m_size; i++ ) + { + if ( !(minfo.pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ) + continue; + + page = xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ, + minfo.p2m_table[i]); + if ( !page ) + continue; + + for ( j = 0; j < pte_num; j++ ) + { + uint64_t pte = ((const uint64_t*)page)[j]; + +#define __MADDR_BITS_X86 ((minfo.guest_width == 8) ? 52 : 44) +#define __MFN_MASK_X86 ((1ULL << (__MADDR_BITS_X86 - PAGE_SHIFT_X86)) - 1) + if ( ((pte >> PAGE_SHIFT_X86) & __MFN_MASK_X86) == mfn) + printf(" 0x%lx <-- [0x%lx][%lu]: 0x%lx\n", + mfn, minfo.p2m_table[i], j, pte); +#undef __MADDR_BITS_X86 +#undef __MFN_MASK_X8 + } + + munmap(page, PAGE_SIZE); + page = NULL; + } + + xc_unmap_domain_meminfo(xch, &minfo); + + return 1; +} + +int memcmp_mfns_func(int argc, char *argv[]) +{ + xc_dominfo_t info1, info2; + void *page1 = NULL, *page2 = NULL; + int domid1, domid2; + xen_pfn_t mfn1, mfn2; + int rc = 0; + + if ( argc < 4 ) + { + help_func(0, NULL); + return 1; + } + domid1 = atoi(argv[0]); + domid2 = atoi(argv[2]); + mfn1 = strtoul(argv[1], NULL, 16); + mfn2 = strtoul(argv[3], NULL, 16); + + if ( xc_domain_getinfo(xch, domid1, 1, &info1) != 1 || + xc_domain_getinfo(xch, domid2, 1, &info2) != 1 || + info1.domid != domid1 || info2.domid != domid2) + { + ERROR("Failed to obtain info for domains\n"); + return -1; + } + + page1 = xc_map_foreign_range(xch, domid1, PAGE_SIZE, PROT_READ, mfn1); + page2 = xc_map_foreign_range(xch, domid2, PAGE_SIZE, PROT_READ, mfn2); + if ( !page1 || !page2 ) + { + ERROR("Failed to map either 0x%lx[dom %d] or 0x%lx[dom %d]\n", + mfn1, domid1, mfn2, domid2); + rc = -1; + goto out; + } + + printf(" --- Comparing the content of 2 MFNs ---\n"); + printf(" 1: 0x%lx[dom %d], 2: 0x%lx[dom %d]\n", + mfn1, domid1, mfn2, domid2); + printf(" memcpy(1, 2) = %d\n", memcmp(page1, page2, PAGE_SIZE)); + + out: + munmap(page1, PAGE_SIZE); + munmap(page2, PAGE_SIZE); + return rc; +} + + + +struct { + const char *name; + int (*func)(int argc, char *argv[]); +} opts[] = { + { "help", help_func }, + { "dump-m2p", dump_m2p_func }, + { "dump-p2m", dump_p2m_func }, + { "dump-ptes", dump_ptes_func }, + { "lookup-pte", lookup_pte_func }, + { "memcmp-mfns", memcmp_mfns_func}, +}; + +int main(int argc, char *argv[]) +{ + int i, ret; + + if (argc < 2) + { + help_func(0, NULL); + return 1; + } + + xch = xc_interface_open(0, 0, 0); + if ( !xch ) + { + ERROR("Failed to open an xc handler"); + return 1; + } + + for ( i = 0; i < ARRAY_SIZE(opts); i++ ) + { + if ( !strncmp(opts[i].name, argv[1], strlen(argv[1])) ) + break; + } + + if ( i == ARRAY_SIZE(opts) ) + { + fprintf(stderr, "Unknown option '%s'", argv[1]); + help_func(0, NULL); + return 1; + } + + ret = opts[i].func(argc - 2, argv + 2); + + xc_interface_close(xch); + + return !!ret; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c index 104655d5f1..e5facb84f5 100644 --- a/tools/xenstat/libxenstat/src/xenstat.c +++ b/tools/xenstat/libxenstat/src/xenstat.c @@ -208,15 +208,15 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags) node->num_domains, DOMAIN_CHUNK_SIZE, domaininfo); + if (new_domains < 0) + goto err; tmp = realloc(node->domains, (node->num_domains + new_domains) * sizeof(xenstat_domain)); - if (tmp == NULL) { - free(node->domains); - free(node); - return NULL; - } + if (tmp == NULL) + goto err; + node->domains = tmp; domain = node->domains + node->num_domains; @@ -280,6 +280,10 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags) } return node; +err: + free(node->domains); + free(node); + return NULL; } void xenstat_free_node(xenstat_node * node) diff --git a/tools/xenstore/xenstored_linux.c b/tools/xenstore/xenstored_linux.c index 5460ca5573..cf40213b3b 100644 --- a/tools/xenstore/xenstored_linux.c +++ b/tools/xenstore/xenstored_linux.c @@ -32,7 +32,7 @@ evtchn_port_t xenbus_evtchn(void) if (fd == -1) return -1; - rc = read(fd, str, sizeof(str)); + rc = read(fd, str, sizeof(str) - 1); if (rc == -1) { int err = errno; diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 060e480005..1214185bd8 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -771,12 +771,9 @@ static void dump_ctx(int vcpu) } ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4; } else { - struct xen_domctl domctl; - memset(&domctl, 0, sizeof domctl); - domctl.domain = xenctx.domid; - domctl.cmd = XEN_DOMCTL_get_address_size; - if (xc_domctl(xenctx.xc_handle, &domctl) == 0) - ctxt_word_size = guest_word_size = domctl.u.address_size.size / 8; + unsigned int gw; + if ( !xc_domain_get_guest_width(xenctx.xc_handle, xenctx.domid, &gw) ) + ctxt_word_size = guest_word_size = gw; } } #endif |