]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/traps: Initialize DR7 by writing its architectural reset value
authorXin Li (Intel) <xin@zytor.com>
Fri, 20 Jun 2025 23:15:04 +0000 (16:15 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Aug 2025 08:48:39 +0000 (09:48 +0100)
commit fa7d0f83c5c4223a01598876352473cb3d3bd4d7 upstream.

Initialize DR7 by writing its architectural reset value to always set
bit 10, which is reserved to '1', when "clearing" DR7 so as not to
trigger unanticipated behavior if said bit is ever unreserved, e.g. as
a feature enabling flag with inverted polarity.

Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Reviewed-by: Sohil Mehta <sohil.mehta@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Sean Christopherson <seanjc@google.com>
Tested-by: Sohil Mehta <sohil.mehta@intel.com>
Cc:stable@vger.kernel.org
Link: https://lore.kernel.org/all/20250620231504.2676902-3-xin%40zytor.com
[ context adjusted: no KVM_DEBUGREG_AUTO_SWITCH flag test" ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/include/asm/debugreg.h
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kvm/x86.c

index fdbbbfec745aa58855641ae59e17a3a50fc2696a..820b4aeabd0c24b2a79c2612285951d8caf54471 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/cpufeature.h>
 #include <asm/msr.h>
 
+/*
+ * Define bits that are always set to 1 in DR7, only bit 10 is
+ * architecturally reserved to '1'.
+ *
+ * This is also the init/reset value for DR7.
+ */
+#define DR7_FIXED_1    0x00000400
+
 DECLARE_PER_CPU(unsigned long, cpu_dr7);
 
 #ifndef CONFIG_PARAVIRT_XXL
@@ -100,8 +108,8 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value)
 
 static inline void hw_breakpoint_disable(void)
 {
-       /* Zero the control register for HW Breakpoint */
-       set_debugreg(0UL, 7);
+       /* Reset the control register for HW Breakpoint */
+       set_debugreg(DR7_FIXED_1, 7);
 
        /* Zero-out the individual HW breakpoint address registers */
        set_debugreg(0UL, 0);
@@ -125,9 +133,12 @@ static __always_inline unsigned long local_db_save(void)
                return 0;
 
        get_debugreg(dr7, 7);
-       dr7 &= ~0x400; /* architecturally set bit */
+
+       /* Architecturally set bit */
+       dr7 &= ~DR7_FIXED_1;
        if (dr7)
-               set_debugreg(0, 7);
+               set_debugreg(DR7_FIXED_1, 7);
+
        /*
         * Ensure the compiler doesn't lower the above statements into
         * the critical section; disabling breakpoints late would not
index e4dd840e0becd4d675fe003f5df9c6f91c1dc6bb..0caa3293f6db90b1d3b1deccd23b3cfd7f583fa6 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <asm/apic.h>
 #include <asm/pvclock-abi.h>
+#include <asm/debugreg.h>
 #include <asm/desc.h>
 #include <asm/mtrr.h>
 #include <asm/msr-index.h>
@@ -246,7 +247,6 @@ enum x86_intercept_stage;
 #define DR7_BP_EN_MASK 0x000000ff
 #define DR7_GE         (1 << 9)
 #define DR7_GD         (1 << 13)
-#define DR7_FIXED_1    0x00000400
 #define DR7_VOLATILE   0xffff2bff
 
 #define KVM_GUESTDBG_VALID_MASK \
index ed072b126111c3364ec3e3cbf581391b8bff85d5..976545ec8fdcb3d876e4e1f8edbdc26a69c3c8e1 100644 (file)
@@ -2160,7 +2160,7 @@ EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
 static void initialize_debug_regs(void)
 {
        /* Control register first -- to make sure everything is disabled. */
-       set_debugreg(0, 7);
+       set_debugreg(DR7_FIXED_1, 7);
        set_debugreg(DR6_RESERVED, 6);
        /* dr5 and dr4 don't exist */
        set_debugreg(0, 3);
index 9c9faa1634fb9ab50907a27f25c6766de8bdd5b8..e5faeec20b1f4b173e6e3b56240473385436b58b 100644 (file)
@@ -385,7 +385,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs)
        struct perf_event *bp;
 
        /* Disable hardware debugging while we are in kgdb: */
-       set_debugreg(0UL, 7);
+       set_debugreg(DR7_FIXED_1, 7);
        for (i = 0; i < HBP_NUM; i++) {
                if (!breakinfo[i].enabled)
                        continue;
index 0917c7f25720be91372bacddb1a3032323b8996f..f10c14cb6ef8bf44c26c415113fbad93de20885b 100644 (file)
@@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
 
        /* Only print out debug registers if they are in their non-default state. */
        if ((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) &&
-           (d6 == DR6_RESERVED) && (d7 == 0x400))
+           (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))
                return;
 
        printk("%sDR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
index 226472332a70dd02902f81c21207d770e698aeed..266366a945ed2be568c56a800ce9d872cfe100b3 100644 (file)
@@ -132,7 +132,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
 
        /* Only print out debug registers if they are in their non-default state. */
        if (!((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) &&
-           (d6 == DR6_RESERVED) && (d7 == 0x400))) {
+           (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))) {
                printk("%sDR0: %016lx DR1: %016lx DR2: %016lx\n",
                       log_lvl, d0, d1, d2);
                printk("%sDR3: %016lx DR6: %016lx DR7: %016lx\n",
index f378d479fea3f9b77e076d7ac232641ea2183681..27d0d6fdd418eeeef694b3fa945924968635e83f 100644 (file)
@@ -10959,7 +10959,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                wrmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
 
        if (unlikely(vcpu->arch.switch_db_regs)) {
-               set_debugreg(0, 7);
+               set_debugreg(DR7_FIXED_1, 7);
                set_debugreg(vcpu->arch.eff_db[0], 0);
                set_debugreg(vcpu->arch.eff_db[1], 1);
                set_debugreg(vcpu->arch.eff_db[2], 2);
@@ -10968,7 +10968,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
                        kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6);
        } else if (unlikely(hw_breakpoint_active())) {
-               set_debugreg(0, 7);
+               set_debugreg(DR7_FIXED_1, 7);
        }
 
        vcpu->arch.host_debugctl = get_debugctlmsr();