KVM: x86 emulator: fix return values of syscall/sysenter/sysexit emulations
authorGleb Natapov <gleb@redhat.com>
Thu, 18 Mar 2010 13:20:12 +0000 (15:20 +0200)
committerAvi Kivity <avi@redhat.com>
Mon, 17 May 2010 09:16:08 +0000 (12:16 +0300)
Return X86EMUL_PROPAGATE_FAULT is fault was injected. Also inject #UD
for those instruction when appropriate.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/emulate.c

index 5afddcf..1393bf0 100644 (file)
@@ -1600,8 +1600,11 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
        u64 msr_data;
 
        /* syscall is not available in real mode */
-       if (ctxt->mode == X86EMUL_MODE_REAL || ctxt->mode == X86EMUL_MODE_VM86)
-               return X86EMUL_UNHANDLEABLE;
+       if (ctxt->mode == X86EMUL_MODE_REAL ||
+           ctxt->mode == X86EMUL_MODE_VM86) {
+               kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+               return X86EMUL_PROPAGATE_FAULT;
+       }
 
        setup_syscalls_segments(ctxt, &cs, &ss);
 
@@ -1651,14 +1654,16 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt)
        /* inject #GP if in real mode */
        if (ctxt->mode == X86EMUL_MODE_REAL) {
                kvm_inject_gp(ctxt->vcpu, 0);
-               return X86EMUL_UNHANDLEABLE;
+               return X86EMUL_PROPAGATE_FAULT;
        }
 
        /* XXX sysenter/sysexit have not been tested in 64bit mode.
        * Therefore, we inject an #UD.
        */
-       if (ctxt->mode == X86EMUL_MODE_PROT64)
-               return X86EMUL_UNHANDLEABLE;
+       if (ctxt->mode == X86EMUL_MODE_PROT64) {
+               kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+               return X86EMUL_PROPAGATE_FAULT;
+       }
 
        setup_syscalls_segments(ctxt, &cs, &ss);
 
@@ -1713,7 +1718,7 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt)
        if (ctxt->mode == X86EMUL_MODE_REAL ||
            ctxt->mode == X86EMUL_MODE_VM86) {
                kvm_inject_gp(ctxt->vcpu, 0);
-               return X86EMUL_UNHANDLEABLE;
+               return X86EMUL_PROPAGATE_FAULT;
        }
 
        setup_syscalls_segments(ctxt, &cs, &ss);