diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 93 |
1 files changed, 36 insertions, 57 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 1d974c1eaa7d..f55690ddb3ac 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -480,8 +480,13 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) | |||
480 | eb = (1u << PF_VECTOR) | (1u << UD_VECTOR); | 480 | eb = (1u << PF_VECTOR) | (1u << UD_VECTOR); |
481 | if (!vcpu->fpu_active) | 481 | if (!vcpu->fpu_active) |
482 | eb |= 1u << NM_VECTOR; | 482 | eb |= 1u << NM_VECTOR; |
483 | if (vcpu->guest_debug.enabled) | 483 | if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) { |
484 | eb |= 1u << DB_VECTOR; | 484 | if (vcpu->guest_debug & |
485 | (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) | ||
486 | eb |= 1u << DB_VECTOR; | ||
487 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) | ||
488 | eb |= 1u << BP_VECTOR; | ||
489 | } | ||
485 | if (vcpu->arch.rmode.active) | 490 | if (vcpu->arch.rmode.active) |
486 | eb = ~0; | 491 | eb = ~0; |
487 | if (vm_need_ept()) | 492 | if (vm_need_ept()) |
@@ -1003,40 +1008,23 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg) | |||
1003 | } | 1008 | } |
1004 | } | 1009 | } |
1005 | 1010 | ||
1006 | static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | 1011 | static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) |
1007 | { | 1012 | { |
1008 | unsigned long dr7 = 0x400; | 1013 | int old_debug = vcpu->guest_debug; |
1009 | int old_singlestep; | 1014 | unsigned long flags; |
1010 | |||
1011 | old_singlestep = vcpu->guest_debug.singlestep; | ||
1012 | |||
1013 | vcpu->guest_debug.enabled = dbg->enabled; | ||
1014 | if (vcpu->guest_debug.enabled) { | ||
1015 | int i; | ||
1016 | |||
1017 | dr7 |= 0x200; /* exact */ | ||
1018 | for (i = 0; i < 4; ++i) { | ||
1019 | if (!dbg->breakpoints[i].enabled) | ||
1020 | continue; | ||
1021 | vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address; | ||
1022 | dr7 |= 2 << (i*2); /* global enable */ | ||
1023 | dr7 |= 0 << (i*4+16); /* execution breakpoint */ | ||
1024 | } | ||
1025 | |||
1026 | vcpu->guest_debug.singlestep = dbg->singlestep; | ||
1027 | } else | ||
1028 | vcpu->guest_debug.singlestep = 0; | ||
1029 | 1015 | ||
1030 | if (old_singlestep && !vcpu->guest_debug.singlestep) { | 1016 | vcpu->guest_debug = dbg->control; |
1031 | unsigned long flags; | 1017 | if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE)) |
1018 | vcpu->guest_debug = 0; | ||
1032 | 1019 | ||
1033 | flags = vmcs_readl(GUEST_RFLAGS); | 1020 | flags = vmcs_readl(GUEST_RFLAGS); |
1021 | if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) | ||
1022 | flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; | ||
1023 | else if (old_debug & KVM_GUESTDBG_SINGLESTEP) | ||
1034 | flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); | 1024 | flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); |
1035 | vmcs_writel(GUEST_RFLAGS, flags); | 1025 | vmcs_writel(GUEST_RFLAGS, flags); |
1036 | } | ||
1037 | 1026 | ||
1038 | update_exception_bitmap(vcpu); | 1027 | update_exception_bitmap(vcpu); |
1039 | vmcs_writel(GUEST_DR7, dr7); | ||
1040 | 1028 | ||
1041 | return 0; | 1029 | return 0; |
1042 | } | 1030 | } |
@@ -2540,24 +2528,6 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr) | |||
2540 | return 0; | 2528 | return 0; |
2541 | } | 2529 | } |
2542 | 2530 | ||
2543 | static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) | ||
2544 | { | ||
2545 | struct kvm_guest_debug *dbg = &vcpu->guest_debug; | ||
2546 | |||
2547 | set_debugreg(dbg->bp[0], 0); | ||
2548 | set_debugreg(dbg->bp[1], 1); | ||
2549 | set_debugreg(dbg->bp[2], 2); | ||
2550 | set_debugreg(dbg->bp[3], 3); | ||
2551 | |||
2552 | if (dbg->singlestep) { | ||
2553 | unsigned long flags; | ||
2554 | |||
2555 | flags = vmcs_readl(GUEST_RFLAGS); | ||
2556 | flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; | ||
2557 | vmcs_writel(GUEST_RFLAGS, flags); | ||
2558 | } | ||
2559 | } | ||
2560 | |||
2561 | static int handle_rmode_exception(struct kvm_vcpu *vcpu, | 2531 | static int handle_rmode_exception(struct kvm_vcpu *vcpu, |
2562 | int vec, u32 err_code) | 2532 | int vec, u32 err_code) |
2563 | { | 2533 | { |
@@ -2574,9 +2544,17 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, | |||
2574 | * the required debugging infrastructure rework. | 2544 | * the required debugging infrastructure rework. |
2575 | */ | 2545 | */ |
2576 | switch (vec) { | 2546 | switch (vec) { |
2577 | case DE_VECTOR: | ||
2578 | case DB_VECTOR: | 2547 | case DB_VECTOR: |
2548 | if (vcpu->guest_debug & | ||
2549 | (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) | ||
2550 | return 0; | ||
2551 | kvm_queue_exception(vcpu, vec); | ||
2552 | return 1; | ||
2579 | case BP_VECTOR: | 2553 | case BP_VECTOR: |
2554 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) | ||
2555 | return 0; | ||
2556 | /* fall through */ | ||
2557 | case DE_VECTOR: | ||
2580 | case OF_VECTOR: | 2558 | case OF_VECTOR: |
2581 | case BR_VECTOR: | 2559 | case BR_VECTOR: |
2582 | case UD_VECTOR: | 2560 | case UD_VECTOR: |
@@ -2593,7 +2571,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, | |||
2593 | static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 2571 | static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
2594 | { | 2572 | { |
2595 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 2573 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
2596 | u32 intr_info, error_code; | 2574 | u32 intr_info, ex_no, error_code; |
2597 | unsigned long cr2, rip; | 2575 | unsigned long cr2, rip; |
2598 | u32 vect_info; | 2576 | u32 vect_info; |
2599 | enum emulation_result er; | 2577 | enum emulation_result er; |
@@ -2653,14 +2631,16 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2653 | return 1; | 2631 | return 1; |
2654 | } | 2632 | } |
2655 | 2633 | ||
2656 | if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == | 2634 | ex_no = intr_info & INTR_INFO_VECTOR_MASK; |
2657 | (INTR_TYPE_HARD_EXCEPTION | 1)) { | 2635 | if (ex_no == DB_VECTOR || ex_no == BP_VECTOR) { |
2658 | kvm_run->exit_reason = KVM_EXIT_DEBUG; | 2636 | kvm_run->exit_reason = KVM_EXIT_DEBUG; |
2659 | return 0; | 2637 | kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; |
2638 | kvm_run->debug.arch.exception = ex_no; | ||
2639 | } else { | ||
2640 | kvm_run->exit_reason = KVM_EXIT_EXCEPTION; | ||
2641 | kvm_run->ex.exception = ex_no; | ||
2642 | kvm_run->ex.error_code = error_code; | ||
2660 | } | 2643 | } |
2661 | kvm_run->exit_reason = KVM_EXIT_EXCEPTION; | ||
2662 | kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK; | ||
2663 | kvm_run->ex.error_code = error_code; | ||
2664 | return 0; | 2644 | return 0; |
2665 | } | 2645 | } |
2666 | 2646 | ||
@@ -3600,7 +3580,6 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
3600 | .vcpu_put = vmx_vcpu_put, | 3580 | .vcpu_put = vmx_vcpu_put, |
3601 | 3581 | ||
3602 | .set_guest_debug = set_guest_debug, | 3582 | .set_guest_debug = set_guest_debug, |
3603 | .guest_debug_pre = kvm_guest_debug_pre, | ||
3604 | .get_msr = vmx_get_msr, | 3583 | .get_msr = vmx_get_msr, |
3605 | .set_msr = vmx_set_msr, | 3584 | .set_msr = vmx_set_msr, |
3606 | .get_segment_base = vmx_get_segment_base, | 3585 | .get_segment_base = vmx_get_segment_base, |