Laurent Vivier wrote:
> Index: kvm/drivers/kvm/kvm.h
> @@ -1860,7 +1869,7 @@ static int kvm_vcpu_ioctl_run(struct kvm
>               vcpu->mmio_read_completed = 1;
>               vcpu->mmio_needed = 0;
>               r = emulate_instruction(vcpu, kvm_run,
> -                                     vcpu->mmio_fault_cr2, 0);
> +                                     vcpu->mmio_fault_cr2, 0, 0);
>               if (r == EMULATE_DO_MMIO) {
>                       /*
>                        * Read-modify-write.  Back to userspace.

Sorry this one is wrong, we must have here:

+                                       vcpu->mmio_fault_cr2, 0, 1);

(good patch attached)
Laurent
-- 
------------- [EMAIL PROTECTED]  --------------
          "Software is hard" - Donald Knuth
Index: kvm/drivers/kvm/kvm.h
===================================================================
--- kvm.orig/drivers/kvm/kvm.h  2007-08-29 18:27:21.000000000 +0200
+++ kvm/drivers/kvm/kvm.h       2007-08-29 18:27:26.000000000 +0200
@@ -206,6 +206,8 @@ enum {
        VCPU_SREG_LDTR,
 };
 
+#include "x86_emulate.h"
+
 struct kvm_pio_request {
        unsigned long count;
        int cur_count;
@@ -372,6 +374,10 @@ struct kvm_vcpu {
 
        int cpuid_nent;
        struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
+
+       /* emulate context */
+
+       struct x86_emulate_ctxt emulate_ctxt;
 };
 
 struct kvm_mem_alias {
@@ -525,7 +531,7 @@ enum emulation_result {
 };
 
 int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                       unsigned long cr2, u16 error_code);
+                       unsigned long cr2, u16 error_code, int no_decode);
 void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
Index: kvm/drivers/kvm/kvm_main.c
===================================================================
--- kvm.orig/drivers/kvm/kvm_main.c     2007-08-29 18:27:26.000000000 +0200
+++ kvm/drivers/kvm/kvm_main.c  2007-08-29 18:55:58.000000000 +0200
@@ -1167,47 +1167,56 @@ struct x86_emulate_ops emulate_ops = {
 int emulate_instruction(struct kvm_vcpu *vcpu,
                        struct kvm_run *run,
                        unsigned long cr2,
-                       u16 error_code)
+                       u16 error_code,
+                       int no_decode)
 {
-       struct x86_emulate_ctxt emulate_ctxt;
        int r;
-       int cs_db, cs_l;
 
        vcpu->mmio_fault_cr2 = cr2;
        kvm_arch_ops->cache_regs(vcpu);
+       vcpu->emulate_ctxt.cr2 = cr2;
 
-       kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
-
-       emulate_ctxt.vcpu = vcpu;
-       emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu);
-       emulate_ctxt.cr2 = cr2;
-       emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM)
-               ? X86EMUL_MODE_REAL : cs_l
-               ? X86EMUL_MODE_PROT64 : cs_db
-               ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
-
-       if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
-               emulate_ctxt.cs_base = 0;
-               emulate_ctxt.ds_base = 0;
-               emulate_ctxt.es_base = 0;
-               emulate_ctxt.ss_base = 0;
-       } else {
-               emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
-               emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
-               emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
-               emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
-       }
+       if (!no_decode) {
+               int cs_db, cs_l;
+               kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+
+               vcpu->emulate_ctxt.vcpu = vcpu;
+               vcpu->emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu);
+               vcpu->emulate_ctxt.mode =
+                       (vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM)
+                       ? X86EMUL_MODE_REAL : cs_l
+                       ? X86EMUL_MODE_PROT64 : cs_db
+                       ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+
+               if (vcpu->emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
+                       vcpu->emulate_ctxt.cs_base = 0;
+                       vcpu->emulate_ctxt.ds_base = 0;
+                       vcpu->emulate_ctxt.es_base = 0;
+                       vcpu->emulate_ctxt.ss_base = 0;
+               } else {
+                       vcpu->emulate_ctxt.cs_base =
+                                       get_segment_base(vcpu, VCPU_SREG_CS);
+                       vcpu->emulate_ctxt.ds_base =
+                                       get_segment_base(vcpu, VCPU_SREG_DS);
+                       vcpu->emulate_ctxt.es_base =
+                                       get_segment_base(vcpu, VCPU_SREG_ES);
+                       vcpu->emulate_ctxt.ss_base =
+                                       get_segment_base(vcpu, VCPU_SREG_SS);
+               }
 
-       emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
-       emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);
+               vcpu->emulate_ctxt.gs_base =
+                                       get_segment_base(vcpu, VCPU_SREG_GS);
+               vcpu->emulate_ctxt.fs_base =
+                                       get_segment_base(vcpu, VCPU_SREG_FS);
 
-       r = x86_decode_insn(&emulate_ctxt, &emulate_ops);
-       if (r)
-               return EMULATE_FAIL;
+               r = x86_decode_insn(&vcpu->emulate_ctxt, &emulate_ops);
+               if (r)
+                       return EMULATE_FAIL;
+       }
 
        vcpu->mmio_is_write = 0;
        vcpu->pio.string = 0;
-       r = x86_emulate_insn(&emulate_ctxt, &emulate_ops);
+       r = x86_emulate_insn(&vcpu->emulate_ctxt, &emulate_ops);
        if (vcpu->pio.string)
                return EMULATE_DO_MMIO;
 
@@ -1223,14 +1232,14 @@ int emulate_instruction(struct kvm_vcpu 
                if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
                        return EMULATE_DONE;
                if (!vcpu->mmio_needed) {
-                       report_emulation_failure(&emulate_ctxt);
+                       report_emulation_failure(&vcpu->emulate_ctxt);
                        return EMULATE_FAIL;
                }
                return EMULATE_DO_MMIO;
        }
 
        kvm_arch_ops->decache_regs(vcpu);
-       kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags);
+       kvm_arch_ops->set_rflags(vcpu, vcpu->emulate_ctxt.eflags);
 
        if (vcpu->mmio_is_write) {
                vcpu->mmio_needed = 0;
@@ -1860,7 +1869,7 @@ static int kvm_vcpu_ioctl_run(struct kvm
                vcpu->mmio_read_completed = 1;
                vcpu->mmio_needed = 0;
                r = emulate_instruction(vcpu, kvm_run,
-                                       vcpu->mmio_fault_cr2, 0);
+                                       vcpu->mmio_fault_cr2, 0, 1);
                if (r == EMULATE_DO_MMIO) {
                        /*
                         * Read-modify-write.  Back to userspace.
Index: kvm/drivers/kvm/svm.c
===================================================================
--- kvm.orig/drivers/kvm/svm.c  2007-08-29 18:27:21.000000000 +0200
+++ kvm/drivers/kvm/svm.c       2007-08-29 18:27:26.000000000 +0200
@@ -938,7 +938,7 @@ static int pf_interception(struct vcpu_s
                return 1;
        }
        er = emulate_instruction(&svm->vcpu, kvm_run, fault_address,
-                                error_code);
+                                error_code, 0);
        mutex_unlock(&kvm->lock);
 
        switch (er) {
@@ -994,7 +994,8 @@ static int io_interception(struct vcpu_s
        string = (io_info & SVM_IOIO_STR_MASK) != 0;
 
        if (string) {
-               if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0) == 
EMULATE_DO_MMIO)
+               if (emulate_instruction(&svm->vcpu,
+                                       kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
                        return 0;
                return 1;
        }
@@ -1052,7 +1053,7 @@ static int cpuid_interception(struct vcp
 static int emulate_on_interception(struct vcpu_svm *svm,
                                   struct kvm_run *kvm_run)
 {
-       if (emulate_instruction(&svm->vcpu, NULL, 0, 0) != EMULATE_DONE)
+       if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE)
                pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__);
        return 1;
 }
Index: kvm/drivers/kvm/vmx.c
===================================================================
--- kvm.orig/drivers/kvm/vmx.c  2007-08-29 18:27:21.000000000 +0200
+++ kvm/drivers/kvm/vmx.c       2007-08-29 18:27:26.000000000 +0200
@@ -1659,7 +1659,7 @@ static int handle_rmode_exception(struct
         * Cause the #SS fault with 0 error code in VM86 mode.
         */
        if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
-               if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE)
+               if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
                        return 1;
        return 0;
 }
@@ -1715,7 +1715,7 @@ static int handle_exception(struct kvm_v
                        return 1;
                }
 
-               er = emulate_instruction(vcpu, kvm_run, cr2, error_code);
+               er = emulate_instruction(vcpu, kvm_run, cr2, error_code, 0);
                mutex_unlock(&vcpu->kvm->lock);
 
                switch (er) {
@@ -1776,7 +1776,8 @@ static int handle_io(struct kvm_vcpu *vc
        string = (exit_qualification & 16) != 0;
 
        if (string) {
-               if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
+               if (emulate_instruction(vcpu,
+                                       kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
                        return 0;
                return 1;
        }
Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c  2007-08-29 18:27:26.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c       2007-08-29 18:27:26.000000000 +0200
@@ -888,8 +888,12 @@ x86_emulate_insn(struct x86_emulate_ctxt
        int mode = ctxt->mode;
        int no_wb = 0;
        u64 msr_data;
+       unsigned long saved_rcx = 0, saved_eip = 0;
        unsigned long _eflags = ctxt->eflags;
 
+       if ((decode->d & ModRM) && (decode->modrm_mod != 3))
+               ctxt->cr2 = decode->modrm_ea;
+
        if (decode->src.type == OP_MEM) {
                decode->src.ptr = (unsigned long *)ctxt->cr2;
                if ((rc = ops->read_emulated((unsigned long)decode->src.ptr,
@@ -1274,6 +1278,8 @@ special_insn:
                        ctxt->vcpu->rip = decode->eip;
                        goto done;
                }
+               saved_rcx = ctxt->decode.regs[VCPU_REGS_RCX];
+               saved_eip = ctxt->decode.eip;
                decode->regs[VCPU_REGS_RCX]--;
                decode->eip = ctxt->vcpu->rip;
        }
@@ -1289,8 +1295,13 @@ special_insn:
                                        ctxt->ds_base,
                                        decode->regs[VCPU_REGS_RSI]),
                                        &decode->dst.val,
-                                       decode->dst.bytes, ctxt->vcpu)) != 0)
+                                       decode->dst.bytes, ctxt->vcpu)) != 0) {
+                       if (ctxt->decode.rep_prefix) {
+                               ctxt->decode.regs[VCPU_REGS_RCX] = saved_rcx;
+                               ctxt->decode.eip = saved_eip;
+                       }
                        goto done;
+               }
                register_address_increment(decode->regs[VCPU_REGS_RSI],
                             (_eflags & EFLG_DF) ? -decode->dst.bytes :
                                                   decode->dst.bytes);
@@ -1316,8 +1327,13 @@ special_insn:
                decode->dst.ptr = (unsigned long *)&decode->regs[VCPU_REGS_RAX];
                if ((rc = ops->read_emulated(ctxt->cr2, &decode->dst.val,
                                             decode->dst.bytes,
-                                            ctxt->vcpu)) != 0)
+                                            ctxt->vcpu)) != 0) {
+                       if (ctxt->decode.rep_prefix) {
+                               ctxt->decode.regs[VCPU_REGS_RCX] = saved_rcx;
+                               ctxt->decode.eip = saved_eip;
+                       }
                        goto done;
+               }
                register_address_increment(decode->regs[VCPU_REGS_RSI],
                           (_eflags & EFLG_DF) ? -decode->dst.bytes :
                                                 decode->dst.bytes);
@@ -1338,8 +1354,13 @@ special_insn:
 pop_instruction:
                if ((rc = ops->read_std(register_address(ctxt->ss_base,
                        decode->regs[VCPU_REGS_RSP]), decode->dst.ptr,
-                       decode->op_bytes, ctxt->vcpu)) != 0)
+                       decode->op_bytes, ctxt->vcpu)) != 0) {
+                       if (ctxt->decode.rep_prefix) {
+                               ctxt->decode.regs[VCPU_REGS_RCX] = saved_rcx;
+                               ctxt->decode.eip = saved_eip;
+                       }
                        goto done;
+               }
 
                register_address_increment(decode->regs[VCPU_REGS_RSP],
                                           decode->op_bytes);
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to