[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Save/restore: save HVM GPRs and DRs with the rest of the CPU state
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |