During my testing, I found that guest debugging with 'DR6.BD' does not work in instruction emulation, as the current code only considers the guest's DR7. Upon reviewing the code, I also observed that the checks for the userspace guest debugging feature and the guest's own debugging feature are repeated in different places during instruction emulation, but the overall logic is the same. If guest debug is enabled, it needs to exit to userspace; otherwise, a #DB exception needs to be injected into the guest. Therefore, as suggested by Jiangshan Lai, some cleanup has been done for #DB handling in instruction emulation in this patchset. A new function named 'kvm_inject_emulated_db()' is introduced to consolidate all the checking logic. Moreover, I hope we can make the #DB interception path use the same function as well.
Additionally, when I looked into the single-step #DB handling in instruction emulation, I noticed that the interrupt shadow is toggled, but it is not considered in the single-step #DB injection. This oversight causes VM entry to fail on VMX (due to pending debug exceptions state checking).
As pointed out by Sean, fault-like code #DBs can be coincident with trap-like single-step #DBs at the instruction boundary on the hardware. However it is difficult to emulate this in the emulator, as kvm_vcpu_check_code_breakpoint() is called at the start of the next instruction while the single-step #DB for the previous instruction has already been injected.
v1->v2: - cleanup in inject_emulated_exception(). - rename 'set_pending_dbg' callback as 'refresh_pending_dbg_exceptions'. - fold refresh_pending_dbg_exceptions() call into kvm_vcpu_do_singlestep(). - Split the change to move up kvm_set_rflags() into a single patch. - Move the #DB and IRQ handler registration after guest debug testcases.
Hou Wenlong (9): KVM: x86: Capture "struct x86_exception" in inject_emulated_exception() KVM: x86: Set guest DR6 by kvm_queue_exception_p() in instruction emulation KVM: x86: Check guest debug in DR access instruction emulation KVM: x86: Only check effective code breakpoint in emulation KVM: x86: Consolidate KVM_GUESTDBG_SINGLESTEP check into the kvm_inject_emulated_db() KVM: x86: Move kvm_set_rflags() up before kvm_vcpu_do_singlestep() KVM: VMX: Refresh 'PENDING_DBG_EXCEPTIONS.BS' bit during instruction emulation KVM: selftests: Verify guest debug DR7.GD checking during instruction emulation KVM: selftests: Verify 'BS' bit checking in pending debug exception during VM entry
arch/x86/include/asm/kvm-x86-ops.h | 1 + arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/emulate.c | 14 +-- arch/x86/kvm/kvm_emulate.h | 7 +- arch/x86/kvm/vmx/main.c | 9 ++ arch/x86/kvm/vmx/vmx.c | 15 ++- arch/x86/kvm/vmx/x86_ops.h | 1 + arch/x86/kvm/x86.c | 116 ++++++++++-------- arch/x86/kvm/x86.h | 7 ++ .../selftests/kvm/include/x86/processor.h | 3 +- tools/testing/selftests/kvm/x86/debug_regs.c | 72 ++++++++++- 11 files changed, 178 insertions(+), 68 deletions(-)
base-commit: 5d3e2d9ba9ed68576c70c127e4f7446d896f2af2 -- 2.31.1