aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-05-06 07:05:25 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-11 03:14:02 -0400
commit5cfc7e0f5e5e1adf998df94f8e36edaf5d30d38e (patch)
tree1eed7b31552a97a9c33b0e7a310e08009bfca227 /arch/x86/kvm
parent285ca9e948fa047e51fe47082528034de5369e8d (diff)
KVM: emulate: avoid repeated calls to do_insn_fetch_bytes
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>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ea188a338afb..ca82ec9c5ffe 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -708,7 +708,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
708 * Prefetch the remaining bytes of the instruction without crossing page 708 * Prefetch the remaining bytes of the instruction without crossing page
709 * boundary if they are not in fetch_cache yet. 709 * boundary if they are not in fetch_cache yet.
710 */ 710 */
711static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt) 711static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
712{ 712{
713 struct fetch_cache *fc = &ctxt->fetch; 713 struct fetch_cache *fc = &ctxt->fetch;
714 int rc; 714 int rc;
@@ -720,7 +720,14 @@ static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt)
720 cur_size = fc->end - fc->start; 720 cur_size = fc->end - fc->start;
721 size = min(15UL - cur_size, 721 size = min(15UL - cur_size,
722 PAGE_SIZE - offset_in_page(fc->end)); 722 PAGE_SIZE - offset_in_page(fc->end));
723 if (unlikely(size == 0)) 723
724 /*
725 * One instruction can only straddle two pages,
726 * and one has been loaded at the beginning of
727 * x86_decode_insn. So, if not enough bytes
728 * still, we must have hit the 15-byte boundary.
729 */
730 if (unlikely(size < op_size))
724 return X86EMUL_UNHANDLEABLE; 731 return X86EMUL_UNHANDLEABLE;
725 rc = __linearize(ctxt, addr, size, false, true, &linear); 732 rc = __linearize(ctxt, addr, size, false, true, &linear);
726 if (unlikely(rc != X86EMUL_CONTINUE)) 733 if (unlikely(rc != X86EMUL_CONTINUE))
@@ -736,17 +743,18 @@ static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt)
736static int do_insn_fetch(struct x86_emulate_ctxt *ctxt, 743static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
737 void *__dest, unsigned size) 744 void *__dest, unsigned size)
738{ 745{
739 int rc;
740 struct fetch_cache *fc = &ctxt->fetch; 746 struct fetch_cache *fc = &ctxt->fetch;
741 u8 *dest = __dest; 747 u8 *dest = __dest;
742 u8 *src = &fc->data[ctxt->_eip - fc->start]; 748 u8 *src = &fc->data[ctxt->_eip - fc->start];
743 749
750 /* We have to be careful about overflow! */
751 if (unlikely(ctxt->_eip > fc->end - size)) {
752 int rc = do_insn_fetch_bytes(ctxt, size);
753 if (rc != X86EMUL_CONTINUE)
754 return rc;
755 }
756
744 while (size--) { 757 while (size--) {
745 if (unlikely(ctxt->_eip == fc->end)) {
746 rc = do_insn_fetch_bytes(ctxt);
747 if (rc != X86EMUL_CONTINUE)
748 return rc;
749 }
750 *dest++ = *src++; 758 *dest++ = *src++;
751 ctxt->_eip++; 759 ctxt->_eip++;
752 continue; 760 continue;
@@ -4228,7 +4236,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
4228 if (insn_len > 0) 4236 if (insn_len > 0)
4229 memcpy(ctxt->fetch.data, insn, insn_len); 4237 memcpy(ctxt->fetch.data, insn, insn_len);
4230 else { 4238 else {
4231 rc = do_insn_fetch_bytes(ctxt); 4239 rc = do_insn_fetch_bytes(ctxt, 1);
4232 if (rc != X86EMUL_CONTINUE) 4240 if (rc != X86EMUL_CONTINUE)
4233 return rc; 4241 return rc;
4234 } 4242 }