aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
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:03 -0400
commit9506d57de3bc8277a4e306e0d439976862f68c6d (patch)
treeaac16beac03ddc018f7ffec0d453d1a89d4a11f0 /arch/x86/kvm/emulate.c
parent5cfc7e0f5e5e1adf998df94f8e36edaf5d30d38e (diff)
KVM: emulate: avoid per-byte copying in instruction fetches
We do not need a memory copying loop anymore in insn_fetch; we can use a byte-aligned pointer to access instruction fields directly from the fetch_cache. This eliminates 50-150 cycles (corresponding to a 5-10% improvement in performance) from each instruction. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ca82ec9c5ffe..02c668aca2b6 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, int op_size) 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;
@@ -740,41 +740,39 @@ static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
740 return X86EMUL_CONTINUE; 740 return X86EMUL_CONTINUE;
741} 741}
742 742
743static int do_insn_fetch(struct x86_emulate_ctxt *ctxt, 743static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
744 void *__dest, unsigned size) 744 unsigned size)
745{ 745{
746 struct fetch_cache *fc = &ctxt->fetch;
747 u8 *dest = __dest;
748 u8 *src = &fc->data[ctxt->_eip - fc->start];
749
750 /* We have to be careful about overflow! */ 746 /* We have to be careful about overflow! */
751 if (unlikely(ctxt->_eip > fc->end - size)) { 747 if (unlikely(ctxt->_eip > ctxt->fetch.end - size))
752 int rc = do_insn_fetch_bytes(ctxt, size); 748 return __do_insn_fetch_bytes(ctxt, size);
753 if (rc != X86EMUL_CONTINUE) 749 else
754 return rc; 750 return X86EMUL_CONTINUE;
755 }
756
757 while (size--) {
758 *dest++ = *src++;
759 ctxt->_eip++;
760 continue;
761 }
762 return X86EMUL_CONTINUE;
763} 751}
764 752
765/* Fetch next part of the instruction being emulated. */ 753/* Fetch next part of the instruction being emulated. */
766#define insn_fetch(_type, _ctxt) \ 754#define insn_fetch(_type, _ctxt) \
767({ unsigned long _x; \ 755({ _type _x; \
768 rc = do_insn_fetch(_ctxt, &_x, sizeof(_type)); \ 756 struct fetch_cache *_fc; \
757 \
758 rc = do_insn_fetch_bytes(_ctxt, sizeof(_type)); \
769 if (rc != X86EMUL_CONTINUE) \ 759 if (rc != X86EMUL_CONTINUE) \
770 goto done; \ 760 goto done; \
771 (_type)_x; \ 761 _fc = &ctxt->fetch; \
762 _x = *(_type __aligned(1) *) &_fc->data[ctxt->_eip - _fc->start]; \
763 ctxt->_eip += sizeof(_type); \
764 _x; \
772}) 765})
773 766
774#define insn_fetch_arr(_arr, _size, _ctxt) \ 767#define insn_fetch_arr(_arr, _size, _ctxt) \
775({ rc = do_insn_fetch(_ctxt, _arr, (_size)); \ 768({ \
769 struct fetch_cache *_fc; \
770 rc = do_insn_fetch_bytes(_ctxt, _size); \
776 if (rc != X86EMUL_CONTINUE) \ 771 if (rc != X86EMUL_CONTINUE) \
777 goto done; \ 772 goto done; \
773 _fc = &ctxt->fetch; \
774 memcpy(_arr, &_fc->data[ctxt->_eip - _fc->start], _size); \
775 ctxt->_eip += (_size); \
778}) 776})
779 777
780/* 778/*
@@ -4236,7 +4234,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
4236 if (insn_len > 0) 4234 if (insn_len > 0)
4237 memcpy(ctxt->fetch.data, insn, insn_len); 4235 memcpy(ctxt->fetch.data, insn, insn_len);
4238 else { 4236 else {
4239 rc = do_insn_fetch_bytes(ctxt, 1); 4237 rc = __do_insn_fetch_bytes(ctxt, 1);
4240 if (rc != X86EMUL_CONTINUE) 4238 if (rc != X86EMUL_CONTINUE)
4241 return rc; 4239 return rc;
4242 } 4240 }