aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_host.h5
-rw-r--r--arch/x86/kvm/svm.c64
-rw-r--r--arch/x86/kvm/x86.c19
3 files changed, 33 insertions, 55 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a1f0b5dd7d75..d73ed48587e4 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -506,9 +506,8 @@ struct kvm_x86_ops {
506 void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); 506 void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
507 void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); 507 void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
508 void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); 508 void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
509 unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr); 509 int (*get_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long *dest);
510 void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value, 510 int (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value);
511 int *exception);
512 void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); 511 void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
513 unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); 512 unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
514 void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); 513 void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 8d7cb62ebef6..4295dfcc6031 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1122,76 +1122,70 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
1122 svm->vmcb->control.asid = sd->next_asid++; 1122 svm->vmcb->control.asid = sd->next_asid++;
1123} 1123}
1124 1124
1125static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr) 1125static int svm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *dest)
1126{ 1126{
1127 struct vcpu_svm *svm = to_svm(vcpu); 1127 struct vcpu_svm *svm = to_svm(vcpu);
1128 unsigned long val;
1129 1128
1130 switch (dr) { 1129 switch (dr) {
1131 case 0 ... 3: 1130 case 0 ... 3:
1132 val = vcpu->arch.db[dr]; 1131 *dest = vcpu->arch.db[dr];
1133 break; 1132 break;
1133 case 4:
1134 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
1135 return EMULATE_FAIL; /* will re-inject UD */
1136 /* fall through */
1134 case 6: 1137 case 6:
1135 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) 1138 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
1136 val = vcpu->arch.dr6; 1139 *dest = vcpu->arch.dr6;
1137 else 1140 else
1138 val = svm->vmcb->save.dr6; 1141 *dest = svm->vmcb->save.dr6;
1139 break; 1142 break;
1143 case 5:
1144 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
1145 return EMULATE_FAIL; /* will re-inject UD */
1146 /* fall through */
1140 case 7: 1147 case 7:
1141 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) 1148 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
1142 val = vcpu->arch.dr7; 1149 *dest = vcpu->arch.dr7;
1143 else 1150 else
1144 val = svm->vmcb->save.dr7; 1151 *dest = svm->vmcb->save.dr7;
1145 break; 1152 break;
1146 default:
1147 val = 0;
1148 } 1153 }
1149 1154
1150 return val; 1155 return EMULATE_DONE;
1151} 1156}
1152 1157
1153static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, 1158static int svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value)
1154 int *exception)
1155{ 1159{
1156 struct vcpu_svm *svm = to_svm(vcpu); 1160 struct vcpu_svm *svm = to_svm(vcpu);
1157 1161
1158 *exception = 0;
1159
1160 switch (dr) { 1162 switch (dr) {
1161 case 0 ... 3: 1163 case 0 ... 3:
1162 vcpu->arch.db[dr] = value; 1164 vcpu->arch.db[dr] = value;
1163 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) 1165 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
1164 vcpu->arch.eff_db[dr] = value; 1166 vcpu->arch.eff_db[dr] = value;
1165 return; 1167 break;
1166 case 4 ... 5: 1168 case 4:
1167 if (vcpu->arch.cr4 & X86_CR4_DE) 1169 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
1168 *exception = UD_VECTOR; 1170 return EMULATE_FAIL; /* will re-inject UD */
1169 return; 1171 /* fall through */
1170 case 6: 1172 case 6:
1171 if (value & 0xffffffff00000000ULL) {
1172 *exception = GP_VECTOR;
1173 return;
1174 }
1175 vcpu->arch.dr6 = (value & DR6_VOLATILE) | DR6_FIXED_1; 1173 vcpu->arch.dr6 = (value & DR6_VOLATILE) | DR6_FIXED_1;
1176 return; 1174 break;
1175 case 5:
1176 if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
1177 return EMULATE_FAIL; /* will re-inject UD */
1178 /* fall through */
1177 case 7: 1179 case 7:
1178 if (value & 0xffffffff00000000ULL) {
1179 *exception = GP_VECTOR;
1180 return;
1181 }
1182 vcpu->arch.dr7 = (value & DR7_VOLATILE) | DR7_FIXED_1; 1180 vcpu->arch.dr7 = (value & DR7_VOLATILE) | DR7_FIXED_1;
1183 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { 1181 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
1184 svm->vmcb->save.dr7 = vcpu->arch.dr7; 1182 svm->vmcb->save.dr7 = vcpu->arch.dr7;
1185 vcpu->arch.switch_db_regs = (value & DR7_BP_EN_MASK); 1183 vcpu->arch.switch_db_regs = (value & DR7_BP_EN_MASK);
1186 } 1184 }
1187 return; 1185 break;
1188 default:
1189 /* FIXME: Possible case? */
1190 printk(KERN_DEBUG "%s: unexpected dr %u\n",
1191 __func__, dr);
1192 *exception = UD_VECTOR;
1193 return;
1194 } 1186 }
1187
1188 return EMULATE_DONE;
1195} 1189}
1196 1190
1197static int pf_interception(struct vcpu_svm *svm) 1191static int pf_interception(struct vcpu_svm *svm)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 322c2c5f9bc4..fd5101b57fa3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3270,29 +3270,14 @@ int emulate_clts(struct kvm_vcpu *vcpu)
3270 3270
3271int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest) 3271int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
3272{ 3272{
3273 struct kvm_vcpu *vcpu = ctxt->vcpu; 3273 return kvm_x86_ops->get_dr(ctxt->vcpu, dr, dest);
3274
3275 switch (dr) {
3276 case 0 ... 3:
3277 *dest = kvm_x86_ops->get_dr(vcpu, dr);
3278 return X86EMUL_CONTINUE;
3279 default:
3280 pr_unimpl(vcpu, "%s: unexpected dr %u\n", __func__, dr);
3281 return X86EMUL_UNHANDLEABLE;
3282 }
3283} 3274}
3284 3275
3285int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value) 3276int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
3286{ 3277{
3287 unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U; 3278 unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
3288 int exception;
3289 3279
3290 kvm_x86_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception); 3280 return kvm_x86_ops->set_dr(ctxt->vcpu, dr, value & mask);
3291 if (exception) {
3292 /* FIXME: better handling */
3293 return X86EMUL_UNHANDLEABLE;
3294 }
3295 return X86EMUL_CONTINUE;
3296} 3281}
3297 3282
3298void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) 3283void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)