diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-11-04 22:32:01 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-11-04 22:32:01 +0000 |
commit | 397ade9be366651e55d3e3aee419cb8160790699 (patch) | |
tree | e29f052de5533b5847dc2d290efb05f7e589c20f /tools/libxc/xc_resume.c | |
parent | e71172174bdf02a34d9f0f768a23439a531cb18c (diff) | |
download | xen-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.c | 52 |
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); |