aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2010-01-20 12:20:20 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:36:01 -0500
commit138ac8d88f91e2a6a278aa5cee9120c714c4ce2d (patch)
tree6d271169762e5266db7d46fe0ea0f07e2a97663a /arch
parentf2483415293b180945da707e7dbe74e5daa72651 (diff)
KVM: VMX: Fix emulation of DR4 and DR5
Make sure DR4 and DR5 are aliased to DR6 and DR7, respectively, if CR4.DE is not set. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/vmx.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 9727773f24b7..c7b99e1f8aae 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3039,6 +3039,15 @@ static int handle_cr(struct kvm_vcpu *vcpu)
3039 return 0; 3039 return 0;
3040} 3040}
3041 3041
3042static int check_dr_alias(struct kvm_vcpu *vcpu)
3043{
3044 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
3045 kvm_queue_exception(vcpu, UD_VECTOR);
3046 return -1;
3047 }
3048 return 0;
3049}
3050
3042static int handle_dr(struct kvm_vcpu *vcpu) 3051static int handle_dr(struct kvm_vcpu *vcpu)
3043{ 3052{
3044 unsigned long exit_qualification; 3053 unsigned long exit_qualification;
@@ -3081,14 +3090,20 @@ static int handle_dr(struct kvm_vcpu *vcpu)
3081 case 0 ... 3: 3090 case 0 ... 3:
3082 val = vcpu->arch.db[dr]; 3091 val = vcpu->arch.db[dr];
3083 break; 3092 break;
3093 case 4:
3094 if (check_dr_alias(vcpu) < 0)
3095 return 1;
3096 /* fall through */
3084 case 6: 3097 case 6:
3085 val = vcpu->arch.dr6; 3098 val = vcpu->arch.dr6;
3086 break; 3099 break;
3087 case 7: 3100 case 5:
3101 if (check_dr_alias(vcpu) < 0)
3102 return 1;
3103 /* fall through */
3104 default: /* 7 */
3088 val = vcpu->arch.dr7; 3105 val = vcpu->arch.dr7;
3089 break; 3106 break;
3090 default:
3091 val = 0;
3092 } 3107 }
3093 kvm_register_write(vcpu, reg, val); 3108 kvm_register_write(vcpu, reg, val);
3094 } else { 3109 } else {
@@ -3099,12 +3114,10 @@ static int handle_dr(struct kvm_vcpu *vcpu)
3099 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) 3114 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
3100 vcpu->arch.eff_db[dr] = val; 3115 vcpu->arch.eff_db[dr] = val;
3101 break; 3116 break;
3102 case 4 ... 5: 3117 case 4:
3103 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) { 3118 if (check_dr_alias(vcpu) < 0)
3104 kvm_queue_exception(vcpu, UD_VECTOR);
3105 return 1; 3119 return 1;
3106 } 3120 /* fall through */
3107 break;
3108 case 6: 3121 case 6:
3109 if (val & 0xffffffff00000000ULL) { 3122 if (val & 0xffffffff00000000ULL) {
3110 kvm_inject_gp(vcpu, 0); 3123 kvm_inject_gp(vcpu, 0);
@@ -3112,7 +3125,11 @@ static int handle_dr(struct kvm_vcpu *vcpu)
3112 } 3125 }
3113 vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1; 3126 vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
3114 break; 3127 break;
3115 case 7: 3128 case 5:
3129 if (check_dr_alias(vcpu) < 0)
3130 return 1;
3131 /* fall through */
3132 default: /* 7 */
3116 if (val & 0xffffffff00000000ULL) { 3133 if (val & 0xffffffff00000000ULL) {
3117 kvm_inject_gp(vcpu, 0); 3134 kvm_inject_gp(vcpu, 0);
3118 return 1; 3135 return 1;