@@ -4742,10 +4742,13 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->fetch.end = ctxt->fetch.data + insn_len;
ctxt->opcode_len = 1;
ctxt->intercept = x86_intercept_none;
+ ctxt->is_mmio_fetch = false;
if (insn_len > 0)
memcpy(ctxt->fetch.data, insn, insn_len);
else {
rc = __do_insn_fetch_bytes(ctxt, 1);
+ if (rc == X86EMUL_IO_NEEDED)
+ ctxt->is_mmio_fetch = true;
if (rc != X86EMUL_CONTINUE)
goto done;
}
@@ -362,6 +362,7 @@ struct x86_emulate_ctxt {
u8 seg_override;
u64 d;
unsigned long _eip;
+ bool is_mmio_fetch;
/* Here begins the usercopy section. */
struct operand src;
@@ -8857,7 +8857,12 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
kvm_queue_exception(vcpu, UD_VECTOR);
- if (!is_guest_mode(vcpu) && kvm_x86_call(get_cpl)(vcpu) == 0) {
+ /*
+ * Don't return an internal error if the emulation error is caused by a fetch from MMIO
+ * address. Injecting a #UD should be enough.
+ */
+ if (!is_guest_mode(vcpu) && kvm_x86_call(get_cpl)(vcpu) == 0 &&
+ !vcpu->arch.emulate_ctxt->is_mmio_fetch) {
prepare_emulation_ctxt_failure_exit(vcpu);
return 0;
}
Currently, we simply return a KVM internal error with suberror = KVM_INTERNAL_ERROR_EMULATION if the guest tries to fetch instruction from MMIO range as we simply can't decode it. I believe it is not the best thing to do, considering that 1) we don't give enough information to VMM about the issue we faced 2) the issue is triggered by the guest itself, so it is not the KVM "internal" error. Inject the #UD into the guest instead and resume it's execution without giving an error to VMM, as it would be if we can't find a valid instruction at MMIO address. Signed-off-by: Ivan Orlov <iorlov@amazon.com> --- arch/x86/kvm/emulate.c | 3 +++ arch/x86/kvm/kvm_emulate.h | 1 + arch/x86/kvm/x86.c | 7 ++++++- 3 files changed, 10 insertions(+), 1 deletion(-)