aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_resume.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-11-04 22:32:01 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-11-04 22:32:01 +0000
commit397ade9be366651e55d3e3aee419cb8160790699 (patch)
treee29f052de5533b5847dc2d290efb05f7e589c20f /tools/libxc/xc_resume.c
parente71172174bdf02a34d9f0f768a23439a531cb18c (diff)
downloadxen-397ade9be366651e55d3e3aee419cb8160790699.tar.gz
xen-397ade9be366651e55d3e3aee419cb8160790699.tar.bz2
xen-397ade9be366651e55d3e3aee419cb8160790699.zip
xc_resume: fix modify_returncode when host width != guest width
Also improve checking in xc_domain_resume_any(). Signed-off-by: Brendan Cully <brendan@cs.ubc.ca> Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'tools/libxc/xc_resume.c')
-rw-r--r--tools/libxc/xc_resume.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index 73c2904053..ad0f137b0d 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -8,15 +8,25 @@
#include <xen/foreign/x86_64.h>
#include <xen/hvm/params.h>
-/* Don't yet support cross-address-size uncooperative resume */
-#define guest_width (sizeof (unsigned long))
+static int pv_guest_width(int xc_handle, uint32_t domid)
+{
+ DECLARE_DOMCTL;
+ domctl.domain = domid;
+ domctl.cmd = XEN_DOMCTL_get_address_size;
+ if ( xc_domctl(xc_handle, &domctl) != 0 )
+ {
+ PERROR("Could not get guest address size");
+ return -1;
+ }
+ return domctl.u.address_size.size / 8;
+}
static int modify_returncode(int xc_handle, uint32_t domid)
{
vcpu_guest_context_any_t ctxt;
xc_dominfo_t info;
xen_capabilities_info_t caps;
- int rc;
+ int rc, guest_width;
if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
{
@@ -24,30 +34,34 @@ static int modify_returncode(int xc_handle, uint32_t domid)
return -1;
}
- /* HVM guests without PV drivers do not have a return code to modify. */
if ( info.hvm )
{
+ /* HVM guests without PV drivers have no return code to modify. */
unsigned long irq = 0;
xc_get_hvm_param(xc_handle, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
if ( !irq )
return 0;
- }
- if ( xc_version(xc_handle, XENVER_capabilities, &caps) != 0 )
+ /* HVM guests have host address width. */
+ if ( xc_version(xc_handle, XENVER_capabilities, &caps) != 0 )
+ {
+ PERROR("Could not get Xen capabilities\n");
+ return -1;
+ }
+ guest_width = strstr(caps, "x86_64") ? 8 : 4;
+ }
+ else
{
- PERROR("Could not get Xen capabilities\n");
- return -1;
+ /* Probe PV guest address width. */
+ guest_width = pv_guest_width(xc_handle, domid);
+ if ( guest_width < 0 )
+ return -1;
}
if ( (rc = xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt)) != 0 )
return rc;
- if ( !info.hvm )
- ctxt.c.user_regs.eax = 1;
- else if ( strstr(caps, "x86_64") )
- ctxt.x64.user_regs.eax = 1;
- else
- ctxt.x32.user_regs.eax = 1;
+ SET_FIELD(&ctxt, user_regs.eax, 1);
if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt)) != 0 )
return rc;
@@ -88,6 +102,7 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid)
xc_dominfo_t info;
int i, rc = -1;
#if defined(__i386__) || defined(__x86_64__)
+ int guest_width;
unsigned long mfn, p2m_size = 0;
vcpu_guest_context_any_t ctxt;
start_info_t *start_info;
@@ -113,6 +128,13 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid)
return rc;
}
+ guest_width = pv_guest_width(xc_handle, domid);
+ if ( guest_width != sizeof(long) )
+ {
+ ERROR("Cannot resume uncooperative cross-address-size guests");
+ return rc;
+ }
+
/* Map the shared info frame */
shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
PROT_READ, info.shared_info_frame);
@@ -167,7 +189,7 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid)
goto out;
}
- mfn = ctxt.c.user_regs.edx;
+ mfn = GET_FIELD(&ctxt, user_regs.edx);
start_info = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
PROT_READ | PROT_WRITE, mfn);