x86/traps: Initialize DR7 by writing its architectural reset value

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

authored by Xin Li (Intel) and committed by Dave Hansen fa7d0f83 5f465c14

Changed files
+22 -11
arch
+15 -4
arch/x86/include/asm/debugreg.h
··· 9 9 #include <asm/cpufeature.h> 10 10 #include <asm/msr.h> 11 11 12 + /* 13 + * Define bits that are always set to 1 in DR7, only bit 10 is 14 + * architecturally reserved to '1'. 15 + * 16 + * This is also the init/reset value for DR7. 17 + */ 18 + #define DR7_FIXED_1 0x00000400 19 + 12 20 DECLARE_PER_CPU(unsigned long, cpu_dr7); 13 21 14 22 #ifndef CONFIG_PARAVIRT_XXL ··· 108 100 109 101 static inline void hw_breakpoint_disable(void) 110 102 { 111 - /* Zero the control register for HW Breakpoint */ 112 - set_debugreg(0UL, 7); 103 + /* Reset the control register for HW Breakpoint */ 104 + set_debugreg(DR7_FIXED_1, 7); 113 105 114 106 /* Zero-out the individual HW breakpoint address registers */ 115 107 set_debugreg(0UL, 0); ··· 133 125 return 0; 134 126 135 127 get_debugreg(dr7, 7); 136 - dr7 &= ~0x400; /* architecturally set bit */ 128 + 129 + /* Architecturally set bit */ 130 + dr7 &= ~DR7_FIXED_1; 137 131 if (dr7) 138 - set_debugreg(0, 7); 132 + set_debugreg(DR7_FIXED_1, 7); 133 + 139 134 /* 140 135 * Ensure the compiler doesn't lower the above statements into 141 136 * the critical section; disabling breakpoints late would not
+1 -1
arch/x86/include/asm/kvm_host.h
··· 31 31 32 32 #include <asm/apic.h> 33 33 #include <asm/pvclock-abi.h> 34 + #include <asm/debugreg.h> 34 35 #include <asm/desc.h> 35 36 #include <asm/mtrr.h> 36 37 #include <asm/msr-index.h> ··· 250 249 #define DR7_BP_EN_MASK 0x000000ff 251 250 #define DR7_GE (1 << 9) 252 251 #define DR7_GD (1 << 13) 253 - #define DR7_FIXED_1 0x00000400 254 252 #define DR7_VOLATILE 0xffff2bff 255 253 256 254 #define KVM_GUESTDBG_VALID_MASK \
+1 -1
arch/x86/kernel/cpu/common.c
··· 2246 2246 static void initialize_debug_regs(void) 2247 2247 { 2248 2248 /* Control register first -- to make sure everything is disabled. */ 2249 - set_debugreg(0, 7); 2249 + set_debugreg(DR7_FIXED_1, 7); 2250 2250 set_debugreg(DR6_RESERVED, 6); 2251 2251 /* dr5 and dr4 don't exist */ 2252 2252 set_debugreg(0, 3);
+1 -1
arch/x86/kernel/kgdb.c
··· 385 385 struct perf_event *bp; 386 386 387 387 /* Disable hardware debugging while we are in kgdb: */ 388 - set_debugreg(0UL, 7); 388 + set_debugreg(DR7_FIXED_1, 7); 389 389 for (i = 0; i < HBP_NUM; i++) { 390 390 if (!breakinfo[i].enabled) 391 391 continue;
+1 -1
arch/x86/kernel/process_32.c
··· 93 93 94 94 /* Only print out debug registers if they are in their non-default state. */ 95 95 if ((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) && 96 - (d6 == DR6_RESERVED) && (d7 == 0x400)) 96 + (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1)) 97 97 return; 98 98 99 99 printk("%sDR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
+1 -1
arch/x86/kernel/process_64.c
··· 133 133 134 134 /* Only print out debug registers if they are in their non-default state. */ 135 135 if (!((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) && 136 - (d6 == DR6_RESERVED) && (d7 == 0x400))) { 136 + (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))) { 137 137 printk("%sDR0: %016lx DR1: %016lx DR2: %016lx\n", 138 138 log_lvl, d0, d1, d2); 139 139 printk("%sDR3: %016lx DR6: %016lx DR7: %016lx\n",
+2 -2
arch/x86/kvm/x86.c
··· 11035 11035 11036 11036 if (unlikely(vcpu->arch.switch_db_regs && 11037 11037 !(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH))) { 11038 - set_debugreg(0, 7); 11038 + set_debugreg(DR7_FIXED_1, 7); 11039 11039 set_debugreg(vcpu->arch.eff_db[0], 0); 11040 11040 set_debugreg(vcpu->arch.eff_db[1], 1); 11041 11041 set_debugreg(vcpu->arch.eff_db[2], 2); ··· 11044 11044 if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) 11045 11045 kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6); 11046 11046 } else if (unlikely(hw_breakpoint_active())) { 11047 - set_debugreg(0, 7); 11047 + set_debugreg(DR7_FIXED_1, 7); 11048 11048 } 11049 11049 11050 11050 vcpu->arch.host_debugctl = get_debugctlmsr();