kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: kvm@vger.kernel.org
Cc: kwolf@redhat.com, gleb@redhat.com, joerg.roedel@amd.com,
	yoshikawa.takuya@oss.ntt.co.jp, avi@redhat.com,
	mtosatti@redhat.com
Subject: [PATCH v2 3/3] KVM: x86 emulator: Allow PM/VM86 switch during task switch
Date: Fri, 27 Jan 2012 20:23:36 +0100	[thread overview]
Message-ID: <1327692216-20450-4-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1327692216-20450-1-git-send-email-kwolf@redhat.com>

Task switches can switch between Protected Mode and VM86. The current
mode must be updated during the task switch emulation so that the new
segment selectors are interpreted correctly and privilege checks
succeed.

VMX code calculates the CPL from the code segment selector and rflags,
so it needs rflags to be updated in the vcpu struct. SVM stores the DPL
of the code segment instead, so we must be sure to give the right one
when updating the selector.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 arch/x86/include/asm/kvm_emulate.h |    1 +
 arch/x86/kvm/emulate.c             |   26 ++++++++++++++++++++++++++
 arch/x86/kvm/x86.c                 |    6 ++++++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index c8a9cf3..4a21c7d 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -176,6 +176,7 @@ struct x86_emulate_ops {
 	void (*set_idt)(struct x86_emulate_ctxt *ctxt, struct desc_ptr *dt);
 	ulong (*get_cr)(struct x86_emulate_ctxt *ctxt, int cr);
 	int (*set_cr)(struct x86_emulate_ctxt *ctxt, int cr, ulong val);
+	void (*set_rflags)(struct x86_emulate_ctxt *ctxt, ulong val);
 	int (*cpl)(struct x86_emulate_ctxt *ctxt);
 	int (*get_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong *dest);
 	int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 833969e..143ce8e 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -552,6 +552,14 @@ static void set_segment_selector(struct x86_emulate_ctxt *ctxt, u16 selector,
 	struct desc_struct desc;
 
 	ctxt->ops->get_segment(ctxt, &dummy, &desc, &base3, seg);
+
+	if (ctxt->mode == X86EMUL_MODE_REAL)
+		desc.dpl = 0;
+	else if (ctxt->mode == X86EMUL_MODE_VM86)
+		desc.dpl = 3;
+	else
+		desc.dpl = selector & 0x3;
+
 	ctxt->ops->set_segment(ctxt, selector, &desc, base3, seg);
 }
 
@@ -2273,6 +2281,24 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
 		return emulate_gp(ctxt, 0);
 	ctxt->_eip = tss->eip;
 	ctxt->eflags = tss->eflags | 2;
+
+	/*
+	 * If we're switching between Protected Mode and VM86, we need to make
+	 * sure to update the mode before loading the segment descriptors so
+	 * that the selectors are interpreted correctly.
+	 *
+	 * Need to get it to the vcpu struct immediately because it influences
+	 * the CPL which is checked at least when loading the segment
+	 * descriptors and when pushing an error code to the new kernel stack.
+	 */
+	if (ctxt->eflags & X86_EFLAGS_VM)
+		ctxt->mode = X86EMUL_MODE_VM86;
+	else
+		ctxt->mode = X86EMUL_MODE_PROT32;
+
+	ctxt->ops->set_rflags(ctxt, ctxt->eflags);
+
+	/* General purpose registers */
 	ctxt->regs[VCPU_REGS_RAX] = tss->eax;
 	ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
 	ctxt->regs[VCPU_REGS_RDX] = tss->edx;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index dc3e945..502b5c3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4040,6 +4040,11 @@ static int emulator_set_cr(struct x86_emulate_ctxt *ctxt, int cr, ulong val)
 	return res;
 }
 
+static void emulator_set_rflags(struct x86_emulate_ctxt *ctxt, ulong val)
+{
+	kvm_set_rflags(emul_to_vcpu(ctxt), val);
+}
+
 static int emulator_get_cpl(struct x86_emulate_ctxt *ctxt)
 {
 	return kvm_x86_ops->get_cpl(emul_to_vcpu(ctxt));
@@ -4199,6 +4204,7 @@ static struct x86_emulate_ops emulate_ops = {
 	.set_idt	     = emulator_set_idt,
 	.get_cr              = emulator_get_cr,
 	.set_cr              = emulator_set_cr,
+	.set_rflags          = emulator_set_rflags,
 	.cpl                 = emulator_get_cpl,
 	.get_dr              = emulator_get_dr,
 	.set_dr              = emulator_set_dr,
-- 
1.7.6.5


  parent reply	other threads:[~2012-01-27 19:20 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-27 19:23 [PATCH v2 0/3] Fix task switches into/out of VM86 Kevin Wolf
2012-01-27 19:23 ` [PATCH v2 1/3] KVM: x86 emulator: Fix task switch privilege checks Kevin Wolf
2012-01-30 10:39   ` Avi Kivity
2012-01-30 11:12     ` Kevin Wolf
2012-01-27 19:23 ` [PATCH v2 2/3] KVM: x86 emulator: VM86 segments must have DPL 3 Kevin Wolf
2012-01-27 19:23 ` Kevin Wolf [this message]
2012-01-30 10:24   ` [PATCH v2 3/3] KVM: x86 emulator: Allow PM/VM86 switch during task switch Avi Kivity
2012-01-30 10:56     ` Gleb Natapov
2012-01-30 12:02       ` Avi Kivity
2012-01-30 12:04         ` Gleb Natapov
2012-01-30 13:24           ` Avi Kivity
2012-01-30 11:05     ` Kevin Wolf
2012-01-30 11:09       ` Gleb Natapov
2012-01-30 13:23       ` Avi Kivity
2012-01-30 14:01         ` Kevin Wolf
2012-01-30 14:32           ` Avi Kivity
2012-01-30 15:26             ` Kevin Wolf
2012-01-30 15:44               ` Avi Kivity
2012-01-30 15:55               ` Takuya Yoshikawa
2012-01-31  9:37               ` Gleb Natapov
2012-01-31 10:26                 ` Avi Kivity
2012-01-27 19:52 ` [PATCH v2 0/3] Fix task switches into/out of VM86 Gleb Natapov
2012-01-30  8:48   ` Kevin Wolf
2012-01-30  8:55     ` Gleb Natapov
2012-01-30 10:22       ` Gleb Natapov
2012-01-30 10:35       ` Kevin Wolf
2012-01-30 10:45         ` Avi Kivity
2012-01-30 10:50           ` Gleb Natapov
2012-01-30 11:59             ` Avi Kivity
2012-01-30 12:16               ` Gleb Natapov
2012-01-30 13:27                 ` Avi Kivity
2012-01-30 12:31               ` Gleb Natapov
2012-01-30 13:28                 ` Avi Kivity
2012-01-30 13:29                   ` Gleb Natapov
2012-01-30 13:39                     ` Avi Kivity
2012-01-30 10:47         ` Gleb Natapov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1327692216-20450-4-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=avi@redhat.com \
    --cc=gleb@redhat.com \
    --cc=joerg.roedel@amd.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=yoshikawa.takuya@oss.ntt.co.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).