diff options
-rw-r--r-- | arch/x86/kvm/emulate.c | 26 |
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 | */ |
711 | static int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt) | 711 | static 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) | |||
736 | static int do_insn_fetch(struct x86_emulate_ctxt *ctxt, | 743 | static 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 | } |