From nobody Thu Oct 9 04:14:04 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0C8823C8A4; Fri, 20 Jun 2025 23:15:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750461349; cv=none; b=E8guPkws+YNydXajcJKHTXclHtcuvuPJZm3UcN1gqzXY2VVQbBHOp/IpNKKxqCBJB7TfKXdJ0s77Zsg9OyGD3XEVRiBHCRp/OgTXq1szjQ142geovDcZ07OGFxssuiv+lazcuJYLnHYW7q7ygnZyA5L36ixNuoQ+eMUbJcmb3ws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750461349; c=relaxed/simple; bh=WxBeAhvEJzqApAg8k2lfiHZOWnO+hOXKRTJ0MaX0A54=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D2sZE5Kf8rUtddqnBwvA8wraImV+c2JGWQULeTU0SDGJY1bCf+0dK1HPQYM2NMcPXyDFvvsAnqKmg215i23ZzuTr214BIi4MCUFC+OjpGMnehFGTmT0oqT0vz3RaiQMica+ZjBSdjUcgwCpHmpOrsZ7ZEKDryiPfGx5MN5ub+3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=CnTJDQQw; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="CnTJDQQw" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 55KNF5V82676916 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Fri, 20 Jun 2025 16:15:10 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 55KNF5V82676916 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025052101; t=1750461310; bh=yoVWlCUSshrYo8Ah5bULITDewE8xGWH+A44LYoq/KtI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CnTJDQQwh4n1acGStIr4GzWGsEcUNbg3t3j2E98DZ27xkzhQbuUTbLOBOAj/GVgrf gqibiZqBY34cZHbYLFdxLQzhHaHDHzMbS/em4SHr6C/w3z2XpcB9BhS4yniKsRiPhv qJihqmcykd5iljGKxUZ32IiWcVLpx+P/o6tPJL/QeCb7B2nNQxhOFMVWihzNawv35L W+VF0tssL+QE1FBzf62qy3PnU5SFCKq19JfRwPWohEIPeLADV4RjK0AC3P3G81zg8v Bw1FOb2oSP/QMoD9DD/bbvVValrfBLmJFq6qvC7HKyjQ1+2wLh0Q1KVI0NREnTEaXF Cc05N0iEdLu9Q== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, stable@vger.kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, seanjc@google.com, pbonzini@redhat.com, peterz@infradead.org, sohil.mehta@intel.com, brgerst@gmail.com, tony.luck@intel.com, fenghuay@nvidia.com Subject: [PATCH v4 2/2] x86/traps: Initialize DR7 by writing its architectural reset value Date: Fri, 20 Jun 2025 16:15:04 -0700 Message-ID: <20250620231504.2676902-3-xin@zytor.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250620231504.2676902-1-xin@zytor.com> References: <20250620231504.2676902-1-xin@zytor.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Tested-by: Sohil Mehta Reviewed-by: H. Peter Anvin (Intel) Reviewed-by: Sohil Mehta Acked-by: Peter Zijlstra (Intel) Acked-by: Sean Christopherson Signed-off-by: Xin Li (Intel) Cc: stable@vger.kernel.org --- Change in v4: *) Cc stable for backporting, just in case bit 10 of DR7 has become unreserved on new hardware, even though clearing it doesn't currently cause any real issues (Dave Hansen). Changes in v3: *) Reword the changelog using Sean's description. *) Explain the definition of DR7_FIXED_1 (Sohil). *) Collect TB, RB, AB (PeterZ, Sohil and Sean). Changes in v2: *) Use debug register index 7 rather than DR_CONTROL (PeterZ and Sean). *) Use DR7_FIXED_1 as the architectural reset value of DR7 (Sean). --- arch/x86/include/asm/debugreg.h | 19 +++++++++++++++---- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/kgdb.c | 2 +- arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/process_64.c | 2 +- arch/x86/kvm/x86.c | 4 ++-- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugre= g.h index 363110e6b2e3..a2c1f2d24b64 100644 --- a/arch/x86/include/asm/debugreg.h +++ b/arch/x86/include/asm/debugreg.h @@ -9,6 +9,14 @@ #include #include =20 +/* + * 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); =20 #ifndef CONFIG_PARAVIRT_XXL @@ -100,8 +108,8 @@ static __always_inline void native_set_debugreg(int reg= no, unsigned long value) =20 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); =20 /* Zero-out the individual HW breakpoint address registers */ set_debugreg(0UL, 0); @@ -125,9 +133,12 @@ static __always_inline unsigned long local_db_save(voi= d) return 0; =20 get_debugreg(dr7, 7); - dr7 &=3D ~0x400; /* architecturally set bit */ + + /* Architecturally set bit */ + dr7 &=3D ~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 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index b4a391929cdb..639d9bcee842 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -31,6 +31,7 @@ =20 #include #include +#include #include #include #include @@ -249,7 +250,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 =20 #define KVM_GUESTDBG_VALID_MASK \ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0f6c280a94f0..27125e009847 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2246,7 +2246,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); diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 102641fd2172..8b1a9733d13e 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -385,7 +385,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs) struct perf_event *bp; =20 /* Disable hardware debugging while we are in kgdb: */ - set_debugreg(0UL, 7); + set_debugreg(DR7_FIXED_1, 7); for (i =3D 0; i < HBP_NUM; i++) { if (!breakinfo[i].enabled) continue; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index a10e180cbf23..3ef15c2f152f 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mod= e mode, =20 /* Only print out debug registers if they are in their non-default state.= */ if ((d0 =3D=3D 0) && (d1 =3D=3D 0) && (d2 =3D=3D 0) && (d3 =3D=3D 0) && - (d6 =3D=3D DR6_RESERVED) && (d7 =3D=3D 0x400)) + (d6 =3D=3D DR6_RESERVED) && (d7 =3D=3D DR7_FIXED_1)) return; =20 printk("%sDR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 8d6cf25127aa..b972bf72fb8b 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -133,7 +133,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_m= ode mode, =20 /* Only print out debug registers if they are in their non-default state.= */ if (!((d0 =3D=3D 0) && (d1 =3D=3D 0) && (d2 =3D=3D 0) && (d3 =3D=3D 0) && - (d6 =3D=3D DR6_RESERVED) && (d7 =3D=3D 0x400))) { + (d6 =3D=3D DR6_RESERVED) && (d7 =3D=3D DR7_FIXED_1))) { printk("%sDR0: %016lx DR1: %016lx DR2: %016lx\n", log_lvl, d0, d1, d2); printk("%sDR3: %016lx DR6: %016lx DR7: %016lx\n", diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b58a74c1722d..a9d992d5652f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -11035,7 +11035,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) =20 if (unlikely(vcpu->arch.switch_db_regs && !(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH))) { - 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); @@ -11044,7 +11044,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); } =20 vcpu->arch.host_debugctl =3D get_debugctlmsr(); --=20 2.49.0