Commit 60fc3d02 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: x86: Remove emulation_result enums, EMULATE_{DONE,FAIL,USER_EXIT}

Deferring emulation failure handling (in some cases) to the caller of
x86_emulate_instruction() has proven fragile, e.g. multiple instances of
KVM not setting run->exit_reason on EMULATE_FAIL, largely due to it
being difficult to discern what emulation types can return what result,
and which combination of types and results are handled where.

Now that x86_emulate_instruction() always handles emulation failure,
i.e. EMULATION_FAIL is only referenced in callers, remove the
emulation_result enums entirely.  Per KVM's existing exit handling
conventions, return '0' and '1' for "exit to userspace" and "resume
guest" respectively.  Doing so cleans up many callers, e.g. they can
return kvm_emulate_instruction() directly instead of having to interpret
its result.
Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 8fff2710
...@@ -1315,12 +1315,6 @@ extern u64 kvm_default_tsc_scaling_ratio; ...@@ -1315,12 +1315,6 @@ extern u64 kvm_default_tsc_scaling_ratio;
extern u64 kvm_mce_cap_supported; extern u64 kvm_mce_cap_supported;
enum emulation_result {
EMULATE_DONE, /* no further processing */
EMULATE_USER_EXIT, /* kvm_run ready for userspace exit */
EMULATE_FAIL, /* can't emulate this instruction */
};
#define EMULTYPE_NO_DECODE (1 << 0) #define EMULTYPE_NO_DECODE (1 << 0)
#define EMULTYPE_TRAP_UD (1 << 1) #define EMULTYPE_TRAP_UD (1 << 1)
#define EMULTYPE_SKIP (1 << 2) #define EMULTYPE_SKIP (1 << 2)
......
...@@ -5383,7 +5383,6 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, ...@@ -5383,7 +5383,6 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
void *insn, int insn_len) void *insn, int insn_len)
{ {
int r, emulation_type = 0; int r, emulation_type = 0;
enum emulation_result er;
bool direct = vcpu->arch.mmu->direct_map; bool direct = vcpu->arch.mmu->direct_map;
/* With shadow page tables, fault_address contains a GVA or nGPA. */ /* With shadow page tables, fault_address contains a GVA or nGPA. */
...@@ -5450,17 +5449,8 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, ...@@ -5450,17 +5449,8 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
return 1; return 1;
} }
er = x86_emulate_instruction(vcpu, cr2, emulation_type, insn, insn_len); return x86_emulate_instruction(vcpu, cr2, emulation_type, insn,
insn_len);
switch (er) {
case EMULATE_DONE:
return 1;
case EMULATE_USER_EXIT:
case EMULATE_FAIL:
return 0;
default:
BUG();
}
} }
EXPORT_SYMBOL_GPL(kvm_mmu_page_fault); EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
......
...@@ -787,7 +787,7 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -787,7 +787,7 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
kvm_rip_write(vcpu, svm->next_rip); kvm_rip_write(vcpu, svm->next_rip);
svm_set_interrupt_shadow(vcpu, 0); svm_set_interrupt_shadow(vcpu, 0);
return EMULATE_DONE; return 1;
} }
static void svm_queue_exception(struct kvm_vcpu *vcpu) static void svm_queue_exception(struct kvm_vcpu *vcpu)
...@@ -2779,8 +2779,7 @@ static int gp_interception(struct vcpu_svm *svm) ...@@ -2779,8 +2779,7 @@ static int gp_interception(struct vcpu_svm *svm)
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
return 1; return 1;
} }
return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP) != return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP);
EMULATE_USER_EXIT;
} }
static bool is_erratum_383(void) static bool is_erratum_383(void)
...@@ -2878,7 +2877,7 @@ static int io_interception(struct vcpu_svm *svm) ...@@ -2878,7 +2877,7 @@ static int io_interception(struct vcpu_svm *svm)
string = (io_info & SVM_IOIO_STR_MASK) != 0; string = (io_info & SVM_IOIO_STR_MASK) != 0;
in = (io_info & SVM_IOIO_TYPE_MASK) != 0; in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
if (string) if (string)
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(vcpu, 0);
port = io_info >> 16; port = io_info >> 16;
size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
...@@ -3885,17 +3884,15 @@ static int task_switch_interception(struct vcpu_svm *svm) ...@@ -3885,17 +3884,15 @@ static int task_switch_interception(struct vcpu_svm *svm)
int_type == SVM_EXITINTINFO_TYPE_SOFT || int_type == SVM_EXITINTINFO_TYPE_SOFT ||
(int_type == SVM_EXITINTINFO_TYPE_EXEPT && (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
(int_vec == OF_VECTOR || int_vec == BP_VECTOR))) { (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) {
if (skip_emulated_instruction(&svm->vcpu) == EMULATE_USER_EXIT) if (!skip_emulated_instruction(&svm->vcpu))
return 0; return 0;
} }
if (int_type != SVM_EXITINTINFO_TYPE_SOFT) if (int_type != SVM_EXITINTINFO_TYPE_SOFT)
int_vec = -1; int_vec = -1;
return kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason, return kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason,
has_error_code, error_code) != EMULATE_USER_EXIT; has_error_code, error_code);
} }
static int cpuid_interception(struct vcpu_svm *svm) static int cpuid_interception(struct vcpu_svm *svm)
...@@ -3916,7 +3913,7 @@ static int iret_interception(struct vcpu_svm *svm) ...@@ -3916,7 +3913,7 @@ static int iret_interception(struct vcpu_svm *svm)
static int invlpg_interception(struct vcpu_svm *svm) static int invlpg_interception(struct vcpu_svm *svm)
{ {
if (!static_cpu_has(X86_FEATURE_DECODEASSISTS)) if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
return kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(&svm->vcpu, 0);
kvm_mmu_invlpg(&svm->vcpu, svm->vmcb->control.exit_info_1); kvm_mmu_invlpg(&svm->vcpu, svm->vmcb->control.exit_info_1);
return kvm_skip_emulated_instruction(&svm->vcpu); return kvm_skip_emulated_instruction(&svm->vcpu);
...@@ -3924,13 +3921,12 @@ static int invlpg_interception(struct vcpu_svm *svm) ...@@ -3924,13 +3921,12 @@ static int invlpg_interception(struct vcpu_svm *svm)
static int emulate_on_interception(struct vcpu_svm *svm) static int emulate_on_interception(struct vcpu_svm *svm)
{ {
return kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(&svm->vcpu, 0);
} }
static int rsm_interception(struct vcpu_svm *svm) static int rsm_interception(struct vcpu_svm *svm)
{ {
return kvm_emulate_instruction_from_buffer(&svm->vcpu, return kvm_emulate_instruction_from_buffer(&svm->vcpu, rsm_ins_bytes, 2);
rsm_ins_bytes, 2) == EMULATE_DONE;
} }
static int rdpmc_interception(struct vcpu_svm *svm) static int rdpmc_interception(struct vcpu_svm *svm)
...@@ -4719,7 +4715,7 @@ static int avic_unaccelerated_access_interception(struct vcpu_svm *svm) ...@@ -4719,7 +4715,7 @@ static int avic_unaccelerated_access_interception(struct vcpu_svm *svm)
ret = avic_unaccel_trap_write(svm); ret = avic_unaccel_trap_write(svm);
} else { } else {
/* Handling Fault */ /* Handling Fault */
ret = (kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE); ret = kvm_emulate_instruction(&svm->vcpu, 0);
} }
return ret; return ret;
......
...@@ -1516,7 +1516,7 @@ static int __skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -1516,7 +1516,7 @@ static int __skip_emulated_instruction(struct kvm_vcpu *vcpu)
/* skipping an emulated instruction also counts */ /* skipping an emulated instruction also counts */
vmx_set_interrupt_shadow(vcpu, 0); vmx_set_interrupt_shadow(vcpu, 0);
return EMULATE_DONE; return 1;
} }
static inline void skip_emulated_instruction(struct kvm_vcpu *vcpu) static inline void skip_emulated_instruction(struct kvm_vcpu *vcpu)
...@@ -4468,7 +4468,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, ...@@ -4468,7 +4468,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
* Cause the #SS fault with 0 error code in VM86 mode. * Cause the #SS fault with 0 error code in VM86 mode.
*/ */
if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) { if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) {
if (kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE) { if (kvm_emulate_instruction(vcpu, 0)) {
if (vcpu->arch.halt_request) { if (vcpu->arch.halt_request) {
vcpu->arch.halt_request = 0; vcpu->arch.halt_request = 0;
return kvm_vcpu_halt(vcpu); return kvm_vcpu_halt(vcpu);
...@@ -4545,8 +4545,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) ...@@ -4545,8 +4545,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
return 1; return 1;
} }
return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP) != return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP);
EMULATE_USER_EXIT;
} }
/* /*
...@@ -4643,7 +4642,7 @@ static int handle_io(struct kvm_vcpu *vcpu) ...@@ -4643,7 +4642,7 @@ static int handle_io(struct kvm_vcpu *vcpu)
++vcpu->stat.io_exits; ++vcpu->stat.io_exits;
if (string) if (string)
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(vcpu, 0);
port = exit_qualification >> 16; port = exit_qualification >> 16;
size = (exit_qualification & 7) + 1; size = (exit_qualification & 7) + 1;
...@@ -4717,7 +4716,7 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val) ...@@ -4717,7 +4716,7 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
static int handle_desc(struct kvm_vcpu *vcpu) static int handle_desc(struct kvm_vcpu *vcpu)
{ {
WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP)); WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(vcpu, 0);
} }
static int handle_cr(struct kvm_vcpu *vcpu) static int handle_cr(struct kvm_vcpu *vcpu)
...@@ -4933,7 +4932,7 @@ static int handle_vmcall(struct kvm_vcpu *vcpu) ...@@ -4933,7 +4932,7 @@ static int handle_vmcall(struct kvm_vcpu *vcpu)
static int handle_invd(struct kvm_vcpu *vcpu) static int handle_invd(struct kvm_vcpu *vcpu)
{ {
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(vcpu, 0);
} }
static int handle_invlpg(struct kvm_vcpu *vcpu) static int handle_invlpg(struct kvm_vcpu *vcpu)
...@@ -5000,7 +4999,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu) ...@@ -5000,7 +4999,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
} }
} }
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE; return kvm_emulate_instruction(vcpu, 0);
} }
static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu) static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
...@@ -5077,7 +5076,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) ...@@ -5077,7 +5076,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
*/ */
return kvm_task_switch(vcpu, tss_selector, return kvm_task_switch(vcpu, tss_selector,
type == INTR_TYPE_SOFT_INTR ? idt_index : -1, type == INTR_TYPE_SOFT_INTR ? idt_index : -1,
reason, has_error_code, error_code) != EMULATE_USER_EXIT; reason, has_error_code, error_code);
} }
static int handle_ept_violation(struct kvm_vcpu *vcpu) static int handle_ept_violation(struct kvm_vcpu *vcpu)
...@@ -5149,8 +5148,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu) ...@@ -5149,8 +5148,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
if (!static_cpu_has(X86_FEATURE_HYPERVISOR)) if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
else else
return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) == return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP);
EMULATE_DONE;
} }
return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0); return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0);
...@@ -5169,7 +5167,6 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu) ...@@ -5169,7 +5167,6 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu)
static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
enum emulation_result err;
bool intr_window_requested; bool intr_window_requested;
unsigned count = 130; unsigned count = 130;
...@@ -5190,14 +5187,9 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) ...@@ -5190,14 +5187,9 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
if (kvm_test_request(KVM_REQ_EVENT, vcpu)) if (kvm_test_request(KVM_REQ_EVENT, vcpu))
return 1; return 1;
err = kvm_emulate_instruction(vcpu, 0); if (!kvm_emulate_instruction(vcpu, 0))
if (err == EMULATE_USER_EXIT)
return 0; return 0;
if (WARN_ON_ONCE(err == EMULATE_FAIL))
return 1;
if (vmx->emulation_required && !vmx->rmode.vm86_active && if (vmx->emulation_required && !vmx->rmode.vm86_active &&
vcpu->arch.exception.pending) { vcpu->arch.exception.pending) {
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
......
...@@ -5451,7 +5451,7 @@ int handle_ud(struct kvm_vcpu *vcpu) ...@@ -5451,7 +5451,7 @@ int handle_ud(struct kvm_vcpu *vcpu)
emul_type = EMULTYPE_TRAP_UD_FORCED; emul_type = EMULTYPE_TRAP_UD_FORCED;
} }
return kvm_emulate_instruction(vcpu, emul_type) != EMULATE_USER_EXIT; return kvm_emulate_instruction(vcpu, emul_type);
} }
EXPORT_SYMBOL_GPL(handle_ud); EXPORT_SYMBOL_GPL(handle_ud);
...@@ -6302,14 +6302,14 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type) ...@@ -6302,14 +6302,14 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
if (emulation_type & EMULTYPE_VMWARE_GP) { if (emulation_type & EMULTYPE_VMWARE_GP) {
kvm_queue_exception_e(vcpu, GP_VECTOR, 0); kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
return EMULATE_DONE; return 1;
} }
if (emulation_type & EMULTYPE_SKIP) { if (emulation_type & EMULTYPE_SKIP) {
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
vcpu->run->internal.ndata = 0; vcpu->run->internal.ndata = 0;
return EMULATE_USER_EXIT; return 0;
} }
kvm_queue_exception(vcpu, UD_VECTOR); kvm_queue_exception(vcpu, UD_VECTOR);
...@@ -6318,10 +6318,10 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type) ...@@ -6318,10 +6318,10 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
vcpu->run->internal.ndata = 0; vcpu->run->internal.ndata = 0;
return EMULATE_USER_EXIT; return 0;
} }
return EMULATE_DONE; return 1;
} }
static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2, static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2,
...@@ -6485,10 +6485,10 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu) ...@@ -6485,10 +6485,10 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu)
kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
kvm_run->debug.arch.exception = DB_VECTOR; kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->exit_reason = KVM_EXIT_DEBUG;
return EMULATE_USER_EXIT; return 0;
} }
kvm_queue_exception_p(vcpu, DB_VECTOR, DR6_BS); kvm_queue_exception_p(vcpu, DB_VECTOR, DR6_BS);
return EMULATE_DONE; return 1;
} }
int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
...@@ -6497,7 +6497,7 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -6497,7 +6497,7 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
int r; int r;
r = kvm_x86_ops->skip_emulated_instruction(vcpu); r = kvm_x86_ops->skip_emulated_instruction(vcpu);
if (unlikely(r != EMULATE_DONE)) if (unlikely(!r))
return 0; return 0;
/* /*
...@@ -6510,7 +6510,7 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -6510,7 +6510,7 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
*/ */
if (unlikely(rflags & X86_EFLAGS_TF)) if (unlikely(rflags & X86_EFLAGS_TF))
r = kvm_vcpu_do_singlestep(vcpu); r = kvm_vcpu_do_singlestep(vcpu);
return r == EMULATE_DONE; return r;
} }
EXPORT_SYMBOL_GPL(kvm_skip_emulated_instruction); EXPORT_SYMBOL_GPL(kvm_skip_emulated_instruction);
...@@ -6529,7 +6529,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r) ...@@ -6529,7 +6529,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
kvm_run->debug.arch.pc = eip; kvm_run->debug.arch.pc = eip;
kvm_run->debug.arch.exception = DB_VECTOR; kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->exit_reason = KVM_EXIT_DEBUG;
*r = EMULATE_USER_EXIT; *r = 0;
return true; return true;
} }
} }
...@@ -6545,7 +6545,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r) ...@@ -6545,7 +6545,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
vcpu->arch.dr6 &= ~DR_TRAP_BITS; vcpu->arch.dr6 &= ~DR_TRAP_BITS;
vcpu->arch.dr6 |= dr6 | DR6_RTM; vcpu->arch.dr6 |= dr6 | DR6_RTM;
kvm_queue_exception(vcpu, DB_VECTOR); kvm_queue_exception(vcpu, DB_VECTOR);
*r = EMULATE_DONE; *r = 1;
return true; return true;
} }
} }
...@@ -6632,11 +6632,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6632,11 +6632,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
if ((emulation_type & EMULTYPE_TRAP_UD) || if ((emulation_type & EMULTYPE_TRAP_UD) ||
(emulation_type & EMULTYPE_TRAP_UD_FORCED)) { (emulation_type & EMULTYPE_TRAP_UD_FORCED)) {
kvm_queue_exception(vcpu, UD_VECTOR); kvm_queue_exception(vcpu, UD_VECTOR);
return EMULATE_DONE; return 1;
} }
if (reexecute_instruction(vcpu, cr2, write_fault_to_spt, if (reexecute_instruction(vcpu, cr2, write_fault_to_spt,
emulation_type)) emulation_type))
return EMULATE_DONE; return 1;
if (ctxt->have_exception) { if (ctxt->have_exception) {
/* /*
* #UD should result in just EMULATION_FAILED, and trap-like * #UD should result in just EMULATION_FAILED, and trap-like
...@@ -6645,7 +6645,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6645,7 +6645,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
WARN_ON_ONCE(ctxt->exception.vector == UD_VECTOR || WARN_ON_ONCE(ctxt->exception.vector == UD_VECTOR ||
exception_type(ctxt->exception.vector) == EXCPT_TRAP); exception_type(ctxt->exception.vector) == EXCPT_TRAP);
inject_emulated_exception(vcpu); inject_emulated_exception(vcpu);
return EMULATE_DONE; return 1;
} }
return handle_emulation_failure(vcpu, emulation_type); return handle_emulation_failure(vcpu, emulation_type);
} }
...@@ -6654,7 +6654,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6654,7 +6654,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
if ((emulation_type & EMULTYPE_VMWARE_GP) && if ((emulation_type & EMULTYPE_VMWARE_GP) &&
!is_vmware_backdoor_opcode(ctxt)) { !is_vmware_backdoor_opcode(ctxt)) {
kvm_queue_exception_e(vcpu, GP_VECTOR, 0); kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
return EMULATE_DONE; return 1;
} }
if (emulation_type & EMULTYPE_SKIP) { if (emulation_type & EMULTYPE_SKIP) {
...@@ -6662,11 +6662,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6662,11 +6662,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
if (ctxt->eflags & X86_EFLAGS_RF) if (ctxt->eflags & X86_EFLAGS_RF)
kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF); kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
kvm_x86_ops->set_interrupt_shadow(vcpu, 0); kvm_x86_ops->set_interrupt_shadow(vcpu, 0);
return EMULATE_DONE; return 1;
} }
if (retry_instruction(ctxt, cr2, emulation_type)) if (retry_instruction(ctxt, cr2, emulation_type))
return EMULATE_DONE; return 1;
/* this is needed for vmware backdoor interface to work since it /* this is needed for vmware backdoor interface to work since it
changes registers values during IO operation */ changes registers values during IO operation */
...@@ -6682,18 +6682,18 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6682,18 +6682,18 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
r = x86_emulate_insn(ctxt); r = x86_emulate_insn(ctxt);
if (r == EMULATION_INTERCEPTED) if (r == EMULATION_INTERCEPTED)
return EMULATE_DONE; return 1;
if (r == EMULATION_FAILED) { if (r == EMULATION_FAILED) {
if (reexecute_instruction(vcpu, cr2, write_fault_to_spt, if (reexecute_instruction(vcpu, cr2, write_fault_to_spt,
emulation_type)) emulation_type))
return EMULATE_DONE; return 1;
return handle_emulation_failure(vcpu, emulation_type); return handle_emulation_failure(vcpu, emulation_type);
} }
if (ctxt->have_exception) { if (ctxt->have_exception) {
r = EMULATE_DONE; r = 1;
if (inject_emulated_exception(vcpu)) if (inject_emulated_exception(vcpu))
return r; return r;
} else if (vcpu->arch.pio.count) { } else if (vcpu->arch.pio.count) {
...@@ -6704,18 +6704,18 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6704,18 +6704,18 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
writeback = false; writeback = false;
vcpu->arch.complete_userspace_io = complete_emulated_pio; vcpu->arch.complete_userspace_io = complete_emulated_pio;
} }
r = EMULATE_USER_EXIT; r = 0;
} else if (vcpu->mmio_needed) { } else if (vcpu->mmio_needed) {
++vcpu->stat.mmio_exits; ++vcpu->stat.mmio_exits;
if (!vcpu->mmio_is_write) if (!vcpu->mmio_is_write)
writeback = false; writeback = false;
r = EMULATE_USER_EXIT; r = 0;
vcpu->arch.complete_userspace_io = complete_emulated_mmio; vcpu->arch.complete_userspace_io = complete_emulated_mmio;
} else if (r == EMULATION_RESTART) } else if (r == EMULATION_RESTART)
goto restart; goto restart;
else else
r = EMULATE_DONE; r = 1;
if (writeback) { if (writeback) {
unsigned long rflags = kvm_x86_ops->get_rflags(vcpu); unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
...@@ -6724,7 +6724,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, ...@@ -6724,7 +6724,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
if (!ctxt->have_exception || if (!ctxt->have_exception ||
exception_type(ctxt->exception.vector) == EXCPT_TRAP) { exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
kvm_rip_write(vcpu, ctxt->eip); kvm_rip_write(vcpu, ctxt->eip);
if (r == EMULATE_DONE && ctxt->tf) if (r && ctxt->tf)
r = kvm_vcpu_do_singlestep(vcpu); r = kvm_vcpu_do_singlestep(vcpu);
__kvm_set_rflags(vcpu, ctxt->eflags); __kvm_set_rflags(vcpu, ctxt->eflags);
} }
...@@ -8319,12 +8319,11 @@ static int vcpu_run(struct kvm_vcpu *vcpu) ...@@ -8319,12 +8319,11 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
static inline int complete_emulated_io(struct kvm_vcpu *vcpu) static inline int complete_emulated_io(struct kvm_vcpu *vcpu)
{ {
int r; int r;
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
r = kvm_emulate_instruction(vcpu, EMULTYPE_NO_DECODE); r = kvm_emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
if (r != EMULATE_DONE) return r;
return 0;
return 1;
} }
static int complete_emulated_pio(struct kvm_vcpu *vcpu) static int complete_emulated_pio(struct kvm_vcpu *vcpu)
...@@ -8696,13 +8695,13 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index, ...@@ -8696,13 +8695,13 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
vcpu->run->internal.ndata = 0; vcpu->run->internal.ndata = 0;
return EMULATE_USER_EXIT; return 0;
} }
kvm_rip_write(vcpu, ctxt->eip); kvm_rip_write(vcpu, ctxt->eip);
kvm_set_rflags(vcpu, ctxt->eflags); kvm_set_rflags(vcpu, ctxt->eflags);
kvm_make_request(KVM_REQ_EVENT, vcpu); kvm_make_request(KVM_REQ_EVENT, vcpu);
return EMULATE_DONE; return 1;
} }
EXPORT_SYMBOL_GPL(kvm_task_switch); EXPORT_SYMBOL_GPL(kvm_task_switch);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment