# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1176386523 -3600
# Node ID 1fa9b5f1df8fe0f6cf910c2bc6360fc12df779c6
# Parent a839e331f06f7b19ca601b277de9fcbedbeb4a77
[HVM] Save/restore: save HVM GPRs and DRs with the rest of the CPU state
and remove the use of xc_vcpu_getcontext() from HVM save/restore.
Also fixes loss of CR2, DR6 and DR7 contents across HVM save/restore.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
tools/libxc/xc_domain_restore.c | 20 ----------
tools/libxc/xc_domain_save.c | 64 +++++++++++----------------------
xen/arch/x86/hvm/hvm.c | 76 +++++++++++++++++++++++++++++++++++++++-
xen/arch/x86/hvm/svm/svm.c | 19 ++++++----
xen/arch/x86/hvm/vmx/vmx.c | 21 ++++++-----
xen/include/public/hvm/save.h | 35 ++++++++++++++++--
6 files changed, 153 insertions(+), 82 deletions(-)
diff -r a839e331f06f -r 1fa9b5f1df8f tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c Thu Apr 12 14:13:04 2007 +0100
+++ b/tools/libxc/xc_domain_restore.c Thu Apr 12 15:02:03 2007 +0100
@@ -696,26 +696,6 @@ int xc_domain_restore(int xc_handle, int
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
*store_mfn = magic_pfns[2];
- /* Read vcpu contexts */
- for ( i = 0; i <= max_vcpu_id; i++ )
- {
- if ( !(vcpumap & (1ULL << i)) )
- continue;
-
- if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) )
- {
- ERROR("error read vcpu context.\n");
- goto out;
- }
-
- if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) )
- {
- ERROR("Could not set vcpu context, rc=%d", rc);
- goto out;
- }
- rc = 1;
- }
-
/* Read HVM context */
if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) )
{
diff -r a839e331f06f -r 1fa9b5f1df8f tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c Thu Apr 12 14:13:04 2007 +0100
+++ b/tools/libxc/xc_domain_save.c Thu Apr 12 15:02:03 2007 +0100
@@ -378,8 +378,7 @@ static int analysis_phase(int xc_handle,
static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
- int dom, xc_dominfo_t *info,
- vcpu_guest_context_t *ctxt)
+ int dom, xc_dominfo_t *info)
{
int i = 0;
@@ -396,10 +395,6 @@ static int suspend_and_state(int (*suspe
ERROR("Could not get domain info");
return -1;
}
-
- if ( xc_vcpu_getcontext(xc_handle, dom, 0, ctxt) )
- ERROR("Could not get vcpu context");
-
if ( info->dying )
{
@@ -663,10 +658,11 @@ static xen_pfn_t *map_and_save_p2m_table
static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
int io_fd,
uint32_t dom,
- vcpu_guest_context_t *ctxt,
unsigned long p2m_size,
shared_info_t *live_shinfo)
{
+ vcpu_guest_context_t ctxt;
+
/* Double and single indirect references to the live P2M table */
xen_pfn_t *live_p2m_frame_list_list = NULL;
xen_pfn_t *live_p2m_frame_list = NULL;
@@ -728,6 +724,12 @@ static xen_pfn_t *map_and_save_p2m_table
(uint64_t)p2m_frame_list[i/fpp]);
goto out;
}
+ }
+
+ if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
+ {
+ ERROR("Could not get vcpu context");
+ goto out;
}
/*
@@ -736,7 +738,7 @@ static xen_pfn_t *map_and_save_p2m_table
* slow paths in the restore code.
*/
if ( (pt_levels == 3) &&
- (ctxt->vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) )
+ (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) )
{
unsigned long signature = ~0UL;
uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8;
@@ -746,7 +748,7 @@ static xen_pfn_t *map_and_save_p2m_table
!write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
!write_exact(io_fd, &chunk_sig, 4) ||
!write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) ||
- !write_exact(io_fd, ctxt, sizeof(*ctxt)) )
+ !write_exact(io_fd, &ctxt, sizeof(ctxt)) )
{
ERROR("write: extended info");
goto out;
@@ -853,11 +855,6 @@ int xc_domain_save(int xc_handle, int io
return 1;
}
- if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
- {
- ERROR("Could not get vcpu context");
- goto out;
- }
shared_info_frame = info.shared_info_frame;
/* Map the shared info frame */
@@ -900,7 +897,7 @@ int xc_domain_save(int xc_handle, int io
else
{
/* This is a non-live suspend. Suspend the domain .*/
- if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) )
+ if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) )
{
ERROR("Domain appears not to have suspended");
goto out;
@@ -999,7 +996,7 @@ int xc_domain_save(int xc_handle, int io
/* Map the P2M table, and write the list of P2M frames */
live_p2m = map_and_save_p2m_table(xc_handle, io_fd, dom,
- &ctxt, p2m_size, live_shinfo);
+ p2m_size, live_shinfo);
if ( live_p2m == NULL )
{
ERROR("Failed to map/save the p2m frame list");
@@ -1304,17 +1301,13 @@ int xc_domain_save(int xc_handle, int io
DPRINTF("Start last iteration\n");
last_iter = 1;
- if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
- &ctxt) )
+ if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) )
{
ERROR("Domain appears not to have suspended");
goto out;
}
- DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
- info.shared_info_frame,
- (unsigned long)ctxt.user_regs.eip,
- (unsigned long)ctxt.user_regs.edx);
+ DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame);
}
if ( xc_shadow_control(xc_handle, dom,
@@ -1410,27 +1403,6 @@ int xc_domain_save(int xc_handle, int io
goto out;
}
- /* Save vcpu contexts */
-
- for ( i = 0; i <= info.max_vcpu_id; i++ )
- {
- if ( !(vcpumap & (1ULL << i)) )
- continue;
-
- if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) )
- {
- ERROR("HVM:Could not get vcpu context");
- goto out;
- }
-
- DPRINTF("write vcpu %d context.\n", i);
- if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) )
- {
- ERROR("write vcpu context failed!\n");
- goto out;
- }
- }
-
/* Get HVM context from Xen and save it too */
if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf,
hvm_buf_size)) == -1 )
@@ -1492,6 +1464,12 @@ int xc_domain_save(int xc_handle, int io
j = 0;
}
}
+ }
+
+ if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
+ {
+ ERROR("Could not get vcpu context");
+ goto out;
}
/* Canonicalise the suspend-record frame number. */
diff -r a839e331f06f -r 1fa9b5f1df8f xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Thu Apr 12 14:13:04 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c Thu Apr 12 15:02:03 2007 +0100
@@ -191,6 +191,7 @@ static int hvm_save_cpu_ctxt(struct doma
{
struct vcpu *v;
struct hvm_hw_cpu ctxt;
+ struct vcpu_guest_context *vc;
for_each_vcpu(d, v)
{
@@ -199,7 +200,40 @@ static int hvm_save_cpu_ctxt(struct doma
if ( test_bit(_VPF_down, &v->pause_flags) )
continue;
+ /* Architecture-specific vmcs/vmcb bits */
hvm_funcs.save_cpu_ctxt(v, &ctxt);
+
+ /* Other vcpu register state */
+ vc = &v->arch.guest_context;
+ if ( vc->flags & VGCF_i387_valid )
+ memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs));
+ else
+ memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs));
+ ctxt.rax = vc->user_regs.eax;
+ ctxt.rbx = vc->user_regs.ebx;
+ ctxt.rcx = vc->user_regs.ecx;
+ ctxt.rdx = vc->user_regs.edx;
+ ctxt.rbp = vc->user_regs.ebp;
+ ctxt.rsi = vc->user_regs.esi;
+ ctxt.rdi = vc->user_regs.edi;
+ /* %rsp handled by arch-specific call above */
+#ifdef __x86_64__
+ ctxt.r8 = vc->user_regs.r8;
+ ctxt.r9 = vc->user_regs.r9;
+ ctxt.r10 = vc->user_regs.r10;
+ ctxt.r11 = vc->user_regs.r11;
+ ctxt.r12 = vc->user_regs.r12;
+ ctxt.r13 = vc->user_regs.r13;
+ ctxt.r14 = vc->user_regs.r14;
+ ctxt.r15 = vc->user_regs.r15;
+#endif
+ ctxt.dr0 = vc->debugreg[0];
+ ctxt.dr1 = vc->debugreg[1];
+ ctxt.dr2 = vc->debugreg[2];
+ ctxt.dr3 = vc->debugreg[3];
+ ctxt.dr6 = vc->debugreg[6];
+ ctxt.dr7 = vc->debugreg[7];
+
if ( hvm_save_entry(CPU, v->vcpu_id, h, &ctxt) != 0 )
return 1;
}
@@ -208,9 +242,10 @@ static int hvm_save_cpu_ctxt(struct doma
static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
{
- int vcpuid;
+ int vcpuid, rc;
struct vcpu *v;
struct hvm_hw_cpu ctxt;
+ struct vcpu_guest_context *vc;
/* Which vcpu is this? */
vcpuid = hvm_load_instance(h);
@@ -219,12 +254,51 @@ static int hvm_load_cpu_ctxt(struct doma
gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid);
return -EINVAL;
}
+ vc = &v->arch.guest_context;
+
+ /* Need to init this vcpu before loading its contents */
+ LOCK_BIGLOCK(d);
+ if ( !v->is_initialised )
+ if ( (rc = boot_vcpu(d, vcpuid, vc)) != 0 )
+ return rc;
+ UNLOCK_BIGLOCK(d);
if ( hvm_load_entry(CPU, h, &ctxt) != 0 )
return -EINVAL;
+ /* Architecture-specific vmcs/vmcb bits */
if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
return -EINVAL;
+
+ /* Other vcpu register state */
+ memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
+ vc->user_regs.eax = ctxt.rax;
+ vc->user_regs.ebx = ctxt.rbx;
+ vc->user_regs.ecx = ctxt.rcx;
+ vc->user_regs.edx = ctxt.rdx;
+ vc->user_regs.ebp = ctxt.rbp;
+ vc->user_regs.esi = ctxt.rsi;
+ vc->user_regs.edi = ctxt.rdi;
+ vc->user_regs.esp = ctxt.rsp;
+#ifdef __x86_64__
+ vc->user_regs.r8; = ctxt.r8;
+ vc->user_regs.r9; = ctxt.r9;
+ vc->user_regs.r10 = ctxt.r10;
+ vc->user_regs.r11 = ctxt.r11;
+ vc->user_regs.r12 = ctxt.r12;
+ vc->user_regs.r13 = ctxt.r13;
+ vc->user_regs.r14 = ctxt.r14;
+ vc->user_regs.r15 = ctxt.r15;
+#endif
+ vc->debugreg[0] = ctxt.dr0;
+ vc->debugreg[1] = ctxt.dr1;
+ vc->debugreg[2] = ctxt.dr2;
+ vc->debugreg[3] = ctxt.dr3;
+ vc->debugreg[6] = ctxt.dr6;
+ vc->debugreg[7] = ctxt.dr7;
+
+ vc->flags = VGCF_i387_valid | VGCF_online;
+ v->fpu_initialised = 1;
/* Auxiliary processors should be woken immediately. */
if ( test_and_clear_bit(_VPF_down, &v->pause_flags) )
diff -r a839e331f06f -r 1fa9b5f1df8f xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Thu Apr 12 14:13:04 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c Thu Apr 12 15:02:03 2007 +0100
@@ -233,7 +233,7 @@ int svm_vmcb_save(struct vcpu *v, struct
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- c->eip = vmcb->rip;
+ c->rip = vmcb->rip;
#ifdef HVM_DEBUG_SUSPEND
printk("%s: eip=0x%"PRIx64".\n",
@@ -241,10 +241,11 @@ int svm_vmcb_save(struct vcpu *v, struct
inst_len, c->eip);
#endif
- c->esp = vmcb->rsp;
- c->eflags = vmcb->rflags;
+ c->rsp = vmcb->rsp;
+ c->rflags = vmcb->rflags;
c->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+ c->cr2 = v->arch.hvm_svm.cpu_cr2;
c->cr3 = v->arch.hvm_svm.cpu_cr3;
c->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
@@ -315,14 +316,16 @@ int svm_vmcb_restore(struct vcpu *v, str
unsigned long mfn, old_base_mfn;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- vmcb->rip = c->eip;
- vmcb->rsp = c->esp;
- vmcb->rflags = c->eflags;
+ vmcb->rip = c->rip;
+ vmcb->rsp = c->rsp;
+ vmcb->rflags = c->rflags;
v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0;
vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET;
if ( !paging_mode_hap(v->domain) )
vmcb->cr0 |= X86_CR0_PG;
+
+ v->arch.hvm_svm.cpu_cr2 = c->cr2;
#ifdef HVM_DEBUG_SUSPEND
printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
@@ -421,6 +424,9 @@ int svm_vmcb_restore(struct vcpu *v, str
vmcb->sysenter_esp = c->sysenter_esp;
vmcb->sysenter_eip = c->sysenter_eip;
+ vmcb->dr6 = c->dr6;
+ vmcb->dr7 = c->dr7;
+
paging_update_paging_modes(v);
return 0;
@@ -440,6 +446,7 @@ void svm_save_cpu_state(struct vcpu *v,
data->msr_cstar = vmcb->cstar;
data->msr_syscall_mask = vmcb->sfmask;
data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer;
+ data->msr_flags = -1ULL;
data->tsc = hvm_get_guest_time(v);
}
diff -r a839e331f06f -r 1fa9b5f1df8f xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Thu Apr 12 14:13:04 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Apr 12 15:02:03 2007 +0100
@@ -370,11 +370,12 @@ static inline void __restore_debug_regis
int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
{
- c->eip = __vmread(GUEST_RIP);
- c->esp = __vmread(GUEST_RSP);
- c->eflags = __vmread(GUEST_RFLAGS);
+ c->rip = __vmread(GUEST_RIP);
+ c->rsp = __vmread(GUEST_RSP);
+ c->rflags = __vmread(GUEST_RFLAGS);
c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0;
+ c->cr2 = v->arch.hvm_vmx.cpu_cr2;
c->cr3 = v->arch.hvm_vmx.cpu_cr3;
c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4;
@@ -444,12 +445,14 @@ int vmx_vmcs_restore(struct vcpu *v, str
vmx_vmcs_enter(v);
- __vmwrite(GUEST_RIP, c->eip);
- __vmwrite(GUEST_RSP, c->esp);
- __vmwrite(GUEST_RFLAGS, c->eflags);
+ __vmwrite(GUEST_RIP, c->rip);
+ __vmwrite(GUEST_RSP, c->rsp);
+ __vmwrite(GUEST_RFLAGS, c->rflags);
v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0;
__vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0);
+
+ v->arch.hvm_vmx.cpu_cr2 = c->cr2;
#ifdef HVM_DEBUG_SUSPEND
printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64",
cr4=0x%"PRIx64".\n",
@@ -555,6 +558,8 @@ int vmx_vmcs_restore(struct vcpu *v, str
__vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp);
__vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip);
+ __vmwrite(GUEST_DR7, c->dr7);
+
vmx_vmcs_exit(v);
paging_update_paging_modes(v);
@@ -590,7 +595,7 @@ void vmx_save_cpu_state(struct vcpu *v,
data->shadow_gs = guest_state->shadow_gs;
/* save msrs */
- data->flags = guest_flags;
+ data->msr_flags = guest_flags;
data->msr_lstar = guest_state->msrs[VMX_INDEX_MSR_LSTAR];
data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR];
data->msr_cstar = guest_state->msrs[VMX_INDEX_MSR_CSTAR];
@@ -607,7 +612,7 @@ void vmx_load_cpu_state(struct vcpu *v,
struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
/* restore msrs */
- guest_state->flags = data->flags;
+ guest_state->flags = data->msr_flags;
guest_state->msrs[VMX_INDEX_MSR_LSTAR] = data->msr_lstar;
guest_state->msrs[VMX_INDEX_MSR_STAR] = data->msr_star;
guest_state->msrs[VMX_INDEX_MSR_CSTAR] = data->msr_cstar;
diff -r a839e331f06f -r 1fa9b5f1df8f xen/include/public/hvm/save.h
--- a/xen/include/public/hvm/save.h Thu Apr 12 14:13:04 2007 +0100
+++ b/xen/include/public/hvm/save.h Thu Apr 12 15:02:03 2007 +0100
@@ -87,12 +87,39 @@ DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct
*/
struct hvm_hw_cpu {
- uint64_t eip;
- uint64_t esp;
- uint64_t eflags;
+ uint8_t fpu_regs[512];
+
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t rsp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ uint64_t rip;
+ uint64_t rflags;
+
uint64_t cr0;
+ uint64_t cr2;
uint64_t cr3;
uint64_t cr4;
+
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr6;
+ uint64_t dr7;
uint32_t cs_sel;
uint32_t ds_sel;
@@ -142,9 +169,9 @@ struct hvm_hw_cpu {
/* msr for em64t */
uint64_t shadow_gs;
- uint64_t flags;
/* msr content saved/restored. */
+ uint64_t msr_flags;
uint64_t msr_lstar;
uint64_t msr_star;
uint64_t msr_cstar;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|