mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: bdas@redhat.com, gleb@kernel.org
Subject: [PATCH 20/25] KVM: emulate: avoid repeated calls to do_insn_fetch_bytes
Date: Mon,  9 Jun 2014 14:59:08 +0200	[thread overview]
Message-ID: <1402318753-23362-21-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1402318753-23362-1-git-send-email-pbonzini@redhat.com>

do_insn_fetch_bytes will only be called once in a given insn_fetch and
insn_fetch_arr, because in fact it will only be called at most twice
for any instruction and the first call is explicit in x86_decode_insn.
This observation lets us hoist the call out of the memory copying loop.
It does not buy performance, because most fetches are one byte long
anyway, but it prepares for the next patch.

The overflow check is tricky, but correct.  Because do_insn_fetch_bytes
has already been called once, we know that fc->end is at least 15.  So
it is okay to subtract the number of bytes we want to read.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/emulate.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index aee124a4cc6c..f81d7a5bc19b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -707,7 +707,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
  * Prefetch the remaining bytes of the instruction without crossing page
  * boundary if they are not in fetch_cache yet.
  */
-static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt)
+static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 {
 	struct fetch_cache *fc = &ctxt->fetch;
 	int rc;
@@ -719,7 +719,14 @@ static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt)
 	cur_size = fc->end - fc->start;
 	size = min(15UL - cur_size,
 		   PAGE_SIZE - offset_in_page(fc->end));
-	if (unlikely(size == 0))
+
+	/*
+	 * One instruction can only straddle two pages,
+	 * and one has been loaded at the beginning of
+	 * x86_decode_insn.  So, if not enough bytes
+	 * still, we must have hit the 15-byte boundary.
+	 */
+	if (unlikely(size < op_size))
 		return X86EMUL_UNHANDLEABLE;
 	rc = __linearize(ctxt, addr, size, false, true, &linear);
 	if (unlikely(rc != X86EMUL_CONTINUE))
@@ -735,17 +742,18 @@ static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt)
 static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
 			 void *__dest, unsigned size)
 {
-	int rc;
 	struct fetch_cache *fc = &ctxt->fetch;
 	u8 *dest = __dest;
 	u8 *src = &fc->data[ctxt->_eip - fc->start];
 
+	/* We have to be careful about overflow! */
+	if (unlikely(ctxt->_eip > fc->end - size)) {
+		int rc = do_insn_fetch_bytes(ctxt, size);
+		if (rc != X86EMUL_CONTINUE)
+			return rc;
+	}
+
 	while (size--) {
-		if (unlikely(ctxt->_eip == fc->end)) {
-			rc = do_insn_fetch_bytes(ctxt);
-			if (rc != X86EMUL_CONTINUE)
-				return rc;
-		}
 		*dest++ = *src++;
 		ctxt->_eip++;
 		continue;
@@ -4302,7 +4310,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 	if (insn_len > 0)
 		memcpy(ctxt->fetch.data, insn, insn_len);
 	else {
-		rc = do_insn_fetch_bytes(ctxt);
+		rc = do_insn_fetch_bytes(ctxt, 1);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 	}
-- 
1.8.3.1



  parent reply	other threads:[~2014-06-09 13:00 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-09 12:58 [PATCH 00/25] KVM: x86: Speed up emulation of invalid state Paolo Bonzini
2014-06-09 12:58 ` [PATCH 01/25] KVM: vmx: speed up emulation of invalid guest state Paolo Bonzini
2014-06-09 12:58 ` [PATCH 02/25] KVM: x86: return all bits from get_interrupt_shadow Paolo Bonzini
2014-06-09 12:58 ` [PATCH 03/25] KVM: x86: avoid useless set of KVM_REQ_EVENT after emulation Paolo Bonzini
2014-06-09 12:58 ` [PATCH 04/25] KVM: emulate: move around some checks Paolo Bonzini
2014-06-09 12:58 ` [PATCH 05/25] KVM: emulate: protect checks on ctxt->d by a common "if (unlikely())" Paolo Bonzini
2014-06-09 12:58 ` [PATCH 06/25] KVM: emulate: speed up emulated moves Paolo Bonzini
2014-06-09 12:58 ` [PATCH 07/25] KVM: emulate: simplify writeback Paolo Bonzini
2014-06-09 12:58 ` [PATCH 08/25] KVM: emulate: abstract handling of memory operands Paolo Bonzini
2014-06-09 12:58 ` [PATCH 09/25] KVM: export mark_page_dirty_in_slot Paolo Bonzini
2014-06-09 12:58 ` [PATCH 10/25] KVM: emulate: introduce memory_prepare callback to speed up memory access Paolo Bonzini
2014-06-09 12:58 ` [PATCH 11/25] KVM: emulate: activate memory access optimization Paolo Bonzini
2014-06-09 12:59 ` [PATCH 12/25] KVM: emulate: extend memory access optimization to stores Paolo Bonzini
2014-06-09 18:40   ` Bandan Das
2014-06-19 11:37     ` Paolo Bonzini
2014-06-09 12:59 ` [PATCH 13/25] KVM: emulate: move init_decode_cache to emulate.c Paolo Bonzini
2014-06-09 12:59 ` [PATCH 14/25] KVM: emulate: Remove ctxt->intercept and ctxt->check_perm checks Paolo Bonzini
2014-06-09 12:59 ` [PATCH 15/25] KVM: emulate: cleanup decode_modrm Paolo Bonzini
2014-06-09 12:59 ` [PATCH 16/25] KVM: emulate: clean up initializations in init_decode_cache Paolo Bonzini
2014-06-09 12:59 ` [PATCH 17/25] KVM: emulate: rework seg_override Paolo Bonzini
2014-06-09 12:59 ` [PATCH 18/25] KVM: emulate: do not initialize memopp Paolo Bonzini
2014-06-09 12:59 ` [PATCH 19/25] KVM: emulate: speed up do_insn_fetch Paolo Bonzini
2014-06-09 12:59 ` Paolo Bonzini [this message]
2014-06-09 12:59 ` [PATCH 21/25] KVM: emulate: avoid per-byte copying in instruction fetches Paolo Bonzini
2014-06-09 12:59 ` [PATCH 22/25] KVM: emulate: put pointers in the fetch_cache Paolo Bonzini
2014-06-09 12:59 ` [PATCH 23/25] KVM: x86: use kvm_read_guest_page for emulator accesses Paolo Bonzini
2014-06-09 12:59 ` [PATCH 24/25] KVM: emulate: simplify BitOp handling Paolo Bonzini
2014-06-09 12:59 ` [PATCH 25/25] KVM: emulate: fix harmless typo in MMX decoding Paolo Bonzini

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=1402318753-23362-21-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=bdas@redhat.com \
    --cc=gleb@kernel.org \
    --cc=linux-kernel@vger.kernel.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

all inboxes | Powered by JetHome®