• Paolo Bonzini's avatar
    KVM: x86, SVM: isolate vcpu->arch.dr6 from vmcb->save.dr6 · d67668e9
    Paolo Bonzini authored
    There are two issues with KVM_EXIT_DEBUG on AMD, whose root cause is the
    different handling of DR6 on intercepted #DB exceptions on Intel and AMD.
    
    On Intel, #DB exceptions transmit the DR6 value via the exit qualification
    field of the VMCS, and the exit qualification only contains the description
    of the precise event that caused a vmexit.
    
    On AMD, instead the DR6 field of the VMCB is filled in as if the #DB exception
    was to be injected into the guest.  This has two effects when guest debugging
    is in use:
    
    * the guest DR6 is clobbered
    
    * the kvm_run->debug.arch.dr6 field can accumulate more debug events, rather
    than just the last one that happened (the testcase in the next patch covers
    this issue).
    
    This patch fixes both issues by emulating, so to speak, the Intel behavior
    on AMD processors.  The important observation is that (after the previous
    patches) the VMCB value of DR6 is only ever observable from the guest is
    KVM_DEBUGREG_WONT_EXIT is set.  Therefore we can actually set vmcb->save.dr6
    to any value we want as long as KVM_DEBUGREG_WONT_EXIT is clear, which it
    will be if guest debugging is enabled.
    
    Therefore it is possible to enter the guest with an all-zero DR6,
    reconstruct the #DB payload from the DR6 we get at exit time, and let
    kvm_deliver_exception_payload move the newly set bits into vcpu->arch.dr6.
    Some extra bits may be included in the payload if KVM_DEBUGREG_WONT_EXIT
    is set, but this is harmless.
    
    This may not be the most optimized way to deal with this, but it is
    simple and, being confined within SVM code, it gets rid of the set_dr6
    callback and kvm_update_dr6.
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    d67668e9
nested.c 24.9 KB