aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c114
1 files changed, 98 insertions, 16 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c776868ffe41..0989776ee7b0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2311,7 +2311,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
2311 kvm_rip_write(vcpu, 0); 2311 kvm_rip_write(vcpu, 0);
2312 kvm_register_write(vcpu, VCPU_REGS_RSP, 0); 2312 kvm_register_write(vcpu, VCPU_REGS_RSP, 0);
2313 2313
2314 /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */
2315 vmcs_writel(GUEST_DR7, 0x400); 2314 vmcs_writel(GUEST_DR7, 0x400);
2316 2315
2317 vmcs_writel(GUEST_GDTR_BASE, 0); 2316 vmcs_writel(GUEST_GDTR_BASE, 0);
@@ -2577,7 +2576,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2577{ 2576{
2578 struct vcpu_vmx *vmx = to_vmx(vcpu); 2577 struct vcpu_vmx *vmx = to_vmx(vcpu);
2579 u32 intr_info, ex_no, error_code; 2578 u32 intr_info, ex_no, error_code;
2580 unsigned long cr2, rip; 2579 unsigned long cr2, rip, dr6;
2581 u32 vect_info; 2580 u32 vect_info;
2582 enum emulation_result er; 2581 enum emulation_result er;
2583 2582
@@ -2637,14 +2636,28 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2637 } 2636 }
2638 2637
2639 ex_no = intr_info & INTR_INFO_VECTOR_MASK; 2638 ex_no = intr_info & INTR_INFO_VECTOR_MASK;
2640 if (ex_no == DB_VECTOR || ex_no == BP_VECTOR) { 2639 switch (ex_no) {
2640 case DB_VECTOR:
2641 dr6 = vmcs_readl(EXIT_QUALIFICATION);
2642 if (!(vcpu->guest_debug &
2643 (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
2644 vcpu->arch.dr6 = dr6 | DR6_FIXED_1;
2645 kvm_queue_exception(vcpu, DB_VECTOR);
2646 return 1;
2647 }
2648 kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
2649 kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
2650 /* fall through */
2651 case BP_VECTOR:
2641 kvm_run->exit_reason = KVM_EXIT_DEBUG; 2652 kvm_run->exit_reason = KVM_EXIT_DEBUG;
2642 kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; 2653 kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
2643 kvm_run->debug.arch.exception = ex_no; 2654 kvm_run->debug.arch.exception = ex_no;
2644 } else { 2655 break;
2656 default:
2645 kvm_run->exit_reason = KVM_EXIT_EXCEPTION; 2657 kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
2646 kvm_run->ex.exception = ex_no; 2658 kvm_run->ex.exception = ex_no;
2647 kvm_run->ex.error_code = error_code; 2659 kvm_run->ex.error_code = error_code;
2660 break;
2648 } 2661 }
2649 return 0; 2662 return 0;
2650} 2663}
@@ -2784,21 +2797,44 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2784 unsigned long val; 2797 unsigned long val;
2785 int dr, reg; 2798 int dr, reg;
2786 2799
2787 /* 2800 dr = vmcs_readl(GUEST_DR7);
2788 * FIXME: this code assumes the host is debugging the guest. 2801 if (dr & DR7_GD) {
2789 * need to deal with guest debugging itself too. 2802 /*
2790 */ 2803 * As the vm-exit takes precedence over the debug trap, we
2804 * need to emulate the latter, either for the host or the
2805 * guest debugging itself.
2806 */
2807 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
2808 kvm_run->debug.arch.dr6 = vcpu->arch.dr6;
2809 kvm_run->debug.arch.dr7 = dr;
2810 kvm_run->debug.arch.pc =
2811 vmcs_readl(GUEST_CS_BASE) +
2812 vmcs_readl(GUEST_RIP);
2813 kvm_run->debug.arch.exception = DB_VECTOR;
2814 kvm_run->exit_reason = KVM_EXIT_DEBUG;
2815 return 0;
2816 } else {
2817 vcpu->arch.dr7 &= ~DR7_GD;
2818 vcpu->arch.dr6 |= DR6_BD;
2819 vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
2820 kvm_queue_exception(vcpu, DB_VECTOR);
2821 return 1;
2822 }
2823 }
2824
2791 exit_qualification = vmcs_readl(EXIT_QUALIFICATION); 2825 exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
2792 dr = exit_qualification & 7; 2826 dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
2793 reg = (exit_qualification >> 8) & 15; 2827 reg = DEBUG_REG_ACCESS_REG(exit_qualification);
2794 if (exit_qualification & 16) { 2828 if (exit_qualification & TYPE_MOV_FROM_DR) {
2795 /* mov from dr */
2796 switch (dr) { 2829 switch (dr) {
2830 case 0 ... 3:
2831 val = vcpu->arch.db[dr];
2832 break;
2797 case 6: 2833 case 6:
2798 val = 0xffff0ff0; 2834 val = vcpu->arch.dr6;
2799 break; 2835 break;
2800 case 7: 2836 case 7:
2801 val = 0x400; 2837 val = vcpu->arch.dr7;
2802 break; 2838 break;
2803 default: 2839 default:
2804 val = 0; 2840 val = 0;
@@ -2806,7 +2842,38 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2806 kvm_register_write(vcpu, reg, val); 2842 kvm_register_write(vcpu, reg, val);
2807 KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler); 2843 KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
2808 } else { 2844 } else {
2809 /* mov to dr */ 2845 val = vcpu->arch.regs[reg];
2846 switch (dr) {
2847 case 0 ... 3:
2848 vcpu->arch.db[dr] = val;
2849 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
2850 vcpu->arch.eff_db[dr] = val;
2851 break;
2852 case 4 ... 5:
2853 if (vcpu->arch.cr4 & X86_CR4_DE)
2854 kvm_queue_exception(vcpu, UD_VECTOR);
2855 break;
2856 case 6:
2857 if (val & 0xffffffff00000000ULL) {
2858 kvm_queue_exception(vcpu, GP_VECTOR);
2859 break;
2860 }
2861 vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
2862 break;
2863 case 7:
2864 if (val & 0xffffffff00000000ULL) {
2865 kvm_queue_exception(vcpu, GP_VECTOR);
2866 break;
2867 }
2868 vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1;
2869 if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
2870 vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
2871 vcpu->arch.switch_db_regs =
2872 (val & DR7_BP_EN_MASK);
2873 }
2874 break;
2875 }
2876 KVMTRACE_2D(DR_WRITE, vcpu, (u32)dr, (u32)val, handler);
2810 } 2877 }
2811 skip_emulated_instruction(vcpu); 2878 skip_emulated_instruction(vcpu);
2812 return 1; 2879 return 1;
@@ -2957,7 +3024,18 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2957 } 3024 }
2958 tss_selector = exit_qualification; 3025 tss_selector = exit_qualification;
2959 3026
2960 return kvm_task_switch(vcpu, tss_selector, reason); 3027 if (!kvm_task_switch(vcpu, tss_selector, reason))
3028 return 0;
3029
3030 /* clear all local breakpoint enable flags */
3031 vmcs_writel(GUEST_DR7, vmcs_readl(GUEST_DR7) & ~55);
3032
3033 /*
3034 * TODO: What about debug traps on tss switch?
3035 * Are we supposed to inject them and update dr6?
3036 */
3037
3038 return 1;
2961} 3039}
2962 3040
2963static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3041static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -3342,6 +3420,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3342 */ 3420 */
3343 vmcs_writel(HOST_CR0, read_cr0()); 3421 vmcs_writel(HOST_CR0, read_cr0());
3344 3422
3423 set_debugreg(vcpu->arch.dr6, 6);
3424
3345 asm( 3425 asm(
3346 /* Store host registers */ 3426 /* Store host registers */
3347 "push %%"R"dx; push %%"R"bp;" 3427 "push %%"R"dx; push %%"R"bp;"
@@ -3436,6 +3516,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3436 vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)); 3516 vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
3437 vcpu->arch.regs_dirty = 0; 3517 vcpu->arch.regs_dirty = 0;
3438 3518
3519 get_debugreg(vcpu->arch.dr6, 6);
3520
3439 vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); 3521 vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
3440 if (vmx->rmode.irq.pending) 3522 if (vmx->rmode.irq.pending)
3441 fixup_rmode_irq(vmx); 3523 fixup_rmode_irq(vmx);