From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH] x86/HVM: prevent infinite VM entry retries Date: Thu, 27 Nov 2014 12:39:59 +0000 Message-ID: <547729AF020000780004B2A7@mail.emea.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartDFEAF18F.1__=" Return-path: Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XtyMb-0005aQ-KZ for xen-devel@lists.xenproject.org; Thu, 27 Nov 2014 12:40:01 +0000 List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel Cc: Andrew Cooper , Tim Deegan , Keir Fraser List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartDFEAF18F.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This reverts the VMX side of commit 28b4baac ("x86/HVM: don't crash guest upon problems occurring in user mode") and gets SVM in line with the resulting VMX behavior. This is because Andrew validly says "A failed vmentry is overwhelmingly likely to be caused by corrupt VMC[SB] state. As a result, injecting a fault and retrying the the vmentry is likely to fail in the same way." Reported-by: Andrew Cooper Signed-off-by: Jan Beulich Signed-off-by: Tim Deegan --- v2: Replace SVM change by what Tim suggested. --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2371,8 +2371,8 @@ void svm_vmexit_handler(struct cpu_user_ goto out; case NESTEDHVM_VMEXIT_FATALERROR: gdprintk(XENLOG_ERR, "unexpected nestedsvm_vmexit() = error\n"); - goto exit_and_crash; - + domain_crash(v->domain); + goto out; default: BUG(); case NESTEDHVM_VMEXIT_ERROR: @@ -2385,18 +2385,21 @@ void svm_vmexit_handler(struct cpu_user_ case NESTEDHVM_VMEXIT_FATALERROR: gdprintk(XENLOG_ERR, "unexpected nestedsvm_check_intercepts() error\n"); - goto exit_and_crash; + domain_crash(v->domain); + goto out; default: gdprintk(XENLOG_INFO, "nestedsvm_check_intercepts() returned = %i\n", nsret); - goto exit_and_crash; + domain_crash(v->domain); + goto out; } } =20 if ( unlikely(exit_reason =3D=3D VMEXIT_INVALID) ) { svm_vmcb_dump(__func__, vmcb); - goto exit_and_crash; + domain_crash(v->domain); + goto out; } =20 perfc_incra(svmexits, exit_reason); @@ -2431,13 +2434,13 @@ void svm_vmexit_handler(struct cpu_user_ =20 case VMEXIT_EXCEPTION_DB: if ( !v->domain->debugger_attached ) - goto exit_and_crash; + goto unexpected_exit_type; domain_pause_for_debugger(); break; =20 case VMEXIT_EXCEPTION_BP: if ( !v->domain->debugger_attached ) - goto exit_and_crash; + goto unexpected_exit_type; /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update = RIP. */ if ( (inst_len =3D __get_instruction_length(v, INSTR_INT3)) = =3D=3D 0 ) break; @@ -2684,7 +2687,7 @@ void svm_vmexit_handler(struct cpu_user_ break; =20 default: - exit_and_crash: + unexpected_exit_type: gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason =3D = %#"PRIx64", " "exitinfo1 =3D %#"PRIx64", exitinfo2 =3D %#"PRIx64"\n", exit_reason,=20 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -134,18 +134,6 @@ static void vmx_vcpu_destroy(struct vcpu passive_domain_destroy(v); } =20 -/* Only crash the guest if the problem originates in kernel mode. */ -static void vmx_crash_or_fault(struct vcpu *v) -{ - struct segment_register ss; - - vmx_get_segment_register(v, x86_seg_ss, &ss); - if ( ss.attr.fields.dpl ) - hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE= ); - else - domain_crash(v->domain); -} - static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state); =20 static const u32 msr_index[] =3D @@ -2520,7 +2508,7 @@ static void vmx_failed_vmentry(unsigned=20 vmcs_dump_vcpu(curr); printk("**************************************\n"); =20 - vmx_crash_or_fault(curr); + domain_crash(curr->domain); } =20 void vmx_enter_realmode(struct cpu_user_regs *regs) @@ -3173,8 +3161,19 @@ void vmx_vmexit_handler(struct cpu_user_ /* fall through */ default: exit_and_crash: - gdprintk(XENLOG_WARNING, "Bad vmexit (reason %#lx)\n", exit_reason= ); - vmx_crash_or_fault(v); + { + struct segment_register ss; + + gdprintk(XENLOG_WARNING, "Bad vmexit (reason %#lx)\n", + exit_reason); + + vmx_get_segment_register(v, x86_seg_ss, &ss); + if ( ss.attr.fields.dpl ) + hvm_inject_hw_exception(TRAP_invalid_op, + HVM_DELIVER_NO_ERROR_CODE); + else + domain_crash(v->domain); + } break; } =20 --=__PartDFEAF18F.1__= Content-Type: text/plain; name="x86-HVM-prevent-infinite-VMentry-loop.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-HVM-prevent-infinite-VMentry-loop.patch" x86/HVM: prevent infinite VM entry retries=0A=0AThis reverts the VMX side = of commit 28b4baac ("x86/HVM: don't crash=0Aguest upon problems occurring = in user mode") and gets SVM in line with=0Athe resulting VMX behavior. = This is because Andrew validly says=0A=0A"A failed vmentry is overwhelmingl= y likely to be caused by corrupt=0A VMC[SB] state. As a result, injecting = a fault and retrying the the=0A vmentry is likely to fail in the same = way."=0A=0AReported-by: Andrew Cooper =0ASigned-= off-by: Jan Beulich =0ASigned-off-by: Tim Deegan = =0A---=0Av2: Replace SVM change by what Tim suggested.=0A=0A--= - a/xen/arch/x86/hvm/svm/svm.c=0A+++ b/xen/arch/x86/hvm/svm/svm.c=0A@@ = -2371,8 +2371,8 @@ void svm_vmexit_handler(struct cpu_user_=0A = goto out;=0A case NESTEDHVM_VMEXIT_FATALERROR:=0A = gdprintk(XENLOG_ERR, "unexpected nestedsvm_vmexit() error\n");=0A- = goto exit_and_crash;=0A-=0A+ domain_crash(v->d= omain);=0A+ goto out;=0A default:=0A = BUG();=0A case NESTEDHVM_VMEXIT_ERROR:=0A@@ -2385,18 = +2385,21 @@ void svm_vmexit_handler(struct cpu_user_=0A case = NESTEDHVM_VMEXIT_FATALERROR:=0A gdprintk(XENLOG_ERR,=0A = "unexpected nestedsvm_check_intercepts() error\n");=0A- = goto exit_and_crash;=0A+ domain_crash(v->domain);=0A+ = goto out;=0A default:=0A gdprintk(XENLOG_INFO, = "nestedsvm_check_intercepts() returned %i\n",=0A nsret);=0A= - goto exit_and_crash;=0A+ domain_crash(v->domain);= =0A+ goto out;=0A }=0A }=0A =0A if ( unlikely(ex= it_reason =3D=3D VMEXIT_INVALID) )=0A {=0A svm_vmcb_dump(__func= __, vmcb);=0A- goto exit_and_crash;=0A+ domain_crash(v->domai= n);=0A+ goto out;=0A }=0A =0A perfc_incra(svmexits, = exit_reason);=0A@@ -2431,13 +2434,13 @@ void svm_vmexit_handler(struct = cpu_user_=0A =0A case VMEXIT_EXCEPTION_DB:=0A if ( !v->domain->= debugger_attached )=0A- goto exit_and_crash;=0A+ = goto unexpected_exit_type;=0A domain_pause_for_debugger();=0A = break;=0A =0A case VMEXIT_EXCEPTION_BP:=0A if ( !v->domain->= debugger_attached )=0A- goto exit_and_crash;=0A+ = goto unexpected_exit_type;=0A /* AMD Vol2, 15.11: INT3, INTO, = BOUND intercepts do not update RIP. */=0A if ( (inst_len =3D = __get_instruction_length(v, INSTR_INT3)) =3D=3D 0 )=0A = break;=0A@@ -2684,7 +2687,7 @@ void svm_vmexit_handler(struct cpu_user_=0A = break;=0A =0A default:=0A- exit_and_crash:=0A+ unexpected= _exit_type:=0A gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit = reason =3D %#"PRIx64", "=0A "exitinfo1 =3D %#"PRIx64", = exitinfo2 =3D %#"PRIx64"\n",=0A exit_reason, =0A--- = a/xen/arch/x86/hvm/vmx/vmx.c=0A+++ b/xen/arch/x86/hvm/vmx/vmx.c=0A@@ = -134,18 +134,6 @@ static void vmx_vcpu_destroy(struct vcpu=0A = passive_domain_destroy(v);=0A }=0A =0A-/* Only crash the guest if the = problem originates in kernel mode. */=0A-static void vmx_crash_or_fault(str= uct vcpu *v)=0A-{=0A- struct segment_register ss;=0A-=0A- vmx_get_seg= ment_register(v, x86_seg_ss, &ss);=0A- if ( ss.attr.fields.dpl )=0A- = hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);=0A= - else=0A- domain_crash(v->domain);=0A-}=0A-=0A static DEFINE_PER= _CPU(struct vmx_msr_state, host_msr_state);=0A =0A static const u32 = msr_index[] =3D=0A@@ -2520,7 +2508,7 @@ static void vmx_failed_vmentry(unsi= gned =0A vmcs_dump_vcpu(curr);=0A printk("*************************= *************\n");=0A =0A- vmx_crash_or_fault(curr);=0A+ domain_crash= (curr->domain);=0A }=0A =0A void vmx_enter_realmode(struct cpu_user_regs = *regs)=0A@@ -3173,8 +3161,19 @@ void vmx_vmexit_handler(struct cpu_user_=0A= /* fall through */=0A default:=0A exit_and_crash:=0A- = gdprintk(XENLOG_WARNING, "Bad vmexit (reason %#lx)\n", exit_reason);=0A- = vmx_crash_or_fault(v);=0A+ {=0A+ struct segment_regi= ster ss;=0A+=0A+ gdprintk(XENLOG_WARNING, "Bad vmexit (reason = %#lx)\n",=0A+ exit_reason);=0A+=0A+ = vmx_get_segment_register(v, x86_seg_ss, &ss);=0A+ if ( = ss.attr.fields.dpl )=0A+ hvm_inject_hw_exception(TRAP_invali= d_op,=0A+ HVM_DELIVER_NO_ERROR_CODE)= ;=0A+ else=0A+ domain_crash(v->domain);=0A+ = }=0A break;=0A }=0A =0A --=__PartDFEAF18F.1__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --=__PartDFEAF18F.1__=--