summaryrefslogtreecommitdiff
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorJim Mattson <jmattson@google.com>2018-10-16 14:29:23 -0700
committerPaolo Bonzini <pbonzini@redhat.com>2018-10-17 19:07:43 +0200
commitf10c729ff965283d2086aa03d139dcf82da86a96 (patch)
tree1fb0a85cd6ecf0f9f21726bc87da7a030bc3738b /arch/x86/kvm/vmx.c
parentda998b46d244767505e41d050dcac5e4d03ba96f (diff)
kvm: vmx: Defer setting of DR6 until #DB delivery
When exception payloads are enabled by userspace (which is not yet possible) and a #DB is raised in L2, defer the setting of DR6 until later. Under VMX, this allows the L1 hypervisor to intercept the fault before DR6 is modified. Under SVM, DR6 is modified before L1 can intercept the fault (as has always been the case with DR7). Note that the payload associated with a #DB exception includes only the "new DR6 bits." When the payload is delievered, DR6.B0-B3 will be cleared and DR6.RTM will be set prior to merging in the new DR6 bits. Also note that bit 16 in the "new DR6 bits" is set to indicate that a debug exception (#DB) or a breakpoint exception (#BP) occurred inside an RTM region while advanced debugging of RTM transactional regions was enabled. Though the reverse of DR6.RTM, this makes the #DB payload field compatible with both the pending debug exceptions field under VMX and the exit qualification for #DB exceptions under VMX. Reported-by: Jim Mattson <jmattson@google.com> Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Jim Mattson <jmattson@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c24
1 files changed, 10 insertions, 14 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 0c7efb1de29d..91f4f5288150 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3305,21 +3305,17 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit
*exit_qual = has_payload ? payload : vcpu->arch.cr2;
return 1;
}
- } else {
- /*
- * FIXME: we must not write DR6 when L1 intercepts an
- * L2 #DB exception.
- */
- if (vmcs12->exception_bitmap & (1u << nr)) {
- if (nr == DB_VECTOR) {
- *exit_qual = vcpu->arch.dr6;
- *exit_qual &= ~(DR6_FIXED_1 | DR6_BT);
- *exit_qual ^= DR6_RTM;
- } else {
- *exit_qual = 0;
+ } else if (vmcs12->exception_bitmap & (1u << nr)) {
+ if (nr == DB_VECTOR) {
+ if (!has_payload) {
+ payload = vcpu->arch.dr6;
+ payload &= ~(DR6_FIXED_1 | DR6_BT);
+ payload ^= DR6_RTM;
}
- return 1;
- }
+ *exit_qual = payload;
+ } else
+ *exit_qual = 0;
+ return 1;
}
return 0;