diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-05-10 04:16:56 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:35:40 -0400 |
commit | 6d77dbfc88e37c9efd5c5dd18445cfe819ae17ea (patch) | |
tree | 96a3afb750d254a99dd43fa4730fd6ff187eb2a0 /arch/x86/kvm/vmx.c | |
parent | 57bc24cfd655c912498983130326b312e0404db1 (diff) |
KVM: inject #UD if instruction emulation fails and exit to userspace
Do not kill VM when instruction emulation fails. Inject #UD and report
failure to userspace instead. Userspace may choose to reenter guest if
vcpu is in userspace (cpl == 3) in which case guest OS will kill
offending process and continue running.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 28 |
1 files changed, 4 insertions, 24 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 598931734251..a82cfa1e2a40 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3070,7 +3070,7 @@ static int handle_io(struct kvm_vcpu *vcpu) | |||
3070 | ++vcpu->stat.io_exits; | 3070 | ++vcpu->stat.io_exits; |
3071 | 3071 | ||
3072 | if (string || in) | 3072 | if (string || in) |
3073 | return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO); | 3073 | return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE; |
3074 | 3074 | ||
3075 | port = exit_qualification >> 16; | 3075 | port = exit_qualification >> 16; |
3076 | size = (exit_qualification & 7) + 1; | 3076 | size = (exit_qualification & 7) + 1; |
@@ -3327,22 +3327,7 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu) | |||
3327 | 3327 | ||
3328 | static int handle_apic_access(struct kvm_vcpu *vcpu) | 3328 | static int handle_apic_access(struct kvm_vcpu *vcpu) |
3329 | { | 3329 | { |
3330 | unsigned long exit_qualification; | 3330 | return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE; |
3331 | enum emulation_result er; | ||
3332 | unsigned long offset; | ||
3333 | |||
3334 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | ||
3335 | offset = exit_qualification & 0xffful; | ||
3336 | |||
3337 | er = emulate_instruction(vcpu, 0, 0, 0); | ||
3338 | |||
3339 | if (er != EMULATE_DONE) { | ||
3340 | printk(KERN_ERR | ||
3341 | "Fail to handle apic access vmexit! Offset is 0x%lx\n", | ||
3342 | offset); | ||
3343 | return -ENOEXEC; | ||
3344 | } | ||
3345 | return 1; | ||
3346 | } | 3331 | } |
3347 | 3332 | ||
3348 | static int handle_task_switch(struct kvm_vcpu *vcpu) | 3333 | static int handle_task_switch(struct kvm_vcpu *vcpu) |
@@ -3554,13 +3539,8 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) | |||
3554 | goto out; | 3539 | goto out; |
3555 | } | 3540 | } |
3556 | 3541 | ||
3557 | if (err != EMULATE_DONE) { | 3542 | if (err != EMULATE_DONE) |
3558 | vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | 3543 | return 0; |
3559 | vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; | ||
3560 | vcpu->run->internal.ndata = 0; | ||
3561 | ret = 0; | ||
3562 | goto out; | ||
3563 | } | ||
3564 | 3544 | ||
3565 | if (signal_pending(current)) | 3545 | if (signal_pending(current)) |
3566 | goto out; | 3546 | goto out; |