diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2010-01-20 12:20:20 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:36:01 -0500 |
commit | 138ac8d88f91e2a6a278aa5cee9120c714c4ce2d (patch) | |
tree | 6d271169762e5266db7d46fe0ea0f07e2a97663a /arch | |
parent | f2483415293b180945da707e7dbe74e5daa72651 (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.c | 35 |
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 | ||
3042 | static 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 | |||
3042 | static int handle_dr(struct kvm_vcpu *vcpu) | 3051 | static 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; |