1 From stefan.bader@canonical.com Wed Apr 7 14:41:50 2010
2 From: Gleb Natapov <gleb@redhat.com>
3 Date: Fri, 19 Mar 2010 15:47:30 +0100
4 Subject: KVM: x86 emulator: Add Virtual-8086 mode of emulation
6 Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
7 Message-ID: <1269010059-25309-3-git-send-email-stefan.bader@canonical.com>
10 From: Gleb Natapov <gleb@redhat.com>
12 commit a0044755679f3e761b8b95995e5f2db2b7efd0f6 upstream
14 For some instructions CPU behaves differently for real-mode and
15 virtual 8086. Let emulator know which mode cpu is in, so it will
16 not poke into vcpu state directly.
18 Signed-off-by: Gleb Natapov <gleb@redhat.com>
19 Signed-off-by: Avi Kivity <avi@redhat.com>
20 Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
23 arch/x86/include/asm/kvm_emulate.h | 1 +
24 arch/x86/kvm/emulate.c | 14 +++++++-------
25 arch/x86/kvm/x86.c | 3 ++-
26 3 files changed, 10 insertions(+), 8 deletions(-)
28 --- a/arch/x86/include/asm/kvm_emulate.h
29 +++ b/arch/x86/include/asm/kvm_emulate.h
30 @@ -168,6 +168,7 @@ struct x86_emulate_ctxt {
32 /* Execution mode, passed to the emulator. */
33 #define X86EMUL_MODE_REAL 0 /* Real mode. */
34 +#define X86EMUL_MODE_VM86 1 /* Virtual 8086 mode. */
35 #define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */
36 #define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */
37 #define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */
38 --- a/arch/x86/kvm/emulate.c
39 +++ b/arch/x86/kvm/emulate.c
40 @@ -895,6 +895,7 @@ x86_decode_insn(struct x86_emulate_ctxt
43 case X86EMUL_MODE_REAL:
44 + case X86EMUL_MODE_VM86:
45 case X86EMUL_MODE_PROT16:
46 def_op_bytes = def_ad_bytes = 2;
48 @@ -1453,7 +1454,7 @@ emulate_syscall(struct x86_emulate_ctxt
50 /* syscall is not available in real mode */
51 if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL
52 - || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE))
53 + || ctxt->mode == X86EMUL_MODE_VM86)
56 setup_syscalls_segments(ctxt, &cs, &ss);
57 @@ -1505,9 +1506,8 @@ emulate_sysenter(struct x86_emulate_ctxt
61 - /* inject #GP if in real mode or paging is disabled */
62 - if (ctxt->mode == X86EMUL_MODE_REAL ||
63 - !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
64 + /* inject #GP if in real mode */
65 + if (ctxt->mode == X86EMUL_MODE_REAL) {
66 kvm_inject_gp(ctxt->vcpu, 0);
69 @@ -1571,9 +1571,9 @@ emulate_sysexit(struct x86_emulate_ctxt
73 - /* inject #GP if in real mode or paging is disabled */
74 - if (ctxt->mode == X86EMUL_MODE_REAL
75 - || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
76 + /* inject #GP if in real mode or Virtual 8086 mode */
77 + if (ctxt->mode == X86EMUL_MODE_REAL ||
78 + ctxt->mode == X86EMUL_MODE_VM86) {
79 kvm_inject_gp(ctxt->vcpu, 0);
82 --- a/arch/x86/kvm/x86.c
83 +++ b/arch/x86/kvm/x86.c
84 @@ -2828,8 +2828,9 @@ int emulate_instruction(struct kvm_vcpu
85 vcpu->arch.emulate_ctxt.vcpu = vcpu;
86 vcpu->arch.emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
87 vcpu->arch.emulate_ctxt.mode =
88 + (!(vcpu->arch.cr0 & X86_CR0_PE)) ? X86EMUL_MODE_REAL :
89 (vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
90 - ? X86EMUL_MODE_REAL : cs_l
91 + ? X86EMUL_MODE_VM86 : cs_l
92 ? X86EMUL_MODE_PROT64 : cs_db
93 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;