This commit is contained in:
Jan Beulich committed 2013-09-13 14:28:46 +02:00
commit c71a3e6d83
32 files changed
+788 -292

No files matched your search

+5 -4
View File
@@ -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/*
+14
View File
@@ -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
+30
View File
@@ -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
+4 -2
View File
@@ -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);
+5 -2
View File
@@ -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;
}
-1
View File
@@ -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);
}
+1 -19
View File
@@ -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;
+3 -5
View File
@@ -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));
+12 -19
View File
@@ -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;
+3 -10
View File
@@ -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:
+143 -6
View File
@@ -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,
+4 -9
View File
@@ -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);
+30 -162
View File
@@ -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;
}
+3 -5
View File
@@ -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;
+3 -5
View File
@@ -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,
+4 -17
View File
@@ -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");
+13
View File
@@ -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
+17
View File
@@ -275,6 +275,23 @@ int xc_query_page_offline_status(xc_interface *xch, unsigned long start,
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
+9
View File
@@ -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))
+1 -8
View File
@@ -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) )
+9 -2
View File
@@ -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);
+11
View File
@@ -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. */
+3
View File
@@ -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);
+10
View File
@@ -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) {
+1 -1
View File
@@ -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
+2
View File
@@ -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", [
+5 -1
View File
@@ -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;
+5 -2
View File
@@ -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)
+425
View File
@@ -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:
*/
+9 -5
View File
@@ -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)
+1 -1
View File
@@ -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;
+3 -6
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.