[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4] x86/vmx: save guest non-register state in hvm_hw_cpu
During VM forking and resetting a failed vmentry has been observed due to the guest non-register state going out-of-sync with the guest register state. For example, a VM fork reset right after a STI instruction can trigger the failed entry. This is due to the guest non-register state not being saved from the parent VM, thus the reset operation only copies the register state. Fix this by including the guest non-register state in hvm_hw_cpu so that when its copied from the parent VM the vCPU state remains in sync. SVM is not currently wired-in as VM forking is VMX only and saving non-register state during normal save/restore/migration operation hasn't been needed. If deemed necessary in the future it can be wired in by adding a svm-substructure to hvm_hw_cpu. Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> --- v4: Correct setting and checking new flag value in hvm.c v3: Add XEN_X86_VMX flag and vmx-substructure in hvm_hw_cpu v2: Include all CPU non-register state and fold the ops into vmx_vmcs_save & vmx_vmcs_restore. Note: no sanity checking is performed on the fields to reduce the cycles during fuzzing. --- xen/arch/x86/hvm/hvm.c | 4 ++-- xen/arch/x86/hvm/vmx/vmx.c | 17 ++++++++++++++++- xen/include/public/arch-x86/hvm/save.h | 13 +++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 709a4191ef..c502d0851e 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -894,7 +894,7 @@ static int cf_check hvm_save_cpu_ctxt(struct vcpu *v, hvm_domain_context_t *h) if ( v->fpu_initialised ) { memcpy(ctxt.fpu_regs, v->arch.fpu_ctxt, sizeof(ctxt.fpu_regs)); - ctxt.flags = XEN_X86_FPU_INITIALISED; + ctxt.flags |= XEN_X86_FPU_INITIALISED; } return hvm_save_entry(CPU, v->vcpu_id, h, &ctxt); @@ -1025,7 +1025,7 @@ static int cf_check hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) return -EINVAL; } - if ( (ctxt.flags & ~XEN_X86_FPU_INITIALISED) != 0 ) + if ( (ctxt.flags & ~(XEN_X86_FPU_INITIALISED | XEN_X86_VMX)) != 0 ) { gprintk(XENLOG_ERR, "bad flags value in CPU context: %#x\n", ctxt.flags); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c075370f64..6da3842d6e 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -713,7 +713,7 @@ static void vmx_restore_dr(struct vcpu *v) static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) { - unsigned long ev; + unsigned long ev, activity_state, intr_info; vmx_vmcs_enter(v); @@ -721,6 +721,10 @@ static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) __vmread(GUEST_SYSENTER_ESP, &c->sysenter_esp); __vmread(GUEST_SYSENTER_EIP, &c->sysenter_eip); + __vmread(GUEST_ACTIVITY_STATE, &activity_state); + __vmread(GUEST_INTERRUPTIBILITY_INFO, &intr_info); + __vmread(GUEST_PENDING_DBG_EXCEPTIONS, &c->vmx.pending_dbg); + __vmread(VM_ENTRY_INTR_INFO, &ev); if ( (ev & INTR_INFO_VALID_MASK) && hvm_event_needs_reinjection(MASK_EXTR(ev, INTR_INFO_INTR_TYPE_MASK), @@ -732,6 +736,10 @@ static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) } vmx_vmcs_exit(v); + + c->vmx.activity_state = activity_state; + c->vmx.interruptibility_info = intr_info; + c->flags |= XEN_X86_VMX; } static int vmx_restore_cr0_cr3( @@ -807,6 +815,13 @@ static int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) __vmwrite(GUEST_DR7, c->dr7); + if ( c->flags & XEN_X86_VMX ) + { + __vmwrite(GUEST_ACTIVITY_STATE, c->vmx.activity_state); + __vmwrite(GUEST_INTERRUPTIBILITY_INFO, c->vmx.interruptibility_info); + __vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, c->vmx.pending_dbg); + } + if ( c->pending_valid && hvm_event_needs_reinjection(c->pending_type, c->pending_vector) ) { diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h index 773a380bc2..0f728aa5d9 100644 --- a/xen/include/public/arch-x86/hvm/save.h +++ b/xen/include/public/arch-x86/hvm/save.h @@ -52,6 +52,7 @@ DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); * Compat: * - Pre-3.4 didn't have msr_tsc_aux * - Pre-4.7 didn't have fpu_initialised + * - Pre-4.17 didn't have non-register state */ struct hvm_hw_cpu { @@ -163,9 +164,21 @@ struct hvm_hw_cpu { uint32_t error_code; #define _XEN_X86_FPU_INITIALISED 0 +#define _XEN_X86_VMX 1 #define XEN_X86_FPU_INITIALISED (1U<<_XEN_X86_FPU_INITIALISED) +#define XEN_X86_VMX (1U<<_XEN_X86_VMX) uint32_t flags; uint32_t pad0; + + /* non-register state */ + union { + /* if flags & XEN_X86_VMX */ + struct { + uint32_t activity_state; + uint32_t interruptibility_info; + uint64_t pending_dbg; + } vmx; + }; }; struct hvm_hw_cpu_compat { -- 2.25.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |