Patch "KVM: x86: Treat #DBs from the emulator as fault-like (code and DR7.GD=1)" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    KVM: x86: Treat #DBs from the emulator as fault-like (code and DR7.GD=1)

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-x86-treat-dbs-from-the-emulator-as-fault-like-co.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit bfc17e5d1035ad471aaef5b77baacac96cf54597
Author: Sean Christopherson <seanjc@xxxxxxxxxx>
Date:   Tue Aug 30 23:15:55 2022 +0000

    KVM: x86: Treat #DBs from the emulator as fault-like (code and DR7.GD=1)
    
    [ Upstream commit 5623f751bd9c438ed12840e086f33c4646440d19 ]
    
    Add a dedicated "exception type" for #DBs, as #DBs can be fault-like or
    trap-like depending the sub-type of #DB, and effectively defer the
    decision of what to do with the #DB to the caller.
    
    For the emulator's two calls to exception_type(), treat the #DB as
    fault-like, as the emulator handles only code breakpoint and general
    detect #DBs, both of which are fault-like.
    
    For event injection, which uses exception_type() to determine whether to
    set EFLAGS.RF=1 on the stack, keep the current behavior of not setting
    RF=1 for #DBs.  Intel and AMD explicitly state RF isn't set on code #DBs,
    so exempting by failing the "== EXCPT_FAULT" check is correct.  The only
    other fault-like #DB is General Detect, and despite Intel and AMD both
    strongly implying (through omission) that General Detect #DBs should set
    RF=1, hardware (multiple generations of both Intel and AMD), in fact does
    not.  Through insider knowledge, extreme foresight, sheer dumb luck, or
    some combination thereof, KVM correctly handled RF for General Detect #DBs.
    
    Fixes: 38827dbd3fb8 ("KVM: x86: Do not update EFLAGS on faulting emulation")
    Cc: stable@xxxxxxxxxxxxxxx
    Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
    Reviewed-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20220830231614.3580124-9-seanjc@xxxxxxxxxx
    Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c171ca2bb85a..cd22557e2645 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -525,6 +525,7 @@ static int exception_class(int vector)
 #define EXCPT_TRAP		1
 #define EXCPT_ABORT		2
 #define EXCPT_INTERRUPT		3
+#define EXCPT_DB		4
 
 static int exception_type(int vector)
 {
@@ -535,8 +536,14 @@ static int exception_type(int vector)
 
 	mask = 1 << vector;
 
-	/* #DB is trap, as instruction watchpoints are handled elsewhere */
-	if (mask & ((1 << DB_VECTOR) | (1 << BP_VECTOR) | (1 << OF_VECTOR)))
+	/*
+	 * #DBs can be trap-like or fault-like, the caller must check other CPU
+	 * state, e.g. DR6, to determine whether a #DB is a trap or fault.
+	 */
+	if (mask & (1 << DB_VECTOR))
+		return EXCPT_DB;
+
+	if (mask & ((1 << BP_VECTOR) | (1 << OF_VECTOR)))
 		return EXCPT_TRAP;
 
 	if (mask & ((1 << DF_VECTOR) | (1 << MC_VECTOR)))
@@ -8134,6 +8141,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 		unsigned long rflags = static_call(kvm_x86_get_rflags)(vcpu);
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
+
+		/*
+		 * Note, EXCPT_DB is assumed to be fault-like as the emulator
+		 * only supports code breakpoints and general detect #DB, both
+		 * of which are fault-like.
+		 */
 		if (!ctxt->have_exception ||
 		    exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
 			kvm_rip_write(vcpu, ctxt->eip);
@@ -9072,6 +9085,16 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit)
 
 	/* try to inject new event if pending */
 	if (vcpu->arch.exception.pending) {
+		/*
+		 * Fault-class exceptions, except #DBs, set RF=1 in the RFLAGS
+		 * value pushed on the stack.  Trap-like exception and all #DBs
+		 * leave RF as-is (KVM follows Intel's behavior in this regard;
+		 * AMD states that code breakpoint #DBs excplitly clear RF=0).
+		 *
+		 * Note, most versions of Intel's SDM and AMD's APM incorrectly
+		 * describe the behavior of General Detect #DBs, which are
+		 * fault-like.  They do _not_ set RF, a la code breakpoints.
+		 */
 		if (exception_type(vcpu->arch.exception.nr) == EXCPT_FAULT)
 			__kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) |
 					     X86_EFLAGS_RF);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux