Commit cc69ac7a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_urgent_for_v6.16_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

 - Make sure DR6 and DR7 are initialized to their architectural values
   and not accidentally cleared, leading to misconfigurations

* tag 'x86_urgent_for_v6.16_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/traps: Initialize DR7 by writing its architectural reset value
  x86/traps: Initialize DR6 by writing its architectural reset value
parents 2fc18d0b fa7d0f83
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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>
@@ -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

#define KVM_GUESTDBG_VALID_MASK \
+20 −1
Original line number Diff line number Diff line
@@ -15,7 +15,26 @@
   which debugging register was responsible for the trap.  The other bits
   are either reserved or not of interest to us. */

/* Define reserved bits in DR6 which are always set to 1 */
/*
 * Define bits in DR6 which are set to 1 by default.
 *
 * This is also the DR6 architectural value following Power-up, Reset or INIT.
 *
 * Note, with the introduction of Bus Lock Detection (BLD) and Restricted
 * Transactional Memory (RTM), the DR6 register has been modified:
 *
 * 1) BLD flag (bit 11) is no longer reserved to 1 if the CPU supports
 *    Bus Lock Detection.  The assertion of a bus lock could clear it.
 *
 * 2) RTM flag (bit 16) is no longer reserved to 1 if the CPU supports
 *    restricted transactional memory.  #DB occurred inside an RTM region
 *    could clear it.
 *
 * Apparently, DR6.BLD and DR6.RTM are active low bits.
 *
 * As a result, DR6_RESERVED is an incorrect name now, but it is kept for
 * compatibility.
 */
#define DR6_RESERVED	(0xFFFF0FF0)

#define DR_TRAP0	(0x1)		/* db0 */
+10 −14
Original line number Diff line number Diff line
@@ -2243,20 +2243,16 @@ EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
#endif
#endif

/*
 * Clear all 6 debug registers:
 */
static void clear_all_debug_regs(void)
static void initialize_debug_regs(void)
{
	int i;

	for (i = 0; i < 8; i++) {
		/* Ignore db4, db5 */
		if ((i == 4) || (i == 5))
			continue;

		set_debugreg(0, i);
	}
	/* Control register first -- to make sure everything is disabled. */
	set_debugreg(DR7_FIXED_1, 7);
	set_debugreg(DR6_RESERVED, 6);
	/* dr5 and dr4 don't exist */
	set_debugreg(0, 3);
	set_debugreg(0, 2);
	set_debugreg(0, 1);
	set_debugreg(0, 0);
}

#ifdef CONFIG_KGDB
@@ -2417,7 +2413,7 @@ void cpu_init(void)

	load_mm_ldt(&init_mm);

	clear_all_debug_regs();
	initialize_debug_regs();
	dbg_restore_debug_regs();

	doublefault_init_cpu_tss();
+1 −1
Original line number Diff line number Diff line
@@ -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;
Loading