diff options
author | Keir Fraser <keir@xen.org> | 2010-11-08 15:44:02 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-11-08 15:44:02 +0000 |
commit | 47a3fb9662188c9e2f02a8a428e5cc72ce3f451a (patch) | |
tree | 00d8ee313ffbbb361ef58cde403255598e5dea56 /tools/libxc/xc_domain_save.c | |
parent | 59e3eeb9ef559fa0db5efe69196aa78ee0c5bbea (diff) | |
download | xen-47a3fb9662188c9e2f02a8a428e5cc72ce3f451a.tar.gz xen-47a3fb9662188c9e2f02a8a428e5cc72ce3f451a.tar.bz2 xen-47a3fb9662188c9e2f02a8a428e5cc72ce3f451a.zip |
x86: xsave save/restore support for both PV and HVM guests (version 2)
I have tested the patch in the following senarios:
1> Non-xsave platform
2> Xsave-capable platform, guest does not support xsave, xen support xsave
3> Xsave-capable platform, guest does support xsave, xen supports xsave
4> Guest (non-xsave) saved on platform without xsave, restored on a
Xsave-capable system.
All passed.
Signed-off-by: Shan Haitao <haitao.shan@intel.com>
Signed-off-by: Han Weidong <weidong.han@intel.com>
Diffstat (limited to 'tools/libxc/xc_domain_save.c')
-rw-r--r-- | tools/libxc/xc_domain_save.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index 1f3022cd43..27b38a6239 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -810,14 +810,39 @@ static xen_pfn_t *map_and_save_p2m_table(xc_interface *xch, ? sizeof(ctxt.x64) : sizeof(ctxt.x32)); uint32_t chunk2_sz = 0; - uint32_t tot_sz = (chunk1_sz + 8) + (chunk2_sz + 8); + uint32_t chunk3_sz = 4; + uint32_t xcnt_size = 0; + uint32_t tot_sz; + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_getvcpuextstate; + domctl.domain = dom; + domctl.u.vcpuextstate.vcpu = 0; + domctl.u.vcpuextstate.size = 0; + domctl.u.vcpuextstate.xfeature_mask = 0; + if ( xc_domctl(xch, &domctl) < 0 ) + { + PERROR("No extended context for VCPU%d", i); + goto out; + } + xcnt_size = domctl.u.vcpuextstate.size + 2 * sizeof(uint64_t); + + tot_sz = (chunk1_sz + 8) + (chunk2_sz + 8); + if ( domctl.u.vcpuextstate.xfeature_mask ) + tot_sz += chunk3_sz + 8; + if ( write_exact(io_fd, &signature, sizeof(signature)) || write_exact(io_fd, &tot_sz, sizeof(tot_sz)) || write_exact(io_fd, "vcpu", 4) || write_exact(io_fd, &chunk1_sz, sizeof(chunk1_sz)) || write_exact(io_fd, &ctxt, chunk1_sz) || write_exact(io_fd, "extv", 4) || - write_exact(io_fd, &chunk2_sz, sizeof(chunk2_sz)) ) + write_exact(io_fd, &chunk2_sz, sizeof(chunk2_sz)) || + (domctl.u.vcpuextstate.xfeature_mask) ? + (write_exact(io_fd, "xcnt", 4) || + write_exact(io_fd, &chunk3_sz, sizeof(chunk3_sz)) || + write_exact(io_fd, &xcnt_size, 4)) : + 0 ) { PERROR("write: extended info"); goto out; @@ -905,6 +930,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter /* base of the region in which domain memory is mapped */ unsigned char *region_base = NULL; + /* A copy of the CPU eXtended States of the guest. */ + DECLARE_HYPERCALL_BUFFER(void, buffer); + /* bitmap of pages: - that should be sent this iteration (unless later marked as skip); - to skip this iteration because already dirty; @@ -1786,6 +1814,50 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter PERROR("Error when writing to state file (2)"); goto out; } + + /* Start to fetch CPU eXtended States */ + /* Get buffer size first */ + domctl.cmd = XEN_DOMCTL_getvcpuextstate; + domctl.domain = dom; + domctl.u.vcpuextstate.vcpu = i; + domctl.u.vcpuextstate.xfeature_mask = 0; + domctl.u.vcpuextstate.size = 0; + if ( xc_domctl(xch, &domctl) < 0 ) + { + PERROR("No eXtended states (XSAVE) for VCPU%d", i); + goto out; + } + + if ( !domctl.u.vcpuextstate.xfeature_mask ) + continue; + + /* Getting eXtended states data */ + buffer = xc_hypercall_buffer_alloc(xch, buffer, domctl.u.vcpuextstate.size); + if ( !buffer ) + { + PERROR("Insufficient memory for getting eXtended states for" + "VCPU%d", i); + goto out; + } + set_xen_guest_handle(domctl.u.vcpuextstate.buffer, buffer); + if ( xc_domctl(xch, &domctl) < 0 ) + { + PERROR("No eXtended states (XSAVE) for VCPU%d", i); + xc_hypercall_buffer_free(xch, buffer); + goto out; + } + + if ( wrexact(io_fd, &domctl.u.vcpuextstate.xfeature_mask, + sizeof(domctl.u.vcpuextstate.xfeature_mask)) || + wrexact(io_fd, &domctl.u.vcpuextstate.size, + sizeof(domctl.u.vcpuextstate.size)) || + wrexact(io_fd, buffer, domctl.u.vcpuextstate.size) ) + { + PERROR("Error when writing to state file VCPU extended state"); + xc_hypercall_buffer_free(xch, buffer); + goto out; + } + xc_hypercall_buffer_free(xch, buffer); } /* |