aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 }