Skip to content

Commit fa7d0f8

Browse files
xinli-intelhansendc
authored andcommitted
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) <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: H. Peter Anvin (Intel) <[email protected]> Reviewed-by: Sohil Mehta <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Sean Christopherson <[email protected]> Tested-by: Sohil Mehta <[email protected]> Cc:[email protected] Link: https://lore.kernel.org/all/20250620231504.2676902-3-xin%40zytor.com
1 parent 5f465c1 commit fa7d0f8

File tree

7 files changed

+22
-11
lines changed

7 files changed

+22
-11
lines changed

arch/x86/include/asm/debugreg.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
#include <asm/cpufeature.h>
1010
#include <asm/msr.h>
1111

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+
1220
DECLARE_PER_CPU(unsigned long, cpu_dr7);
1321

1422
#ifndef CONFIG_PARAVIRT_XXL
@@ -100,8 +108,8 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value)
100108

101109
static inline void hw_breakpoint_disable(void)
102110
{
103-
/* Zero the control register for HW Breakpoint */
104-
set_debugreg(0UL, 7);
111+
/* Reset the control register for HW Breakpoint */
112+
set_debugreg(DR7_FIXED_1, 7);
105113

106114
/* Zero-out the individual HW breakpoint address registers */
107115
set_debugreg(0UL, 0);
@@ -125,9 +133,12 @@ static __always_inline unsigned long local_db_save(void)
125133
return 0;
126134

127135
get_debugreg(dr7, 7);
128-
dr7 &= ~0x400; /* architecturally set bit */
136+
137+
/* Architecturally set bit */
138+
dr7 &= ~DR7_FIXED_1;
129139
if (dr7)
130-
set_debugreg(0, 7);
140+
set_debugreg(DR7_FIXED_1, 7);
141+
131142
/*
132143
* Ensure the compiler doesn't lower the above statements into
133144
* the critical section; disabling breakpoints late would not

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <asm/apic.h>
3333
#include <asm/pvclock-abi.h>
34+
#include <asm/debugreg.h>
3435
#include <asm/desc.h>
3536
#include <asm/mtrr.h>
3637
#include <asm/msr-index.h>
@@ -249,7 +250,6 @@ enum x86_intercept_stage;
249250
#define DR7_BP_EN_MASK 0x000000ff
250251
#define DR7_GE (1 << 9)
251252
#define DR7_GD (1 << 13)
252-
#define DR7_FIXED_1 0x00000400
253253
#define DR7_VOLATILE 0xffff2bff
254254

255255
#define KVM_GUESTDBG_VALID_MASK \

arch/x86/kernel/cpu/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2246,7 +2246,7 @@ EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
22462246
static void initialize_debug_regs(void)
22472247
{
22482248
/* Control register first -- to make sure everything is disabled. */
2249-
set_debugreg(0, 7);
2249+
set_debugreg(DR7_FIXED_1, 7);
22502250
set_debugreg(DR6_RESERVED, 6);
22512251
/* dr5 and dr4 don't exist */
22522252
set_debugreg(0, 3);

arch/x86/kernel/kgdb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs)
385385
struct perf_event *bp;
386386

387387
/* Disable hardware debugging while we are in kgdb: */
388-
set_debugreg(0UL, 7);
388+
set_debugreg(DR7_FIXED_1, 7);
389389
for (i = 0; i < HBP_NUM; i++) {
390390
if (!breakinfo[i].enabled)
391391
continue;

arch/x86/kernel/process_32.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
9393

9494
/* Only print out debug registers if they are in their non-default state. */
9595
if ((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) &&
96-
(d6 == DR6_RESERVED) && (d7 == 0x400))
96+
(d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))
9797
return;
9898

9999
printk("%sDR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",

arch/x86/kernel/process_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
133133

134134
/* Only print out debug registers if they are in their non-default state. */
135135
if (!((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) &&
136-
(d6 == DR6_RESERVED) && (d7 == 0x400))) {
136+
(d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))) {
137137
printk("%sDR0: %016lx DR1: %016lx DR2: %016lx\n",
138138
log_lvl, d0, d1, d2);
139139
printk("%sDR3: %016lx DR6: %016lx DR7: %016lx\n",

arch/x86/kvm/x86.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11035,7 +11035,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
1103511035

1103611036
if (unlikely(vcpu->arch.switch_db_regs &&
1103711037
!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH))) {
11038-
set_debugreg(0, 7);
11038+
set_debugreg(DR7_FIXED_1, 7);
1103911039
set_debugreg(vcpu->arch.eff_db[0], 0);
1104011040
set_debugreg(vcpu->arch.eff_db[1], 1);
1104111041
set_debugreg(vcpu->arch.eff_db[2], 2);
@@ -11044,7 +11044,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
1104411044
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
1104511045
kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6);
1104611046
} else if (unlikely(hw_breakpoint_active())) {
11047-
set_debugreg(0, 7);
11047+
set_debugreg(DR7_FIXED_1, 7);
1104811048
}
1104911049

1105011050
vcpu->arch.host_debugctl = get_debugctlmsr();

0 commit comments

Comments
 (0)