| From f85d40160691881a17a397c448d799dfc90987ba Mon Sep 17 00:00:00 2001 |
| From: Lai Jiangshan <laijs@linux.alibaba.com> |
| Date: Tue, 29 Jun 2021 01:26:32 +0800 |
| Subject: KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run() |
| |
| From: Lai Jiangshan <laijs@linux.alibaba.com> |
| |
| commit f85d40160691881a17a397c448d799dfc90987ba upstream. |
| |
| When the host is using debug registers but the guest is not using them |
| nor is the guest in guest-debug state, the kvm code does not reset |
| the host debug registers before kvm_x86->run(). Rather, it relies on |
| the hardware vmentry instruction to automatically reset the dr7 registers |
| which ensures that the host breakpoints do not affect the guest. |
| |
| This however violates the non-instrumentable nature around VM entry |
| and exit; for example, when a host breakpoint is set on vcpu->arch.cr2, |
| |
| Another issue is consistency. When the guest debug registers are active, |
| the host breakpoints are reset before kvm_x86->run(). But when the |
| guest debug registers are inactive, the host breakpoints are delayed to |
| be disabled. The host tracing tools may see different results depending |
| on what the guest is doing. |
| |
| To fix the problems, we clear %db7 unconditionally before kvm_x86->run() |
| if the host has set any breakpoints, no matter if the guest is using |
| them or not. |
| |
| Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com> |
| Message-Id: <20210628172632.81029-1-jiangshanlai@gmail.com> |
| Cc: stable@vger.kernel.org |
| [Only clear %db7 instead of reloading all debug registers. - Paolo] |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kvm/x86.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -9194,6 +9194,8 @@ static int vcpu_enter_guest(struct kvm_v |
| set_debugreg(vcpu->arch.eff_db[3], 3); |
| set_debugreg(vcpu->arch.dr6, 6); |
| vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD; |
| + } else if (unlikely(hw_breakpoint_active())) { |
| + set_debugreg(0, 7); |
| } |
| |
| for (;;) { |