aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-09-13 14:28:46 +0200
committerJan Beulich <jbeulich@suse.com>2013-09-13 14:28:46 +0200
commitc71a3e6d83fb6d03eeae8df08eafd4ea02d9e278 (patch)
tree0004587285d811993caeb1cc6d99e3934ffbbcff
parenta54dc5f4fe1eae6b1beb21326ef0338cd3969cd1 (diff)
parent255d252c0afafd0d2b6a9e4c2ad4dadbd2f00051 (diff)
downloadxen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.tar.gz
xen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.tar.bz2
xen-c71a3e6d83fb6d03eeae8df08eafd4ea02d9e278.zip
Merge.
-rw-r--r--.gitignore9
-rw-r--r--docs/man/xl.cfg.pod.514
-rw-r--r--docs/misc/arm/booting.txt30
-rw-r--r--extras/mini-os/console/xenbus.c6
-rw-r--r--extras/mini-os/lib/xs.c7
-rw-r--r--tools/debugger/kdd/kdd-xen.c1
-rw-r--r--tools/libxc/xc_core.c20
-rw-r--r--tools/libxc/xc_cpuid_x86.c8
-rw-r--r--tools/libxc/xc_dom_boot.c31
-rw-r--r--tools/libxc/xc_dom_x86.c13
-rw-r--r--tools/libxc/xc_domain.c149
-rw-r--r--tools/libxc/xc_domain_restore.c13
-rw-r--r--tools/libxc/xc_offline_page.c192
-rw-r--r--tools/libxc/xc_pagetab.c8
-rw-r--r--tools/libxc/xc_private.c8
-rw-r--r--tools/libxc/xc_resume.c21
-rw-r--r--tools/libxc/xenctrl.h13
-rw-r--r--tools/libxc/xenguest.h17
-rw-r--r--tools/libxc/xg_private.h9
-rw-r--r--tools/libxc/xg_save_restore.h9
-rw-r--r--tools/libxl/libxl.c11
-rw-r--r--tools/libxl/libxl.h11
-rw-r--r--tools/libxl/libxl_create.c3
-rw-r--r--tools/libxl/libxl_dm.c10
-rw-r--r--tools/libxl/libxl_exec.c2
-rw-r--r--tools/libxl/libxl_types.idl2
-rw-r--r--tools/libxl/xl_cmdimpl.c6
-rw-r--r--tools/misc/Makefile7
-rw-r--r--tools/misc/xen-mfndump.c425
-rw-r--r--tools/xenstat/libxenstat/src/xenstat.c14
-rw-r--r--tools/xenstore/xenstored_linux.c2
-rw-r--r--tools/xentrace/xenctx.c9
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