diff options
author | Andre Przywara <andre.przywara@amd.com> | 2010-12-21 05:12:00 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-01-12 04:30:58 -0500 |
commit | eea1cff9ab732ea56358ff5e1bd8b99db2e8402d (patch) | |
tree | 000abd8fa64f58602ebfc03b09e1f394c72f4ad7 /arch/x86/kvm/x86.c | |
parent | a63512a4d711c9bd6a5d03847f45fcf88cdea0c6 (diff) |
KVM: x86: fix CR8 handling
The handling of CR8 writes in KVM is currently somewhat cumbersome.
This patch makes it look like the other CR register handlers
and fixes a possible issue in VMX, where the RIP would be incremented
despite an injected #GP.
Signed-off-by: Andre Przywara <andre.przywara@amd.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 | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f569da8ff839..2dbf68cd46e3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -662,7 +662,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | |||
662 | } | 662 | } |
663 | EXPORT_SYMBOL_GPL(kvm_set_cr3); | 663 | EXPORT_SYMBOL_GPL(kvm_set_cr3); |
664 | 664 | ||
665 | int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | 665 | int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) |
666 | { | 666 | { |
667 | if (cr8 & CR8_RESERVED_BITS) | 667 | if (cr8 & CR8_RESERVED_BITS) |
668 | return 1; | 668 | return 1; |
@@ -672,12 +672,6 @@ int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | |||
672 | vcpu->arch.cr8 = cr8; | 672 | vcpu->arch.cr8 = cr8; |
673 | return 0; | 673 | return 0; |
674 | } | 674 | } |
675 | |||
676 | void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | ||
677 | { | ||
678 | if (__kvm_set_cr8(vcpu, cr8)) | ||
679 | kvm_inject_gp(vcpu, 0); | ||
680 | } | ||
681 | EXPORT_SYMBOL_GPL(kvm_set_cr8); | 675 | EXPORT_SYMBOL_GPL(kvm_set_cr8); |
682 | 676 | ||
683 | unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) | 677 | unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) |
@@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu) | |||
4104 | res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); | 4098 | res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); |
4105 | break; | 4099 | break; |
4106 | case 8: | 4100 | case 8: |
4107 | res = __kvm_set_cr8(vcpu, val & 0xfUL); | 4101 | res = kvm_set_cr8(vcpu, val); |
4108 | break; | 4102 | break; |
4109 | default: | 4103 | default: |
4110 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); | 4104 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); |
@@ -5381,8 +5375,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
5381 | } | 5375 | } |
5382 | 5376 | ||
5383 | /* re-sync apic's tpr */ | 5377 | /* re-sync apic's tpr */ |
5384 | if (!irqchip_in_kernel(vcpu->kvm)) | 5378 | if (!irqchip_in_kernel(vcpu->kvm)) { |
5385 | kvm_set_cr8(vcpu, kvm_run->cr8); | 5379 | if (kvm_set_cr8(vcpu, kvm_run->cr8) != 0) { |
5380 | r = -EINVAL; | ||
5381 | goto out; | ||
5382 | } | ||
5383 | } | ||
5386 | 5384 | ||
5387 | if (vcpu->arch.pio.count || vcpu->mmio_needed) { | 5385 | if (vcpu->arch.pio.count || vcpu->mmio_needed) { |
5388 | if (vcpu->mmio_needed) { | 5386 | if (vcpu->mmio_needed) { |