public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
To: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: [PATCH 5/5] Call x86_decode_insn() only when needed
Date: Wed, 29 Aug 2007 18:45:36 +0200	[thread overview]
Message-ID: <46D5A2B0.7050802@bull.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 280 bytes --]

move emulate_ctxt to kvm_vcpu to keep emulate context when we exit from kvm
module. Call x86_decode_insn() only when needed. Modify x86_emulate_insn() to
not modify the context if it must be re-entered.

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>

[-- Attachment #2: x86_emulate-optimize --]
[-- Type: text/plain, Size: 9612 bytes --]

Index: kvm/drivers/kvm/kvm.h
===================================================================
--- kvm.orig/drivers/kvm/kvm.h	2007-08-29 18:02:41.000000000 +0200
+++ kvm/drivers/kvm/kvm.h	2007-08-29 18:02:45.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:02:41.000000000 +0200
+++ kvm/drivers/kvm/kvm_main.c	2007-08-29 18:02:45.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, 0);
 		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:02:41.000000000 +0200
+++ kvm/drivers/kvm/svm.c	2007-08-29 18:03:18.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:02:41.000000000 +0200
+++ kvm/drivers/kvm/vmx.c	2007-08-29 18:03:30.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:02:41.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-08-29 18:02:45.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);

[-- Attachment #3: Type: text/plain, Size: 315 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/

[-- Attachment #4: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

             reply	other threads:[~2007-08-29 16:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-29 16:45 Laurent Vivier [this message]
     [not found] ` <46D5A2B0.7050802-6ktuUTfB/bM@public.gmane.org>
2007-08-29 17:03   ` [PATCH 5/5] Call x86_decode_insn() only when needed Laurent Vivier

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=46D5A2B0.7050802@bull.net \
    --to=laurent.vivier-6ktuutfb/bm@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /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