diff options
author | Avi Kivity <avi@redhat.com> | 2010-06-10 10:02:14 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:46:32 -0400 |
commit | 49a9b07edcf4aff159c1f3d3a27e58cf38bc27cd (patch) | |
tree | 750ff11b09e7baa3f4c811ce7c85bf7546b051ae /arch/x86/kvm/x86.c | |
parent | 2acf923e38fb6a4ce0c57115decbb38d334902ac (diff) |
KVM: Fix mov cr0 #GP at wrong instruction
On Intel, we call skip_emulated_instruction() even if we injected a #GP,
resulting in the #GP pointing at the wrong address.
Fix by injecting the exception and skipping the instruction at the same place,
so we can do just one or the other.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 12 |
1 files changed, 3 insertions, 9 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b5e644701cc1..05e9b5dde646 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -425,7 +425,7 @@ out: | |||
425 | return changed; | 425 | return changed; |
426 | } | 426 | } |
427 | 427 | ||
428 | static int __kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | 428 | int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) |
429 | { | 429 | { |
430 | unsigned long old_cr0 = kvm_read_cr0(vcpu); | 430 | unsigned long old_cr0 = kvm_read_cr0(vcpu); |
431 | unsigned long update_bits = X86_CR0_PG | X86_CR0_WP | | 431 | unsigned long update_bits = X86_CR0_PG | X86_CR0_WP | |
@@ -468,17 +468,11 @@ static int __kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
468 | kvm_mmu_reset_context(vcpu); | 468 | kvm_mmu_reset_context(vcpu); |
469 | return 0; | 469 | return 0; |
470 | } | 470 | } |
471 | |||
472 | void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | ||
473 | { | ||
474 | if (__kvm_set_cr0(vcpu, cr0)) | ||
475 | kvm_inject_gp(vcpu, 0); | ||
476 | } | ||
477 | EXPORT_SYMBOL_GPL(kvm_set_cr0); | 471 | EXPORT_SYMBOL_GPL(kvm_set_cr0); |
478 | 472 | ||
479 | void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) | 473 | void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) |
480 | { | 474 | { |
481 | kvm_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~0x0eul) | (msw & 0x0f)); | 475 | (void)kvm_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~0x0eul) | (msw & 0x0f)); |
482 | } | 476 | } |
483 | EXPORT_SYMBOL_GPL(kvm_lmsw); | 477 | EXPORT_SYMBOL_GPL(kvm_lmsw); |
484 | 478 | ||
@@ -3732,7 +3726,7 @@ static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu) | |||
3732 | 3726 | ||
3733 | switch (cr) { | 3727 | switch (cr) { |
3734 | case 0: | 3728 | case 0: |
3735 | res = __kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val)); | 3729 | res = kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val)); |
3736 | break; | 3730 | break; |
3737 | case 2: | 3731 | case 2: |
3738 | vcpu->arch.cr2 = val; | 3732 | vcpu->arch.cr2 = val; |