KVM: x86: check DR6/7 high-bits are clear only on long-mode
authorNadav Amit <nadav.amit@gmail.com>
Wed, 18 Jun 2014 14:19:23 +0000 (17:19 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 19 Jun 2014 10:52:14 +0000 (12:52 +0200)
When the guest sets DR6 and DR7, KVM asserts the high 32-bits are clear, and
otherwise injects a #GP exception. This exception should only be injected only
if running in long-mode.

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.h

index a717c13b9466ded9d4e1a869fcc76ac63d676dd2..b362a1a38e518910b6729a879c0bc79c8cc8d71b 100644 (file)
@@ -5184,7 +5184,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
                        return 1;
                kvm_register_write(vcpu, reg, val);
        } else
-               if (kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)))
+               if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
                        return 1;
 
        skip_emulated_instruction(vcpu);
index 8c97bac9a895a335cb90f5b220bf65cff43f0ffc..c5b61a7eb1441cbda53467747d1ce5d918ff2a25 100644 (file)
@@ -47,6 +47,16 @@ static inline int is_long_mode(struct kvm_vcpu *vcpu)
 #endif
 }
 
+static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu)
+{
+       int cs_db, cs_l;
+
+       if (!is_long_mode(vcpu))
+               return false;
+       kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+       return cs_l;
+}
+
 static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu;
@@ -108,6 +118,14 @@ static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
        return false;
 }
 
+static inline unsigned long kvm_register_readl(struct kvm_vcpu *vcpu,
+                                              enum kvm_reg reg)
+{
+       unsigned long val = kvm_register_read(vcpu, reg);
+
+       return is_64_bit_mode(vcpu) ? val : (u32)val;
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);