From mboxrd@z Thu Jan 1 00:00:00 1970 From: Gleb Natapov Subject: Re: [PATCH] KVM: x86 emulator: Fix segment loading in VM86 Date: Thu, 11 Apr 2013 15:53:26 +0300 Message-ID: <20130411125326.GX17919@redhat.com> References: <1365681963-2032-1-git-send-email-kwolf@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: kvm@vger.kernel.org, mtosatti@redhat.com To: Kevin Wolf Return-path: Received: from mx1.redhat.com ([209.132.183.28]:64463 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751004Ab3DKMxa (ORCPT ); Thu, 11 Apr 2013 08:53:30 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r3BCrUGY014004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 11 Apr 2013 08:53:30 -0400 Content-Disposition: inline In-Reply-To: <1365681963-2032-1-git-send-email-kwolf@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: On Thu, Apr 11, 2013 at 02:06:03PM +0200, Kevin Wolf wrote: > This fixes a regression introduced in commit 03ebebeb1 ("KVM: x86 > emulator: Leave segment limit and attributs alone in real mode"). > > The mentioned commit changed the segment descriptors for both real mode > and VM86 to only update the segment base instead of creating a > completely new descriptor with limit 0xffff so that unreal mode keeps > working across a segment register reload. > > This leads to an invalid segment descriptor in the eyes of VMX, which > seems to be okay for real mode because KVM will fix it up before the > next VM entry or emulate the state, but it doesn't do this if the guest > is in VM86, so we end up with: > > KVM: entry failed, hardware error 0x80000021 > > Fix this by effectively reverting commit 03ebebeb1 for VM86 and leaving > it only in place for real mode, which is where it's really needed. > > Signed-off-by: Kevin Wolf Applied, thanks. > --- > arch/x86/kvm/emulate.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c > index a335cc6..069d799 100644 > --- a/arch/x86/kvm/emulate.c > +++ b/arch/x86/kvm/emulate.c > @@ -1578,12 +1578,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt, > > memset(&seg_desc, 0, sizeof seg_desc); > > - if ((seg <= VCPU_SREG_GS && ctxt->mode == X86EMUL_MODE_VM86) > - || ctxt->mode == X86EMUL_MODE_REAL) { > - /* set real mode segment descriptor */ > + if (ctxt->mode == X86EMUL_MODE_REAL) { > + /* set real mode segment descriptor (keep limit etc. for > + * unreal mode) */ > ctxt->ops->get_segment(ctxt, &dummy, &seg_desc, NULL, seg); > set_desc_base(&seg_desc, selector << 4); > goto load; > + } else if (seg <= VCPU_SREG_GS && ctxt->mode == X86EMUL_MODE_VM86) { > + /* VM86 needs a clean new segment descriptor */ > + set_desc_base(&seg_desc, selector << 4); > + set_desc_limit(&seg_desc, 0xffff); > + seg_desc.type = 3; > + seg_desc.p = 1; > + seg_desc.s = 1; > + seg_desc.dpl = 3; > + goto load; > } > > rpl = selector & 3; > -- > 1.8.1.4 -- Gleb.