diff options
author | Nadav Amit <nadav.amit@gmail.com> | 2014-06-18 10:19:23 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-06-19 06:52:14 -0400 |
commit | 5777392e83c96e3a0799dd2985598e0fc76cf4aa (patch) | |
tree | b9b9d7ee6afe5d0e1864750b292abd2bb11fea53 | |
parent | 5381417f6a51293e7b8af1eb18aefa5d47976a71 (diff) |
KVM: x86: check DR6/7 high-bits are clear only on long-mode
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>
-rw-r--r-- | arch/x86/kvm/vmx.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/x86.h | 18 |
2 files changed, 19 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a717c13b9466..b362a1a38e51 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -5184,7 +5184,7 @@ static int handle_dr(struct kvm_vcpu *vcpu) | |||
5184 | return 1; | 5184 | return 1; |
5185 | kvm_register_write(vcpu, reg, val); | 5185 | kvm_register_write(vcpu, reg, val); |
5186 | } else | 5186 | } else |
5187 | if (kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg))) | 5187 | if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg))) |
5188 | return 1; | 5188 | return 1; |
5189 | 5189 | ||
5190 | skip_emulated_instruction(vcpu); | 5190 | skip_emulated_instruction(vcpu); |
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 8c97bac9a895..c5b61a7eb144 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h | |||
@@ -47,6 +47,16 @@ static inline int is_long_mode(struct kvm_vcpu *vcpu) | |||
47 | #endif | 47 | #endif |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu) | ||
51 | { | ||
52 | int cs_db, cs_l; | ||
53 | |||
54 | if (!is_long_mode(vcpu)) | ||
55 | return false; | ||
56 | kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | ||
57 | return cs_l; | ||
58 | } | ||
59 | |||
50 | static inline bool mmu_is_nested(struct kvm_vcpu *vcpu) | 60 | static inline bool mmu_is_nested(struct kvm_vcpu *vcpu) |
51 | { | 61 | { |
52 | return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu; | 62 | 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) | |||
108 | return false; | 118 | return false; |
109 | } | 119 | } |
110 | 120 | ||
121 | static inline unsigned long kvm_register_readl(struct kvm_vcpu *vcpu, | ||
122 | enum kvm_reg reg) | ||
123 | { | ||
124 | unsigned long val = kvm_register_read(vcpu, reg); | ||
125 | |||
126 | return is_64_bit_mode(vcpu) ? val : (u32)val; | ||
127 | } | ||
128 | |||
111 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); | 129 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); |
112 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); | 130 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); |
113 | int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); | 131 | int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); |