lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 10 Mar 2016 21:45:46 -0700
From:	Toshi Kani <toshi.kani@....com>
To:	mingo@...nel.org, bp@...e.de, hpa@...or.com, tglx@...utronix.de
Cc:	mcgrof@...e.com, jgross@...e.com, paul.gortmaker@...driver.com,
	x86@...nel.org, linux-kernel@...r.kernel.org,
	Toshi Kani <toshi.kani@....com>
Subject: [PATCH 2/2] x86/mtrr: Refactor PAT initialization code

MTRR manages PAT initialization as it implements a rendezvous
handler that initializes PAT as part of MTRR initialization.

When CPU does not support MTRR, ex. qemu32 virtual CPU, MTRR
simply skips PAT init, which causes PAT left enabled without
initialization.  Also, get_mtrr_state() calls pat_init() on
BSP even if MTRR is disabled by its MSR.  This causes pat_init()
be called on BSP only.

The following changes are made to address these issues:
- Move BSP's PAT init code to mtrr_bp_pat_init(), and change
  mtrr_bp_init() to call it if MTRR is enabled.  This keeps
  the init condition consistent with mtrr_ap_init() and
  mtrr_aps_init() for APs.
- Change mtrr_bp_init() to call pat_disable() when MTRR is
  disabled.
- Change mtrr_bp_init() stub function to call pat_disable()
  when CONFIG_MTRR is unset.

The table below discribes how PAT is initialized in all possible
cases.

 Legend
 ----------------------------
 E       Enabled in CPU feature and MSR
 D       Disabled in CPU feature or MSR
 nopat   "nopat" boot option specified
 !PAT    CONFIG_X86_PAT unset
 !MTRR   CONFIG_MTRR unset

 MTRR   PAT    ACTION
 ====================================================================
 E      E      MTRR calls pat_init() -> PAT enabled
 E      D      MTRR calls pat_init() -> PAT disabled per cpu_has_pat
 D      E      MTRR calls pat_disable() -> PAT disabled (*)
 D      D      MTRR calls pat_disable() -> PAT disabled
 E      nopat  nopat() calls pat_disable() -> PAT disabled
 D      nopat  nopat() calls pat_disable() -> PAT disabled
 E      !PAT   MTRR calls pat_init() -> PAT disabled per __pat_enabled
 D      !PAT   MTRR calls pat_disable() -> PAT disabled
 !MTRR  !PAT   mtrr_bp_init() stub calls pat_disable() -> PAT disabled

 (*) Further enhancement may enable PAT if needed

Signed-off-by: Toshi Kani <toshi.kani@....com>
Cc: Borislav Petkov <bp@...e.de>
Cc: Luis R. Rodriguez <mcgrof@...e.com>
Cc: Juergen Gross <jgross@...e.com>
Cc: Ingo Molnar <mingo@...nel.org>
Cc: H. Peter Anvin <hpa@...or.com>
Cc: Thomas Gleixner <tglx@...utronix.de>
---
 arch/x86/include/asm/mtrr.h        |    6 +++++-
 arch/x86/kernel/cpu/mtrr/generic.c |   24 ++++++++++++++----------
 arch/x86/kernel/cpu/mtrr/main.c    |   13 ++++++++++++-
 arch/x86/kernel/cpu/mtrr/mtrr.h    |    1 +
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index b94f6f6..a965e74 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -24,6 +24,7 @@
 #define _ASM_X86_MTRR_H
 
 #include <uapi/asm/mtrr.h>
+#include <asm/pat.h>
 
 
 /*
@@ -83,9 +84,12 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
+static inline void mtrr_bp_init(void)
+{
+	pat_disable("PAT disabled by MTRR");
+}
 
 #define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
 #define set_mtrr_aps_delayed_init() do {} while (0)
 #define mtrr_aps_init() do {} while (0)
 #define mtrr_bp_restore() do {} while (0)
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index c870af1..136ae86 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -444,11 +444,24 @@ static void __init print_mtrr_state(void)
 		pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
 }
 
+/* PAT setup for BP. We need to go through sync steps here */
+void __init mtrr_bp_pat_init(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	prepare_set();
+
+	pat_init();
+
+	post_set();
+	local_irq_restore(flags);
+}
+
 /* Grab all of the MTRR state for this CPU into *state */
 bool __init get_mtrr_state(void)
 {
 	struct mtrr_var_range *vrs;
-	unsigned long flags;
 	unsigned lo, dummy;
 	unsigned int i;
 
@@ -481,15 +494,6 @@ bool __init get_mtrr_state(void)
 
 	mtrr_state_set = 1;
 
-	/* PAT setup for BP. We need to go through sync steps here */
-	local_irq_save(flags);
-	prepare_set();
-
-	pat_init();
-
-	post_set();
-	local_irq_restore(flags);
-
 	return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
 }
 
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 5c3d149..d9e91f1 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -752,6 +752,9 @@ void __init mtrr_bp_init(void)
 			/* BIOS may override */
 			__mtrr_enabled = get_mtrr_state();
 
+			if (mtrr_enabled())
+				mtrr_bp_pat_init();
+
 			if (mtrr_cleanup(phys_addr)) {
 				changed_by_mtrr_cleanup = 1;
 				mtrr_if->set_all();
@@ -759,8 +762,16 @@ void __init mtrr_bp_init(void)
 		}
 	}
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled()) {
 		pr_info("MTRR: Disabled\n");
+
+		/*
+		 * PAT initialization relies on MTRR's rendezvous handler.
+		 * Disable PAT until the handler can initialize both features
+		 * independently.
+		 */
+		pat_disable("PAT disabled by MTRR");
+	}
 }
 
 void mtrr_ap_init(void)
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 951884d..6c7ced0 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
 void fill_mtrr_var_range(unsigned int index,
 		u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
 bool get_mtrr_state(void);
+void mtrr_bp_pat_init(void);
 
 extern void set_mtrr_ops(const struct mtrr_ops *ops);
 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ