linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/16] x86: make pat and mtrr independent from each other
@ 2022-10-04  8:10 Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 01/16] x86/mtrr: add comment for set_mtrr_state() serialization Juergen Gross
                   ` (16 more replies)
  0 siblings, 17 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, linux-pm
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Rafael J. Wysocki, Pavel Machek,
	Andy Lutomirski, Peter Zijlstra

Today PAT can't be used without MTRR being available, unless MTRR is at
least configured via CONFIG_MTRR and the system is running as Xen PV
guest. In this case PAT is automatically available via the hypervisor,
but the PAT MSR can't be modified by the kernel and MTRR is disabled.

The same applies to a kernel built with no MTRR support: it won't
allow to use the PAT MSR, even if there is no technical reason for
that, other than setting up PAT on all cpus the same way (which is a
requirement of the processor's cache management) is relying on some
MTRR specific code.

Fix all of that by:

- moving the function needed by PAT from MTRR specific code one level
  up
- reworking the init sequences of MTRR and PAT to be more similar to
  each other without calling PAT from MTRR code
- removing the dependency of PAT on MTRR

While working on that I discovered two minor bugs in MTRR code, which
are fixed, too.

There is some more cleanup done reducing code size.

Changes in V4:
- new patches 10, 14, 15, 16
- split up old patch 4 into 3 patches
- addressed comments

Changes in V3:
- replace patch 1 by just adding a comment

Changes in V2:
- complete rework of the patches based on comments by Boris Petkov
- added several patches to the series

Juergen Gross (16):
  x86/mtrr: add comment for set_mtrr_state() serialization
  x86/mtrr: remove unused cyrix_set_all() function
  x86/mtrr: replace use_intel() with a local flag
  x86/mtrr: rename prepare_set() and post_set()
  x86/mtrr: split MTRR specific handling from cache dis/enabling
  x86: move some code out of arch/x86/kernel/cpu/mtrr
  x86/mtrr: split generic_set_all()
  x86/mtrr: remove set_all callback from struct mtrr_ops
  x86/mtrr: simplify mtrr_bp_init()
  x86/mtrr: get rid of mtrr_enabled bool
  x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init
  x86/mtrr: add a stop_machine() handler calling only cache_cpu_init()
  x86: decouple pat and mtrr handling
  x86: switch cache_ap_init() to hotplug callback
  x86: do MTRR/PAT setup on all secondary CPUs in parallel
  x86/mtrr: simplify mtrr_ops initialization

 arch/x86/include/asm/cacheinfo.h   |  18 +++
 arch/x86/include/asm/memtype.h     |   5 +-
 arch/x86/include/asm/mtrr.h        |  13 +-
 arch/x86/kernel/cpu/cacheinfo.c    | 168 ++++++++++++++++++++++++++
 arch/x86/kernel/cpu/common.c       |   2 +-
 arch/x86/kernel/cpu/mtrr/amd.c     |   8 +-
 arch/x86/kernel/cpu/mtrr/centaur.c |   8 +-
 arch/x86/kernel/cpu/mtrr/cyrix.c   |  42 +------
 arch/x86/kernel/cpu/mtrr/generic.c | 127 +++-----------------
 arch/x86/kernel/cpu/mtrr/mtrr.c    | 185 ++++-------------------------
 arch/x86/kernel/cpu/mtrr/mtrr.h    |  20 ++--
 arch/x86/kernel/setup.c            |  14 +--
 arch/x86/kernel/smpboot.c          |   9 +-
 arch/x86/mm/pat/memtype.c          | 127 ++++++--------------
 arch/x86/power/cpu.c               |   3 +-
 include/linux/cpuhotplug.h         |   1 +
 16 files changed, 298 insertions(+), 452 deletions(-)

-- 
2.35.3


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v4 01/16] x86/mtrr: add comment for set_mtrr_state() serialization
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 02/16] x86/mtrr: remove unused cyrix_set_all() function Juergen Gross
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Add a comment how set_mtrr_state() is needing serialization.

Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
V3:
- new patch instead of old patch 1
---
 arch/x86/kernel/cpu/mtrr/generic.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 558108296f3c..cd64eab02393 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -684,7 +684,10 @@ static u32 deftype_lo, deftype_hi;
 /**
  * set_mtrr_state - Set the MTRR state for this CPU.
  *
- * NOTE: The CPU must already be in a safe state for MTRR changes.
+ * NOTE: The CPU must already be in a safe state for MTRR changes, including
+ *       measures that only a single CPU can be active in set_mtrr_state() in
+ *       order to not be subject to races for usage of deftype_lo (this is
+ *       accomplished by taking set_atomicity_lock).
  * RETURNS: 0 if no changes made, else a mask indicating what was changed.
  */
 static unsigned long set_mtrr_state(void)
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 02/16] x86/mtrr: remove unused cyrix_set_all() function
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 01/16] x86/mtrr: add comment for set_mtrr_state() serialization Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-20 14:13   ` [tip: x86/cpu] x86/mtrr: Remove " tip-bot2 for Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag Juergen Gross
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

The Cyrix CPU specific MTRR function cyrix_set_all() will never be
called, as the struct mtrr_ops set_all() callback will only be called
in the use_intel() case, which would require the use_intel_if member
of struct mtrr_ops to be set, which isn't the case for Cyrix.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
---
 arch/x86/kernel/cpu/mtrr/cyrix.c | 34 --------------------------------
 1 file changed, 34 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index ca670919b561..c77d3b0a5bf2 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -234,42 +234,8 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
 	post_set();
 }
 
-typedef struct {
-	unsigned long	base;
-	unsigned long	size;
-	mtrr_type	type;
-} arr_state_t;
-
-static arr_state_t arr_state[8] = {
-	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
-	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
-};
-
-static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
-
-static void cyrix_set_all(void)
-{
-	int i;
-
-	prepare_set();
-
-	/* the CCRs are not contiguous */
-	for (i = 0; i < 4; i++)
-		setCx86(CX86_CCR0 + i, ccr_state[i]);
-	for (; i < 7; i++)
-		setCx86(CX86_CCR4 + i, ccr_state[i]);
-
-	for (i = 0; i < 8; i++) {
-		cyrix_set_arr(i, arr_state[i].base,
-			      arr_state[i].size, arr_state[i].type);
-	}
-
-	post_set();
-}
-
 static const struct mtrr_ops cyrix_mtrr_ops = {
 	.vendor            = X86_VENDOR_CYRIX,
-	.set_all	   = cyrix_set_all,
 	.set               = cyrix_set_arr,
 	.get               = cyrix_get_arr,
 	.get_free_region   = cyrix_get_free_region,
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 01/16] x86/mtrr: add comment for set_mtrr_state() serialization Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 02/16] x86/mtrr: remove unused cyrix_set_all() function Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-21 17:19   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 04/16] x86/mtrr: rename prepare_set() and post_set() Juergen Gross
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

In MTRR code use_intel() is only used in one source file, and the
relevant use_intel_if member of struct mtrr_ops is set only in
generic_mtrr_ops.

Replace use_intel() with a single flag in cacheinfo.c, which can be set
when assigning generic_mtrr_ops to mtrr_if. This allows to drop
use_intel_if from mtrr_ops, while preparing to support PAT without
MTRR. As another preparation for the PAT/MTRR decoupling use a bit for
MTRR control and one for PAT control. For now set both bits together,
this can be changed later.

As the new flag will be set only if mtrr_enabled is set, the test for
mtrr_enabled can be dropped at some places.

At the same time drop the local mtrr_enabled() function and rename
the __mtrr_enabled flag to mtrr_enabled.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
V4:
- rename cache_generic to memory_caching_control (Borislav Petkov)
- rename CACHE_GENERIC_* to CACHE_* (Borislav Petkov)
- get rid of use_generic in mtrr_bp_init() (Borislav Petkov)
---
 arch/x86/include/asm/cacheinfo.h   |  5 +++
 arch/x86/kernel/cpu/cacheinfo.c    |  3 ++
 arch/x86/kernel/cpu/mtrr/generic.c |  1 -
 arch/x86/kernel/cpu/mtrr/mtrr.c    | 55 +++++++++++++-----------------
 arch/x86/kernel/cpu/mtrr/mtrr.h    |  2 --
 5 files changed, 32 insertions(+), 34 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 86b2e0dcc4bf..c3873962a7cd 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -2,6 +2,11 @@
 #ifndef _ASM_X86_CACHEINFO_H
 #define _ASM_X86_CACHEINFO_H
 
+/* Kernel controls MTRR and/or PAT MSRs. */
+extern unsigned int memory_caching_control;
+#define CACHE_MTRR 0x01
+#define CACHE_PAT  0x02
+
 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 66556833d7af..5228fb9a3798 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -35,6 +35,9 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 /* Shared L2 cache maps */
 DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map);
 
+/* Kernel controls MTRR and/or PAT MSRs. */
+unsigned int memory_caching_control __ro_after_init = 0;
+
 struct _cache_table {
 	unsigned char descriptor;
 	char cache_type;
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index cd64eab02393..81742870ecc5 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -917,7 +917,6 @@ int positive_have_wrcomb(void)
  * Generic structure...
  */
 const struct mtrr_ops generic_mtrr_ops = {
-	.use_intel_if		= 1,
 	.set_all		= generic_set_all,
 	.get			= generic_get_mtrr,
 	.get_free_region	= generic_get_free_region,
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 2746cac9d8a9..dacb537da126 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -46,6 +46,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/rcupdate.h>
 
+#include <asm/cacheinfo.h>
 #include <asm/cpufeature.h>
 #include <asm/e820/api.h>
 #include <asm/mtrr.h>
@@ -58,12 +59,7 @@
 #define MTRR_TO_PHYS_WC_OFFSET 1000
 
 u32 num_var_ranges;
-static bool __mtrr_enabled;
-
-static bool mtrr_enabled(void)
-{
-	return __mtrr_enabled;
-}
+static bool mtrr_enabled;
 
 unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
 static DEFINE_MUTEX(mtrr_mutex);
@@ -119,11 +115,11 @@ static int have_wrcomb(void)
 }
 
 /*  This function returns the number of variable MTRRs  */
-static void __init set_num_var_ranges(void)
+static void __init set_num_var_ranges(bool use_generic)
 {
 	unsigned long config = 0, dummy;
 
-	if (use_intel())
+	if (use_generic)
 		rdmsr(MSR_MTRRcap, config, dummy);
 	else if (is_cpu(AMD) || is_cpu(HYGON))
 		config = 2;
@@ -303,7 +299,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
 	int i, replace, error;
 	mtrr_type ltype;
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return -ENXIO;
 
 	error = mtrr_if->validate_add_page(base, size, type);
@@ -451,7 +447,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
 int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
 	     bool increment)
 {
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -480,7 +476,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
 	unsigned long lbase, lsize;
 	int error = -EINVAL;
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return -ENODEV;
 
 	max = num_var_ranges;
@@ -540,7 +536,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
  */
 int mtrr_del(int reg, unsigned long base, unsigned long size)
 {
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -566,7 +562,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled() || !mtrr_enabled())
+	if (pat_enabled() || !mtrr_enabled)
 		return 0;  /* Success!  (We don't need to do anything.) */
 
 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
@@ -755,15 +751,17 @@ void __init mtrr_bp_init(void)
 	}
 
 	if (mtrr_if) {
-		__mtrr_enabled = true;
-		set_num_var_ranges();
+		mtrr_enabled = true;
+		set_num_var_ranges(mtrr_if == &generic_mtrr_ops);
 		init_table();
-		if (use_intel()) {
+		if (mtrr_if == &generic_mtrr_ops) {
 			/* BIOS may override */
-			__mtrr_enabled = get_mtrr_state();
+			mtrr_enabled = get_mtrr_state();
 
-			if (mtrr_enabled())
+			if (mtrr_enabled) {
 				mtrr_bp_pat_init();
+				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
+			}
 
 			if (mtrr_cleanup(phys_addr)) {
 				changed_by_mtrr_cleanup = 1;
@@ -772,7 +770,7 @@ void __init mtrr_bp_init(void)
 		}
 	}
 
-	if (!mtrr_enabled()) {
+	if (!mtrr_enabled) {
 		pr_info("Disabled\n");
 
 		/*
@@ -786,10 +784,7 @@ void __init mtrr_bp_init(void)
 
 void mtrr_ap_init(void)
 {
-	if (!mtrr_enabled())
-		return;
-
-	if (!use_intel() || mtrr_aps_delayed_init)
+	if (!memory_caching_control || mtrr_aps_delayed_init)
 		return;
 
 	/*
@@ -816,7 +811,7 @@ void mtrr_save_state(void)
 {
 	int first_cpu;
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return;
 
 	first_cpu = cpumask_first(cpu_online_mask);
@@ -825,9 +820,7 @@ void mtrr_save_state(void)
 
 void set_mtrr_aps_delayed_init(void)
 {
-	if (!mtrr_enabled())
-		return;
-	if (!use_intel())
+	if (!memory_caching_control)
 		return;
 
 	mtrr_aps_delayed_init = true;
@@ -838,7 +831,7 @@ void set_mtrr_aps_delayed_init(void)
  */
 void mtrr_aps_init(void)
 {
-	if (!use_intel() || !mtrr_enabled())
+	if (!memory_caching_control)
 		return;
 
 	/*
@@ -855,7 +848,7 @@ void mtrr_aps_init(void)
 
 void mtrr_bp_restore(void)
 {
-	if (!use_intel() || !mtrr_enabled())
+	if (!memory_caching_control)
 		return;
 
 	mtrr_if->set_all();
@@ -863,10 +856,10 @@ void mtrr_bp_restore(void)
 
 static int __init mtrr_init_finialize(void)
 {
-	if (!mtrr_enabled())
+	if (!mtrr_enabled)
 		return 0;
 
-	if (use_intel()) {
+	if (memory_caching_control & CACHE_MTRR) {
 		if (!changed_by_mtrr_cleanup)
 			mtrr_state_warn();
 		return 0;
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 2ac99e561181..88b1c4b6174a 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -14,7 +14,6 @@ extern unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
 
 struct mtrr_ops {
 	u32	vendor;
-	u32	use_intel_if;
 	void	(*set)(unsigned int reg, unsigned long base,
 		       unsigned long size, mtrr_type type);
 	void	(*set_all)(void);
@@ -61,7 +60,6 @@ extern u64 size_or_mask, size_and_mask;
 extern const struct mtrr_ops *mtrr_if;
 
 #define is_cpu(vnd)	(mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd)
-#define use_intel()	(mtrr_if && mtrr_if->use_intel_if == 1)
 
 extern unsigned int num_var_ranges;
 extern u64 mtrr_tom2;
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 04/16] x86/mtrr: rename prepare_set() and post_set()
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (2 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling Juergen Gross
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Rename the currently MTRR specific functions prepare_set() and
post_set() for preparing to move them. Make them non-static and put
their prototypes into cacheinfo.h, where they will end after moving
them to their final position anyway.

Expand the comment before the functions with an introductory line and
rename two related static variables, too.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- carved out from other patch (Borislav Petkov)
---
 arch/x86/include/asm/cacheinfo.h   |  3 +++
 arch/x86/kernel/cpu/mtrr/generic.c | 43 +++++++++++++++---------------
 2 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index c3873962a7cd..6159874b4183 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -10,4 +10,7 @@ extern unsigned int memory_caching_control;
 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
+void cache_disable(void);
+void cache_enable(void);
+
 #endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 81742870ecc5..aebdc90a2489 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 
 #include <asm/processor-flags.h>
+#include <asm/cacheinfo.h>
 #include <asm/cpufeature.h>
 #include <asm/tlbflush.h>
 #include <asm/mtrr.h>
@@ -396,9 +397,6 @@ print_fixed(unsigned base, unsigned step, const mtrr_type *types)
 	}
 }
 
-static void prepare_set(void);
-static void post_set(void);
-
 static void __init print_mtrr_state(void)
 {
 	unsigned int i;
@@ -450,11 +448,11 @@ void __init mtrr_bp_pat_init(void)
 	unsigned long flags;
 
 	local_irq_save(flags);
-	prepare_set();
+	cache_disable();
 
 	pat_init();
 
-	post_set();
+	cache_enable();
 	local_irq_restore(flags);
 }
 
@@ -687,7 +685,7 @@ static u32 deftype_lo, deftype_hi;
  * NOTE: The CPU must already be in a safe state for MTRR changes, including
  *       measures that only a single CPU can be active in set_mtrr_state() in
  *       order to not be subject to races for usage of deftype_lo (this is
- *       accomplished by taking set_atomicity_lock).
+ *       accomplished by taking cache_disable_lock).
  * RETURNS: 0 if no changes made, else a mask indicating what was changed.
  */
 static unsigned long set_mtrr_state(void)
@@ -718,18 +716,19 @@ static unsigned long set_mtrr_state(void)
 	return change_mask;
 }
 
-
-static unsigned long cr4;
-static DEFINE_RAW_SPINLOCK(set_atomicity_lock);
-
 /*
+ * Disable and enable caches. Needed for changing MTRRs and the PAT MSR.
+ *
  * Since we are disabling the cache don't allow any interrupts,
  * they would run extremely slow and would only increase the pain.
  *
  * The caller must ensure that local interrupts are disabled and
- * are reenabled after post_set() has been called.
+ * are reenabled after cache_enable() has been called.
  */
-static void prepare_set(void) __acquires(set_atomicity_lock)
+static unsigned long saved_cr4;
+static DEFINE_RAW_SPINLOCK(cache_disable_lock);
+
+void cache_disable(void) __acquires(cache_disable_lock)
 {
 	unsigned long cr0;
 
@@ -740,7 +739,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 	 * changes to the way the kernel boots
 	 */
 
-	raw_spin_lock(&set_atomicity_lock);
+	raw_spin_lock(&cache_disable_lock);
 
 	/* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
 	cr0 = read_cr0() | X86_CR0_CD;
@@ -757,8 +756,8 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 
 	/* Save value of CR4 and clear Page Global Enable (bit 7) */
 	if (boot_cpu_has(X86_FEATURE_PGE)) {
-		cr4 = __read_cr4();
-		__write_cr4(cr4 & ~X86_CR4_PGE);
+		saved_cr4 = __read_cr4();
+		__write_cr4(saved_cr4 & ~X86_CR4_PGE);
 	}
 
 	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
@@ -776,7 +775,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 		wbinvd();
 }
 
-static void post_set(void) __releases(set_atomicity_lock)
+void cache_enable(void) __releases(cache_disable_lock)
 {
 	/* Flush TLBs (no need to flush caches - they are disabled) */
 	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
@@ -790,8 +789,8 @@ static void post_set(void) __releases(set_atomicity_lock)
 
 	/* Restore value of CR4 */
 	if (boot_cpu_has(X86_FEATURE_PGE))
-		__write_cr4(cr4);
-	raw_spin_unlock(&set_atomicity_lock);
+		__write_cr4(saved_cr4);
+	raw_spin_unlock(&cache_disable_lock);
 }
 
 static void generic_set_all(void)
@@ -800,7 +799,7 @@ static void generic_set_all(void)
 	unsigned long flags;
 
 	local_irq_save(flags);
-	prepare_set();
+	cache_disable();
 
 	/* Actually set the state */
 	mask = set_mtrr_state();
@@ -808,7 +807,7 @@ static void generic_set_all(void)
 	/* also set PAT */
 	pat_init();
 
-	post_set();
+	cache_enable();
 	local_irq_restore(flags);
 
 	/* Use the atomic bitops to update the global mask */
@@ -839,7 +838,7 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
 	vr = &mtrr_state.var_ranges[reg];
 
 	local_irq_save(flags);
-	prepare_set();
+	cache_disable();
 
 	if (size == 0) {
 		/*
@@ -858,7 +857,7 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
 		mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
 	}
 
-	post_set();
+	cache_enable();
 	local_irq_restore(flags);
 }
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (3 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 04/16] x86/mtrr: rename prepare_set() and post_set() Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-26  9:24   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 06/16] x86: move some code out of arch/x86/kernel/cpu/mtrr Juergen Gross
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Split the MTRR specific actions from cache_disable() and cache_enable()
into the new functions mtrr_disable() and mtrr_enable().

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- carved out from other patch (Borislav Petkov)
---
 arch/x86/include/asm/mtrr.h        |  4 ++++
 arch/x86/kernel/cpu/mtrr/generic.c | 26 +++++++++++++++++++-------
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 76d726074c16..12a16caed395 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -48,6 +48,8 @@ extern void mtrr_aps_init(void);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
+void mtrr_disable(void);
+void mtrr_enable(void);
 #  else
 static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
@@ -87,6 +89,8 @@ static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 #define set_mtrr_aps_delayed_init() do {} while (0)
 #define mtrr_aps_init() do {} while (0)
 #define mtrr_bp_restore() do {} while (0)
+#define mtrr_disable() do {} while (0)
+#define mtrr_enable() do {} while (0)
 #  endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index aebdc90a2489..164d753e9867 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -716,6 +716,21 @@ static unsigned long set_mtrr_state(void)
 	return change_mask;
 }
 
+void mtrr_disable(void)
+{
+	/* Save MTRR state */
+	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
+
+	/* Disable MTRRs, and set the default type to uncached */
+	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
+}
+
+void mtrr_enable(void)
+{
+	/* Intel (P6) standard MTRRs */
+	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
+}
+
 /*
  * Disable and enable caches. Needed for changing MTRRs and the PAT MSR.
  *
@@ -764,11 +779,8 @@ void cache_disable(void) __acquires(cache_disable_lock)
 	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
 	flush_tlb_local();
 
-	/* Save MTRR state */
-	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
-
-	/* Disable MTRRs, and set the default type to uncached */
-	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
+	if (boot_cpu_has(X86_FEATURE_MTRR))
+		mtrr_disable();
 
 	/* Again, only flush caches if we have to. */
 	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
@@ -781,8 +793,8 @@ void cache_enable(void) __releases(cache_disable_lock)
 	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
 	flush_tlb_local();
 
-	/* Intel (P6) standard MTRRs */
-	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
+	if (boot_cpu_has(X86_FEATURE_MTRR))
+		mtrr_enable();
 
 	/* Enable caches */
 	write_cr0(read_cr0() & ~X86_CR0_CD);
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 06/16] x86: move some code out of arch/x86/kernel/cpu/mtrr
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (4 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 07/16] x86/mtrr: split generic_set_all() Juergen Gross
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Prepare making PAT and MTRR support independent from each other by
moving some code needed by both out of the MTRR specific sources.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- move code from cpu/common.c to cpu/cacheinfo.c (Borislav Petkov)
V4:
- carved out all non-movement modifications (Borislav Petkov)
---
 arch/x86/kernel/cpu/cacheinfo.c    | 77 ++++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/mtrr/generic.c | 74 ----------------------------
 2 files changed, 77 insertions(+), 74 deletions(-)

diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 5228fb9a3798..ff32b2b1ca23 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -20,6 +20,8 @@
 #include <asm/cacheinfo.h>
 #include <asm/amd_nb.h>
 #include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/tlbflush.h>
 
 #include "cpu.h"
 
@@ -1043,3 +1045,78 @@ int populate_cache_leaves(unsigned int cpu)
 
 	return 0;
 }
+
+/*
+ * Disable and enable caches. Needed for changing MTRRs and the PAT MSR.
+ *
+ * Since we are disabling the cache don't allow any interrupts,
+ * they would run extremely slow and would only increase the pain.
+ *
+ * The caller must ensure that local interrupts are disabled and
+ * are reenabled after cache_enable() has been called.
+ */
+static unsigned long saved_cr4;
+static DEFINE_RAW_SPINLOCK(cache_disable_lock);
+
+void cache_disable(void) __acquires(cache_disable_lock)
+{
+	unsigned long cr0;
+
+	/*
+	 * Note that this is not ideal
+	 * since the cache is only flushed/disabled for this CPU while the
+	 * MTRRs are changed, but changing this requires more invasive
+	 * changes to the way the kernel boots
+	 */
+
+	raw_spin_lock(&cache_disable_lock);
+
+	/* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
+	cr0 = read_cr0() | X86_CR0_CD;
+	write_cr0(cr0);
+
+	/*
+	 * Cache flushing is the most time-consuming step when programming
+	 * the MTRRs. Fortunately, as per the Intel Software Development
+	 * Manual, we can skip it if the processor supports cache self-
+	 * snooping.
+	 */
+	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
+		wbinvd();
+
+	/* Save value of CR4 and clear Page Global Enable (bit 7) */
+	if (boot_cpu_has(X86_FEATURE_PGE)) {
+		saved_cr4 = __read_cr4();
+		__write_cr4(saved_cr4 & ~X86_CR4_PGE);
+	}
+
+	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
+	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
+	flush_tlb_local();
+
+	if (boot_cpu_has(X86_FEATURE_MTRR))
+		mtrr_disable();
+
+	/* Again, only flush caches if we have to. */
+	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
+		wbinvd();
+}
+
+void cache_enable(void) __releases(cache_disable_lock)
+{
+	/* Flush TLBs (no need to flush caches - they are disabled) */
+	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
+	flush_tlb_local();
+
+	if (boot_cpu_has(X86_FEATURE_MTRR))
+		mtrr_enable();
+
+	/* Enable caches */
+	write_cr0(read_cr0() & ~X86_CR0_CD);
+
+	/* Restore value of CR4 */
+	if (boot_cpu_has(X86_FEATURE_PGE))
+		__write_cr4(saved_cr4);
+
+	raw_spin_unlock(&cache_disable_lock);
+}
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 164d753e9867..bfe13eedaca8 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -731,80 +731,6 @@ void mtrr_enable(void)
 	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
 }
 
-/*
- * Disable and enable caches. Needed for changing MTRRs and the PAT MSR.
- *
- * Since we are disabling the cache don't allow any interrupts,
- * they would run extremely slow and would only increase the pain.
- *
- * The caller must ensure that local interrupts are disabled and
- * are reenabled after cache_enable() has been called.
- */
-static unsigned long saved_cr4;
-static DEFINE_RAW_SPINLOCK(cache_disable_lock);
-
-void cache_disable(void) __acquires(cache_disable_lock)
-{
-	unsigned long cr0;
-
-	/*
-	 * Note that this is not ideal
-	 * since the cache is only flushed/disabled for this CPU while the
-	 * MTRRs are changed, but changing this requires more invasive
-	 * changes to the way the kernel boots
-	 */
-
-	raw_spin_lock(&cache_disable_lock);
-
-	/* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
-	cr0 = read_cr0() | X86_CR0_CD;
-	write_cr0(cr0);
-
-	/*
-	 * Cache flushing is the most time-consuming step when programming
-	 * the MTRRs. Fortunately, as per the Intel Software Development
-	 * Manual, we can skip it if the processor supports cache self-
-	 * snooping.
-	 */
-	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
-		wbinvd();
-
-	/* Save value of CR4 and clear Page Global Enable (bit 7) */
-	if (boot_cpu_has(X86_FEATURE_PGE)) {
-		saved_cr4 = __read_cr4();
-		__write_cr4(saved_cr4 & ~X86_CR4_PGE);
-	}
-
-	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
-	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
-	flush_tlb_local();
-
-	if (boot_cpu_has(X86_FEATURE_MTRR))
-		mtrr_disable();
-
-	/* Again, only flush caches if we have to. */
-	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
-		wbinvd();
-}
-
-void cache_enable(void) __releases(cache_disable_lock)
-{
-	/* Flush TLBs (no need to flush caches - they are disabled) */
-	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
-	flush_tlb_local();
-
-	if (boot_cpu_has(X86_FEATURE_MTRR))
-		mtrr_enable();
-
-	/* Enable caches */
-	write_cr0(read_cr0() & ~X86_CR0_CD);
-
-	/* Restore value of CR4 */
-	if (boot_cpu_has(X86_FEATURE_PGE))
-		__write_cr4(saved_cr4);
-	raw_spin_unlock(&cache_disable_lock);
-}
-
 static void generic_set_all(void)
 {
 	unsigned long mask, count;
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 07/16] x86/mtrr: split generic_set_all()
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (5 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 06/16] x86: move some code out of arch/x86/kernel/cpu/mtrr Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-26 10:37   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops Juergen Gross
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Split generic_set_all() into multiple parts, while moving the main
function body into cacheinfo.c.

Prepare the support of PAT without needing MTRR support by
moving the main function body of generic_set_all() into cacheinfo.c
while renaming it to cache_cpu_init(). The MTRR specific parts are
moved into a dedicated small function called by cache_cpu_init() in
order to make cache_cpu_init() as MTRR agnostic as possible.

The setting of smp_changes_mask is merged into the (new) function
mtrr_generic_set_state() used to call set_mtrr_state(). It was
probably split in ancient times, as atomic operations while running
uncached might be quite expensive, but OTOH only systems with a
broken BIOS should ever require to set any bit in smp_changes_mask,
so just hurting those devices with a penalty of a few microseconds
during boot shouldn't be a real issue.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
V4:
- remove some comments (Borislav Petkov)
---
 arch/x86/include/asm/cacheinfo.h   |  1 +
 arch/x86/include/asm/mtrr.h        |  2 ++
 arch/x86/kernel/cpu/cacheinfo.c    | 17 +++++++++++++++++
 arch/x86/kernel/cpu/mtrr/generic.c | 15 ++-------------
 4 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 6159874b4183..978bac70fd49 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -12,5 +12,6 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
 void cache_disable(void);
 void cache_enable(void);
+void cache_cpu_init(void);
 
 #endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 12a16caed395..986249a2b9b6 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -50,6 +50,7 @@ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
 void mtrr_disable(void);
 void mtrr_enable(void);
+void mtrr_generic_set_state(void);
 #  else
 static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
@@ -91,6 +92,7 @@ static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 #define mtrr_bp_restore() do {} while (0)
 #define mtrr_disable() do {} while (0)
 #define mtrr_enable() do {} while (0)
+#define mtrr_generic_set_state() do {} while (0)
 #  endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index ff32b2b1ca23..49b60a427fc9 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -1120,3 +1120,20 @@ void cache_enable(void) __releases(cache_disable_lock)
 
 	raw_spin_unlock(&cache_disable_lock);
 }
+
+void cache_cpu_init(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cache_disable();
+
+	if (memory_caching_control & CACHE_MTRR)
+		mtrr_generic_set_state();
+
+	if (memory_caching_control & CACHE_PAT)
+		pat_init();
+
+	cache_enable();
+	local_irq_restore(flags);
+}
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index bfe13eedaca8..32aebed25e3f 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -731,30 +731,19 @@ void mtrr_enable(void)
 	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
 }
 
-static void generic_set_all(void)
+void mtrr_generic_set_state(void)
 {
 	unsigned long mask, count;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	cache_disable();
 
 	/* Actually set the state */
 	mask = set_mtrr_state();
 
-	/* also set PAT */
-	pat_init();
-
-	cache_enable();
-	local_irq_restore(flags);
-
 	/* Use the atomic bitops to update the global mask */
 	for (count = 0; count < sizeof(mask) * 8; ++count) {
 		if (mask & 0x01)
 			set_bit(count, &smp_changes_mask);
 		mask >>= 1;
 	}
-
 }
 
 /**
@@ -854,7 +843,7 @@ int positive_have_wrcomb(void)
  * Generic structure...
  */
 const struct mtrr_ops generic_mtrr_ops = {
-	.set_all		= generic_set_all,
+	.set_all		= cache_cpu_init,
 	.get			= generic_get_mtrr,
 	.get_free_region	= generic_get_free_region,
 	.set			= generic_set_mtrr,
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (6 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 07/16] x86/mtrr: split generic_set_all() Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-27  9:18   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init() Juergen Gross
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Instead of using an indirect call to mtrr_if->set_all just call the
only possible target cache_cpu_init() directly. This enables to remove
the set_all callback from struct mtrr_ops.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 arch/x86/kernel/cpu/mtrr/generic.c |  1 -
 arch/x86/kernel/cpu/mtrr/mtrr.c    | 10 +++++-----
 arch/x86/kernel/cpu/mtrr/mtrr.h    |  2 --
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 32aebed25e3f..af8422c96b92 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -843,7 +843,6 @@ int positive_have_wrcomb(void)
  * Generic structure...
  */
 const struct mtrr_ops generic_mtrr_ops = {
-	.set_all		= cache_cpu_init,
 	.get			= generic_get_mtrr,
 	.get_free_region	= generic_get_free_region,
 	.set			= generic_set_mtrr,
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index dacb537da126..501ca1747d55 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -165,15 +165,15 @@ static int mtrr_rendezvous_handler(void *info)
 	 * saved, and we want to replicate that across all the cpus that come
 	 * online (either at the end of boot or resume or during a runtime cpu
 	 * online). If we're doing that, @reg is set to something special and on
-	 * all the cpu's we do mtrr_if->set_all() (On the logical cpu that
+	 * all the cpu's we do cache_cpu_init() (On the logical cpu that
 	 * started the boot/resume sequence, this might be a duplicate
-	 * set_all()).
+	 * cache_cpu_init()).
 	 */
 	if (data->smp_reg != ~0U) {
 		mtrr_if->set(data->smp_reg, data->smp_base,
 			     data->smp_size, data->smp_type);
 	} else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
-		mtrr_if->set_all();
+		cache_cpu_init();
 	}
 	return 0;
 }
@@ -765,7 +765,7 @@ void __init mtrr_bp_init(void)
 
 			if (mtrr_cleanup(phys_addr)) {
 				changed_by_mtrr_cleanup = 1;
-				mtrr_if->set_all();
+				cache_cpu_init();
 			}
 		}
 	}
@@ -851,7 +851,7 @@ void mtrr_bp_restore(void)
 	if (!memory_caching_control)
 		return;
 
-	mtrr_if->set_all();
+	cache_cpu_init();
 }
 
 static int __init mtrr_init_finialize(void)
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 88b1c4b6174a..3b1883185185 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -16,8 +16,6 @@ struct mtrr_ops {
 	u32	vendor;
 	void	(*set)(unsigned int reg, unsigned long base,
 		       unsigned long size, mtrr_type type);
-	void	(*set_all)(void);
-
 	void	(*get)(unsigned int reg, unsigned long *base,
 		       unsigned long *size, mtrr_type *type);
 	int	(*get_free_region)(unsigned long base, unsigned long size,
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init()
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (7 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-27  9:32   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 10/16] x86/mtrr: get rid of mtrr_enabled bool Juergen Gross
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

In case of the generic cache interface being used (Intel CPUs or a
64-bit system), the initialization sequence of the boot CPU is more
complicated as necessary:

- check if MTRR enabled, if yes, call mtrr_bp_pat_init() which will
  disable caching, set the PAT MSR, and reenable caching

- call mtrr_cleanup(), in case that changed anything, call
  cache_cpu_init() doing the same caching disable/enable dance as
  above, but this time with setting the (modified) MTRR state (even
  if MTRR was disabled) AND setting the PAT MSR (again even with
  disabled MTRR)

The sequence can be simplified a lot while removing potential
inconsistencies:

- check if MTRR enabled, if yes, call mtrr_cleanup() and then
  cache_cpu_init()

This ensures to:

- no longer disable/enable caching more than once

- avoid to set MTRRs and/or the PAT MSR on the boot processor in case
  of MTRR cleanups even if MTRRs meant to be disabled

With that mtrr_bp_pat_init() can be removed.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
---
 arch/x86/kernel/cpu/mtrr/generic.c | 14 --------------
 arch/x86/kernel/cpu/mtrr/mtrr.c    |  6 +-----
 arch/x86/kernel/cpu/mtrr/mtrr.h    |  1 -
 3 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index af8422c96b92..2f2485d6657f 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -442,20 +442,6 @@ 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);
-	cache_disable();
-
-	pat_init();
-
-	cache_enable();
-	local_irq_restore(flags);
-}
-
 /* Grab all of the MTRR state for this CPU into *state */
 bool __init get_mtrr_state(void)
 {
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 501ca1747d55..9e1b478ac896 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -759,12 +759,8 @@ void __init mtrr_bp_init(void)
 			mtrr_enabled = get_mtrr_state();
 
 			if (mtrr_enabled) {
-				mtrr_bp_pat_init();
 				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
-			}
-
-			if (mtrr_cleanup(phys_addr)) {
-				changed_by_mtrr_cleanup = 1;
+				changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr);
 				cache_cpu_init();
 			}
 		}
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 3b1883185185..c98928ceee6a 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -50,7 +50,6 @@ 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 __init set_mtrr_ops(const struct mtrr_ops *ops);
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 10/16] x86/mtrr: get rid of mtrr_enabled bool
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (8 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init() Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init Juergen Gross
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

There is no need for keeping mtrr_enabled, as it can easily be replaced
by testing mtrr_if to be not NULL.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- new patch
---
 arch/x86/kernel/cpu/mtrr/mtrr.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 9e1b478ac896..7eed5387e828 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -59,7 +59,6 @@
 #define MTRR_TO_PHYS_WC_OFFSET 1000
 
 u32 num_var_ranges;
-static bool mtrr_enabled;
 
 unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
 static DEFINE_MUTEX(mtrr_mutex);
@@ -299,7 +298,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
 	int i, replace, error;
 	mtrr_type ltype;
 
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return -ENXIO;
 
 	error = mtrr_if->validate_add_page(base, size, type);
@@ -447,7 +446,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
 int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
 	     bool increment)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -476,7 +475,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
 	unsigned long lbase, lsize;
 	int error = -EINVAL;
 
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return -ENODEV;
 
 	max = num_var_ranges;
@@ -536,7 +535,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
  */
 int mtrr_del(int reg, unsigned long base, unsigned long size)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -562,7 +561,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled() || !mtrr_enabled)
+	if (pat_enabled() || !mtrr_if)
 		return 0;  /* Success!  (We don't need to do anything.) */
 
 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
@@ -751,22 +750,21 @@ void __init mtrr_bp_init(void)
 	}
 
 	if (mtrr_if) {
-		mtrr_enabled = true;
 		set_num_var_ranges(mtrr_if == &generic_mtrr_ops);
 		init_table();
 		if (mtrr_if == &generic_mtrr_ops) {
 			/* BIOS may override */
-			mtrr_enabled = get_mtrr_state();
-
-			if (mtrr_enabled) {
+			if (get_mtrr_state()) {
 				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
 				changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr);
 				cache_cpu_init();
+			} else {
+				mtrr_if = NULL;
 			}
 		}
 	}
 
-	if (!mtrr_enabled) {
+	if (!mtrr_if) {
 		pr_info("Disabled\n");
 
 		/*
@@ -807,7 +805,7 @@ void mtrr_save_state(void)
 {
 	int first_cpu;
 
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return;
 
 	first_cpu = cpumask_first(cpu_online_mask);
@@ -852,7 +850,7 @@ void mtrr_bp_restore(void)
 
 static int __init mtrr_init_finialize(void)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_if)
 		return 0;
 
 	if (memory_caching_control & CACHE_MTRR) {
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (9 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 10/16] x86/mtrr: get rid of mtrr_enabled bool Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-27 12:18   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init() Juergen Gross
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

In order to prepare decoupling MTRR and PAT replace the MTRR specific
mtrr_aps_delayed_init flag with a more generic cache_aps_delayed_init
one.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
V4:
- reestablish function to set cache_aps_delayed_init (Borislav Petkov)
---
 arch/x86/include/asm/cacheinfo.h |  3 +++
 arch/x86/include/asm/mtrr.h      |  2 --
 arch/x86/kernel/cpu/cacheinfo.c  |  7 +++++++
 arch/x86/kernel/cpu/mtrr/mtrr.c  | 17 ++++-------------
 arch/x86/kernel/smpboot.c        |  5 +++--
 5 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 978bac70fd49..1339bf0908dc 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -7,11 +7,14 @@ extern unsigned int memory_caching_control;
 #define CACHE_MTRR 0x01
 #define CACHE_PAT  0x02
 
+extern bool cache_aps_delayed_init;
+
 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
 void cache_disable(void);
 void cache_enable(void);
 void cache_cpu_init(void);
+void set_cache_aps_delayed_init(void);
 
 #endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 986249a2b9b6..5d31219c8529 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -43,7 +43,6 @@ extern int mtrr_del(int reg, unsigned long base, unsigned long size);
 extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
 extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 extern void mtrr_ap_init(void);
-extern void set_mtrr_aps_delayed_init(void);
 extern void mtrr_aps_init(void);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
@@ -87,7 +86,6 @@ static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
 #define mtrr_ap_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)
 #define mtrr_disable() do {} while (0)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 49b60a427fc9..330aa412be63 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -1137,3 +1137,10 @@ void cache_cpu_init(void)
 	cache_enable();
 	local_irq_restore(flags);
 }
+
+bool cache_aps_delayed_init;
+
+void set_cache_aps_delayed_init(void)
+{
+	cache_aps_delayed_init = true;
+}
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 7eed5387e828..68376c924b75 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -64,7 +64,6 @@ unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
 static DEFINE_MUTEX(mtrr_mutex);
 
 u64 size_or_mask, size_and_mask;
-static bool mtrr_aps_delayed_init;
 
 static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
 
@@ -171,7 +170,7 @@ static int mtrr_rendezvous_handler(void *info)
 	if (data->smp_reg != ~0U) {
 		mtrr_if->set(data->smp_reg, data->smp_base,
 			     data->smp_size, data->smp_type);
-	} else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
+	} else if (cache_aps_delayed_init || !cpu_online(smp_processor_id())) {
 		cache_cpu_init();
 	}
 	return 0;
@@ -778,7 +777,7 @@ void __init mtrr_bp_init(void)
 
 void mtrr_ap_init(void)
 {
-	if (!memory_caching_control || mtrr_aps_delayed_init)
+	if (!memory_caching_control || cache_aps_delayed_init)
 		return;
 
 	/*
@@ -812,14 +811,6 @@ void mtrr_save_state(void)
 	smp_call_function_single(first_cpu, mtrr_save_fixed_ranges, NULL, 1);
 }
 
-void set_mtrr_aps_delayed_init(void)
-{
-	if (!memory_caching_control)
-		return;
-
-	mtrr_aps_delayed_init = true;
-}
-
 /*
  * Delayed MTRR initialization for all AP's
  */
@@ -833,11 +824,11 @@ void mtrr_aps_init(void)
 	 * by doing set_mtrr_aps_delayed_init(), prior to this point. If not,
 	 * then we are done.
 	 */
-	if (!mtrr_aps_delayed_init)
+	if (!cache_aps_delayed_init)
 		return;
 
 	set_mtrr(~0U, 0, 0, 0);
-	mtrr_aps_delayed_init = false;
+	cache_aps_delayed_init = false;
 }
 
 void mtrr_bp_restore(void)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index f24227bc3220..de2082c21e8b 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -58,6 +58,7 @@
 #include <linux/overflow.h>
 
 #include <asm/acpi.h>
+#include <asm/cacheinfo.h>
 #include <asm/desc.h>
 #include <asm/nmi.h>
 #include <asm/irq.h>
@@ -1428,7 +1429,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 	uv_system_init();
 
-	set_mtrr_aps_delayed_init();
+	set_cache_aps_delayed_init();
 
 	smp_quirk_init_udelay();
 
@@ -1439,7 +1440,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 void arch_thaw_secondary_cpus_begin(void)
 {
-	set_mtrr_aps_delayed_init();
+	set_cache_aps_delayed_init();
 }
 
 void arch_thaw_secondary_cpus_end(void)
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init()
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (10 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-29 10:07   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 13/16] x86: decouple pat and mtrr handling Juergen Gross
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, linux-pm
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Rafael J. Wysocki, Pavel Machek

Instead of having a stop_machine() handler for either a specific MTRR
register or all state at once, add a handler just for calling
cache_cpu_init() if appropriate.

Add functions for calling stop_machine() with this handler as well.

Add a generic replacements for mtrr_bp_restore() and a wrapper for
mtrr_bp_init().

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- completely new replacement of former patch 2
---
 arch/x86/include/asm/cacheinfo.h |  7 +--
 arch/x86/include/asm/mtrr.h      |  4 --
 arch/x86/kernel/cpu/cacheinfo.c  | 61 +++++++++++++++++++++-
 arch/x86/kernel/cpu/common.c     |  3 +-
 arch/x86/kernel/cpu/mtrr/mtrr.c  | 87 +-------------------------------
 arch/x86/kernel/setup.c          |  3 +-
 arch/x86/kernel/smpboot.c        |  4 +-
 arch/x86/power/cpu.c             |  3 +-
 8 files changed, 73 insertions(+), 99 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 1339bf0908dc..77fe39a11679 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -7,14 +7,15 @@ extern unsigned int memory_caching_control;
 #define CACHE_MTRR 0x01
 #define CACHE_PAT  0x02
 
-extern bool cache_aps_delayed_init;
-
 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
 void cache_disable(void);
 void cache_enable(void);
-void cache_cpu_init(void);
 void set_cache_aps_delayed_init(void);
+void cache_bp_init(void);
+void cache_bp_restore(void);
+void cache_ap_init(void);
+void cache_aps_init(void);
 
 #endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 5d31219c8529..ec73d1e5bafb 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -42,8 +42,6 @@ extern int mtrr_add_page(unsigned long base, unsigned long size,
 extern int mtrr_del(int reg, unsigned long base, unsigned long size);
 extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
 extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
-extern void mtrr_ap_init(void);
-extern void mtrr_aps_init(void);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
@@ -85,8 +83,6 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
-#define mtrr_ap_init() do {} while (0)
-#define mtrr_aps_init() do {} while (0)
 #define mtrr_bp_restore() do {} while (0)
 #define mtrr_disable() do {} while (0)
 #define mtrr_enable() do {} while (0)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 330aa412be63..5867325809a6 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -15,6 +15,7 @@
 #include <linux/capability.h>
 #include <linux/sysfs.h>
 #include <linux/pci.h>
+#include <linux/stop_machine.h>
 
 #include <asm/cpufeature.h>
 #include <asm/cacheinfo.h>
@@ -1121,7 +1122,7 @@ void cache_enable(void) __releases(cache_disable_lock)
 	raw_spin_unlock(&cache_disable_lock);
 }
 
-void cache_cpu_init(void)
+static void cache_cpu_init(void)
 {
 	unsigned long flags;
 
@@ -1138,9 +1139,65 @@ void cache_cpu_init(void)
 	local_irq_restore(flags);
 }
 
-bool cache_aps_delayed_init;
+static bool cache_aps_delayed_init;
 
 void set_cache_aps_delayed_init(void)
 {
 	cache_aps_delayed_init = true;
 }
+
+static int cache_rendezvous_handler(void *unused)
+{
+	if (cache_aps_delayed_init || !cpu_online(smp_processor_id()))
+		cache_cpu_init();
+
+	return 0;
+}
+
+void __init cache_bp_init(void)
+{
+	mtrr_bp_init();
+
+	if (memory_caching_control)
+		cache_cpu_init();
+}
+
+void cache_bp_restore(void)
+{
+	if (memory_caching_control)
+		cache_cpu_init();
+}
+
+void cache_ap_init(void)
+{
+	if (!memory_caching_control || cache_aps_delayed_init)
+		return;
+
+	/*
+	 * Ideally we should hold mtrr_mutex here to avoid mtrr entries
+	 * changed, but this routine will be called in cpu boot time,
+	 * holding the lock breaks it.
+	 *
+	 * This routine is called in two cases:
+	 *
+	 *   1. very early time of software resume, when there absolutely
+	 *      isn't mtrr entry changes;
+	 *
+	 *   2. cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug
+	 *      lock to prevent mtrr entry changes
+	 */
+	stop_machine_from_inactive_cpu(cache_rendezvous_handler, NULL,
+				       cpu_callout_mask);
+}
+
+/*
+ * Delayed cache initialization for all AP's
+ */
+void cache_aps_init(void)
+{
+	if (!memory_caching_control || !cache_aps_delayed_init)
+		return;
+
+	stop_machine(cache_rendezvous_handler, NULL, cpu_online_mask);
+	cache_aps_delayed_init = false;
+}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 3e508f239098..fd058b547f8d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -52,6 +52,7 @@
 #include <asm/cpu.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
+#include <asm/cacheinfo.h>
 #include <asm/memtype.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
@@ -1948,7 +1949,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
 #ifdef CONFIG_X86_32
 	enable_sep_cpu();
 #endif
-	mtrr_ap_init();
+	cache_ap_init();
 	validate_apic_and_package_id(c);
 	x86_spec_ctrl_setup_ap();
 	update_srbds_msr();
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 68376c924b75..61666931abc4 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -69,9 +69,6 @@ static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
 
 const struct mtrr_ops *mtrr_if;
 
-static void set_mtrr(unsigned int reg, unsigned long base,
-		     unsigned long size, mtrr_type type);
-
 void __init set_mtrr_ops(const struct mtrr_ops *ops)
 {
 	if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
@@ -154,25 +151,8 @@ static int mtrr_rendezvous_handler(void *info)
 {
 	struct set_mtrr_data *data = info;
 
-	/*
-	 * We use this same function to initialize the mtrrs during boot,
-	 * resume, runtime cpu online and on an explicit request to set a
-	 * specific MTRR.
-	 *
-	 * During boot or suspend, the state of the boot cpu's mtrrs has been
-	 * saved, and we want to replicate that across all the cpus that come
-	 * online (either at the end of boot or resume or during a runtime cpu
-	 * online). If we're doing that, @reg is set to something special and on
-	 * all the cpu's we do cache_cpu_init() (On the logical cpu that
-	 * started the boot/resume sequence, this might be a duplicate
-	 * cache_cpu_init()).
-	 */
-	if (data->smp_reg != ~0U) {
-		mtrr_if->set(data->smp_reg, data->smp_base,
-			     data->smp_size, data->smp_type);
-	} else if (cache_aps_delayed_init || !cpu_online(smp_processor_id())) {
-		cache_cpu_init();
-	}
+	mtrr_if->set(data->smp_reg, data->smp_base,
+		     data->smp_size, data->smp_type);
 	return 0;
 }
 
@@ -242,19 +222,6 @@ static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base,
 	stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask);
 }
 
-static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
-				      unsigned long size, mtrr_type type)
-{
-	struct set_mtrr_data data = { .smp_reg = reg,
-				      .smp_base = base,
-				      .smp_size = size,
-				      .smp_type = type
-				    };
-
-	stop_machine_from_inactive_cpu(mtrr_rendezvous_handler, &data,
-				       cpu_callout_mask);
-}
-
 /**
  * mtrr_add_page - Add a memory type region
  * @base: Physical base address of region in pages (in units of 4 kB!)
@@ -756,7 +723,6 @@ void __init mtrr_bp_init(void)
 			if (get_mtrr_state()) {
 				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
 				changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr);
-				cache_cpu_init();
 			} else {
 				mtrr_if = NULL;
 			}
@@ -775,27 +741,6 @@ void __init mtrr_bp_init(void)
 	}
 }
 
-void mtrr_ap_init(void)
-{
-	if (!memory_caching_control || cache_aps_delayed_init)
-		return;
-
-	/*
-	 * Ideally we should hold mtrr_mutex here to avoid mtrr entries
-	 * changed, but this routine will be called in cpu boot time,
-	 * holding the lock breaks it.
-	 *
-	 * This routine is called in two cases:
-	 *
-	 *   1. very early time of software resume, when there absolutely
-	 *      isn't mtrr entry changes;
-	 *
-	 *   2. cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug
-	 *      lock to prevent mtrr entry changes
-	 */
-	set_mtrr_from_inactive_cpu(~0U, 0, 0, 0);
-}
-
 /**
  * mtrr_save_state - Save current fixed-range MTRR state of the first
  *	cpu in cpu_online_mask.
@@ -811,34 +756,6 @@ void mtrr_save_state(void)
 	smp_call_function_single(first_cpu, mtrr_save_fixed_ranges, NULL, 1);
 }
 
-/*
- * Delayed MTRR initialization for all AP's
- */
-void mtrr_aps_init(void)
-{
-	if (!memory_caching_control)
-		return;
-
-	/*
-	 * Check if someone has requested the delay of AP MTRR initialization,
-	 * by doing set_mtrr_aps_delayed_init(), prior to this point. If not,
-	 * then we are done.
-	 */
-	if (!cache_aps_delayed_init)
-		return;
-
-	set_mtrr(~0U, 0, 0, 0);
-	cache_aps_delayed_init = false;
-}
-
-void mtrr_bp_restore(void)
-{
-	if (!memory_caching_control)
-		return;
-
-	cache_cpu_init();
-}
-
 static int __init mtrr_init_finialize(void)
 {
 	if (!mtrr_if)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 216fee7144ee..e0e185ee0229 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -34,6 +34,7 @@
 #include <asm/numa.h>
 #include <asm/bios_ebda.h>
 #include <asm/bugs.h>
+#include <asm/cacheinfo.h>
 #include <asm/cpu.h>
 #include <asm/efi.h>
 #include <asm/gart.h>
@@ -1075,7 +1076,7 @@ void __init setup_arch(char **cmdline_p)
 
 	/* update e820 for memory not covered by WB MTRRs */
 	if (IS_ENABLED(CONFIG_MTRR))
-		mtrr_bp_init();
+		cache_bp_init();
 	else
 		pat_disable("PAT support disabled because CONFIG_MTRR is disabled in the kernel.");
 
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index de2082c21e8b..fb225a02455f 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1445,7 +1445,7 @@ void arch_thaw_secondary_cpus_begin(void)
 
 void arch_thaw_secondary_cpus_end(void)
 {
-	mtrr_aps_init();
+	cache_aps_init();
 }
 
 /*
@@ -1488,7 +1488,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
 
 	nmi_selftest();
 	impress_friends();
-	mtrr_aps_init();
+	cache_aps_init();
 }
 
 static int __initdata setup_possible_cpus = -1;
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index bb176c72891c..754221c9a1c3 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -23,6 +23,7 @@
 #include <asm/fpu/api.h>
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
+#include <asm/cacheinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/cpu_device_id.h>
 #include <asm/microcode.h>
@@ -261,7 +262,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
 	do_fpu_end();
 	tsc_verify_tsc_adjust(true);
 	x86_platform.restore_sched_clock_state();
-	mtrr_bp_restore();
+	cache_bp_restore();
 	perf_restore_debug_store();
 
 	c = &cpu_data(smp_processor_id());
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 13/16] x86: decouple pat and mtrr handling
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (11 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init() Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-29 12:15   ` Borislav Petkov
  2022-10-04  8:10 ` [PATCH v4 14/16] x86: switch cache_ap_init() to hotplug callback Juergen Gross
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Andy Lutomirski, Peter Zijlstra

Today PAT is usable only with MTRR being active, with some nasty tweaks
to make PAT usable when running as Xen PV guest, which doesn't support
MTRR.

The reason for this coupling is, that both, PAT MSR changes and MTRR
changes, require a similar sequence and so full PAT support was added
using the already available MTRR handling.

Xen PV PAT handling can work without MTRR, as it just needs to consume
the PAT MSR setting done by the hypervisor without the ability and need
to change it. This in turn has resulted in a convoluted initialization
sequence and wrong decisions regarding cache mode availability due to
misguiding PAT availability flags.

Fix all of that by allowing to use PAT without MTRR and by reworking
the current PAT initialization sequence to match better with the newly
introduced generic cache initialization.

This removes the need of the recently added pat_force_disabled flag, so
remove the remnants of the patch adding it.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- former patch 3 completely reworked
---
 arch/x86/include/asm/memtype.h  |   5 +-
 arch/x86/kernel/cpu/cacheinfo.c |   3 +-
 arch/x86/kernel/cpu/mtrr/mtrr.c |  12 +--
 arch/x86/kernel/setup.c         |  13 +---
 arch/x86/mm/pat/memtype.c       | 127 ++++++++++----------------------
 5 files changed, 45 insertions(+), 115 deletions(-)

diff --git a/arch/x86/include/asm/memtype.h b/arch/x86/include/asm/memtype.h
index 9ca760e430b9..113b2fa51849 100644
--- a/arch/x86/include/asm/memtype.h
+++ b/arch/x86/include/asm/memtype.h
@@ -6,9 +6,8 @@
 #include <asm/pgtable_types.h>
 
 extern bool pat_enabled(void);
-extern void pat_disable(const char *reason);
-extern void pat_init(void);
-extern void init_cache_modes(void);
+extern void pat_bp_init(void);
+extern void pat_cpu_init(void);
 
 extern int memtype_reserve(u64 start, u64 end,
 		enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 5867325809a6..40c304314513 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -1133,7 +1133,7 @@ static void cache_cpu_init(void)
 		mtrr_generic_set_state();
 
 	if (memory_caching_control & CACHE_PAT)
-		pat_init();
+		pat_cpu_init();
 
 	cache_enable();
 	local_irq_restore(flags);
@@ -1157,6 +1157,7 @@ static int cache_rendezvous_handler(void *unused)
 void __init cache_bp_init(void)
 {
 	mtrr_bp_init();
+	pat_bp_init();
 
 	if (memory_caching_control)
 		cache_cpu_init();
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 61666931abc4..1b652fa768a6 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -721,7 +721,7 @@ void __init mtrr_bp_init(void)
 		if (mtrr_if == &generic_mtrr_ops) {
 			/* BIOS may override */
 			if (get_mtrr_state()) {
-				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
+				memory_caching_control |= CACHE_MTRR;
 				changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr);
 			} else {
 				mtrr_if = NULL;
@@ -729,16 +729,8 @@ void __init mtrr_bp_init(void)
 		}
 	}
 
-	if (!mtrr_if) {
+	if (!mtrr_if)
 		pr_info("Disabled\n");
-
-		/*
-		 * PAT initialization relies on MTRR's rendezvous handler.
-		 * Skip PAT init until the handler can initialize both
-		 * features independently.
-		 */
-		pat_disable("MTRRs disabled, skipping PAT initialization too.");
-	}
 }
 
 /**
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index e0e185ee0229..aacaa96f0195 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1075,23 +1075,12 @@ void __init setup_arch(char **cmdline_p)
 	max_pfn = e820__end_of_ram_pfn();
 
 	/* update e820 for memory not covered by WB MTRRs */
-	if (IS_ENABLED(CONFIG_MTRR))
-		cache_bp_init();
-	else
-		pat_disable("PAT support disabled because CONFIG_MTRR is disabled in the kernel.");
-
+	cache_bp_init();
 	if (mtrr_trim_uncached_memory(max_pfn))
 		max_pfn = e820__end_of_ram_pfn();
 
 	max_possible_pfn = max_pfn;
 
-	/*
-	 * This call is required when the CPU does not support PAT. If
-	 * mtrr_bp_init() invoked it already via pat_init() the call has no
-	 * effect.
-	 */
-	init_cache_modes();
-
 	/*
 	 * Define random base addresses for memory sections after max_pfn is
 	 * defined and before each memory section base is used.
diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c
index 66a209f7eb86..ce1f3246a3e3 100644
--- a/arch/x86/mm/pat/memtype.c
+++ b/arch/x86/mm/pat/memtype.c
@@ -43,6 +43,7 @@
 #include <linux/rbtree.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cacheinfo.h>
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
@@ -60,41 +61,34 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "" fmt
 
-static bool __read_mostly pat_bp_initialized;
 static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
-static bool __initdata pat_force_disabled = !IS_ENABLED(CONFIG_X86_PAT);
-static bool __read_mostly pat_bp_enabled;
-static bool __read_mostly pat_cm_initialized;
+static u64 __read_mostly pat_msr_val;
 
 /*
  * PAT support is enabled by default, but can be disabled for
  * various user-requested or hardware-forced reasons:
  */
-void pat_disable(const char *msg_reason)
+static void __init pat_disable(const char *msg_reason)
 {
 	if (pat_disabled)
 		return;
 
-	if (pat_bp_initialized) {
-		WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n");
-		return;
-	}
-
 	pat_disabled = true;
 	pr_info("x86/PAT: %s\n", msg_reason);
+
+	memory_caching_control &= ~CACHE_PAT;
 }
 
 static int __init nopat(char *str)
 {
 	pat_disable("PAT support disabled via boot option.");
-	pat_force_disabled = true;
 	return 0;
 }
 early_param("nopat", nopat);
 
 bool pat_enabled(void)
 {
-	return pat_bp_enabled;
+	return !pat_disabled;
 }
 EXPORT_SYMBOL_GPL(pat_enabled);
 
@@ -192,7 +186,8 @@ enum {
 
 #define CM(c) (_PAGE_CACHE_MODE_ ## c)
 
-static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
+static enum page_cache_mode __init pat_get_cache_mode(unsigned int pat_val,
+						      char *msg)
 {
 	enum page_cache_mode cache;
 	char *cache_mode;
@@ -219,14 +214,12 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
  * configuration.
  * Using lower indices is preferred, so we start with highest index.
  */
-static void __init_cache_modes(u64 pat)
+static void __init init_cache_modes(u64 pat)
 {
 	enum page_cache_mode cache;
 	char pat_msg[33];
 	int i;
 
-	WARN_ON_ONCE(pat_cm_initialized);
-
 	pat_msg[32] = 0;
 	for (i = 7; i >= 0; i--) {
 		cache = pat_get_cache_mode((pat >> (i * 8)) & 7,
@@ -234,34 +227,11 @@ static void __init_cache_modes(u64 pat)
 		update_cache_mode_entry(i, cache);
 	}
 	pr_info("x86/PAT: Configuration [0-7]: %s\n", pat_msg);
-
-	pat_cm_initialized = true;
 }
 
 #define PAT(x, y)	((u64)PAT_ ## y << ((x)*8))
 
-static void pat_bp_init(u64 pat)
-{
-	u64 tmp_pat;
-
-	if (!boot_cpu_has(X86_FEATURE_PAT)) {
-		pat_disable("PAT not supported by the CPU.");
-		return;
-	}
-
-	rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
-	if (!tmp_pat) {
-		pat_disable("PAT support disabled by the firmware.");
-		return;
-	}
-
-	wrmsrl(MSR_IA32_CR_PAT, pat);
-	pat_bp_enabled = true;
-
-	__init_cache_modes(pat);
-}
-
-static void pat_ap_init(u64 pat)
+void pat_cpu_init(void)
 {
 	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		/*
@@ -271,30 +241,35 @@ static void pat_ap_init(u64 pat)
 		panic("x86/PAT: PAT enabled, but not supported by secondary CPU\n");
 	}
 
-	wrmsrl(MSR_IA32_CR_PAT, pat);
+	wrmsrl(MSR_IA32_CR_PAT, pat_msr_val);
 }
 
-void __init init_cache_modes(void)
+/**
+ * pat_bp_init - Initialize the PAT MSR value and PAT table
+ *
+ * This function initializes PAT MSR value and PAT table with an OS-defined
+ * value to enable additional cache attributes, WC, WT and WP.
+ *
+ * This function prepares the calls of pat_cpu_init() via cache_cpu_init()
+ * on all cpus.
+ */
+void __init pat_bp_init(void)
 {
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u64 pat = 0;
 
-	if (pat_cm_initialized)
-		return;
+#ifndef CONFIG_X86_PAT
+	pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
+#endif
 
-	if (boot_cpu_has(X86_FEATURE_PAT)) {
-		/*
-		 * CPU supports PAT. Set PAT table to be consistent with
-		 * PAT MSR. This case supports "nopat" boot option, and
-		 * virtual machine environments which support PAT without
-		 * MTRRs. In specific, Xen has unique setup to PAT MSR.
-		 *
-		 * If PAT MSR returns 0, it is considered invalid and emulates
-		 * as No PAT.
-		 */
+	if (!boot_cpu_has(X86_FEATURE_PAT))
+		pat_disable("PAT not supported by the CPU.");
+	else
 		rdmsrl(MSR_IA32_CR_PAT, pat);
-	}
 
 	if (!pat) {
+		pat_disable("PAT support disabled by the firmware.");
+
 		/*
 		 * No PAT. Emulate the PAT table that corresponds to the two
 		 * cache bits, PWT (Write Through) and PCD (Cache Disable).
@@ -315,38 +290,14 @@ void __init init_cache_modes(void)
 		 */
 		pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
 		      PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
-	} else if (!pat_force_disabled && cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) {
-		/*
-		 * Clearly PAT is enabled underneath. Allow pat_enabled() to
-		 * reflect this.
-		 */
-		pat_bp_enabled = true;
 	}
 
-	__init_cache_modes(pat);
-}
-
-/**
- * pat_init - Initialize the PAT MSR and PAT table on the current CPU
- *
- * This function initializes PAT MSR and PAT table with an OS-defined value
- * to enable additional cache attributes, WC, WT and WP.
- *
- * This function must be called on all CPUs using the specific sequence of
- * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
- * procedure for PAT.
- */
-void pat_init(void)
-{
-	u64 pat;
-	struct cpuinfo_x86 *c = &boot_cpu_data;
-
-#ifndef CONFIG_X86_PAT
-	pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
-#endif
+	/* Xen PV doesn't allow to set PAT MSR, but all cache modes are fine. */
+	if (pat_disabled || cpu_feature_enabled(X86_FEATURE_XENPV)) {
+		init_cache_modes(pat);
 
-	if (pat_disabled)
 		return;
+	}
 
 	if ((c->x86_vendor == X86_VENDOR_INTEL) &&
 	    (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
@@ -404,12 +355,10 @@ void pat_init(void)
 		      PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
 	}
 
-	if (!pat_bp_initialized) {
-		pat_bp_init(pat);
-		pat_bp_initialized = true;
-	} else {
-		pat_ap_init(pat);
-	}
+	pat_msr_val = pat;
+	memory_caching_control |= CACHE_PAT;
+
+	init_cache_modes(pat);
 }
 
 #undef PAT
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 14/16] x86: switch cache_ap_init() to hotplug callback
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (12 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 13/16] x86: decouple pat and mtrr handling Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 15/16] x86: do MTRR/PAT setup on all secondary CPUs in parallel Juergen Gross
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Instead of explicitly calling cache_ap_init() in
identify_secondary_cpu() use a cpu hotplug callback instead. By
registering the callback only after having started the non-boot CPUs
and initializing cache_aps_delayed_init with "true", calling
set_cache_aps_delayed_init() at boot time can be dropped.

It should be noted that this change results in cache_ap_init() being
called a little bit later when hotplugging CPUs. By using a new
hotplug slot right at the start of the low level bringup this is not
problematic, as no operations requiring a specific caching mode are
performed that early in CPU initialization.

Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- new patch
---
 arch/x86/include/asm/cacheinfo.h |  1 -
 arch/x86/kernel/cpu/cacheinfo.c  | 18 +++++++++++++++---
 arch/x86/kernel/cpu/common.c     |  1 -
 arch/x86/kernel/smpboot.c        |  2 --
 include/linux/cpuhotplug.h       |  1 +
 5 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 77fe39a11679..f6c521687535 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -15,7 +15,6 @@ void cache_enable(void);
 void set_cache_aps_delayed_init(void);
 void cache_bp_init(void);
 void cache_bp_restore(void);
-void cache_ap_init(void);
 void cache_aps_init(void);
 
 #endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 40c304314513..48ce48827f87 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/cacheinfo.h>
 #include <linux/cpu.h>
+#include <linux/cpuhotplug.h>
 #include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/sysfs.h>
@@ -1139,7 +1140,7 @@ static void cache_cpu_init(void)
 	local_irq_restore(flags);
 }
 
-static bool cache_aps_delayed_init;
+static bool cache_aps_delayed_init = true;
 
 void set_cache_aps_delayed_init(void)
 {
@@ -1169,10 +1170,10 @@ void cache_bp_restore(void)
 		cache_cpu_init();
 }
 
-void cache_ap_init(void)
+static int cache_ap_init(unsigned int cpu)
 {
 	if (!memory_caching_control || cache_aps_delayed_init)
-		return;
+		return 0;
 
 	/*
 	 * Ideally we should hold mtrr_mutex here to avoid mtrr entries
@@ -1189,6 +1190,8 @@ void cache_ap_init(void)
 	 */
 	stop_machine_from_inactive_cpu(cache_rendezvous_handler, NULL,
 				       cpu_callout_mask);
+
+	return 0;
 }
 
 /*
@@ -1202,3 +1205,12 @@ void cache_aps_init(void)
 	stop_machine(cache_rendezvous_handler, NULL, cpu_online_mask);
 	cache_aps_delayed_init = false;
 }
+
+static int __init cache_ap_register(void)
+{
+	cpuhp_setup_state_nocalls(CPUHP_AP_CACHECTRL_STARTING,
+				  "x86/cachectrl:starting",
+				  cache_ap_init, NULL);
+	return 0;
+}
+core_initcall(cache_ap_register);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index fd058b547f8d..bf4ac1cb93d7 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1949,7 +1949,6 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
 #ifdef CONFIG_X86_32
 	enable_sep_cpu();
 #endif
-	cache_ap_init();
 	validate_apic_and_package_id(c);
 	x86_spec_ctrl_setup_ap();
 	update_srbds_msr();
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index fb225a02455f..d90be0a80560 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1429,8 +1429,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 	uv_system_init();
 
-	set_cache_aps_delayed_init();
-
 	smp_quirk_init_udelay();
 
 	speculative_store_bypass_ht_init();
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index f61447913db9..0d277b4b025a 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -140,6 +140,7 @@ enum cpuhp_state {
 	 */
 	CPUHP_AP_IDLE_DEAD,
 	CPUHP_AP_OFFLINE,
+	CPUHP_AP_CACHECTRL_STARTING,
 	CPUHP_AP_SCHED_STARTING,
 	CPUHP_AP_RCUTREE_DYING,
 	CPUHP_AP_CPU_PM_STARTING,
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 15/16] x86: do MTRR/PAT setup on all secondary CPUs in parallel
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (13 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 14/16] x86: switch cache_ap_init() to hotplug callback Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-04  8:10 ` [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization Juergen Gross
  2022-10-19  7:18 ` [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

Instead of serializing MTRR/PAT setup on the secondary CPUs in order
to avoid clobbering of static variables used by the setup process, put
those variables into a structure held on the stack and drop the
serialization.

This speeds up the start of secondary cpus a little bit (on a small
system with 8 CPUs the time needed for starting the secondary CPUs was
measured to go down from about 60 milliseconds without this patch to
about 55 milliseconds with this patch applied).

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- new patch
---
 arch/x86/include/asm/cacheinfo.h   | 10 ++++++--
 arch/x86/include/asm/mtrr.h        | 13 +++++-----
 arch/x86/kernel/cpu/cacheinfo.c    | 28 ++++++++-------------
 arch/x86/kernel/cpu/mtrr/generic.c | 40 ++++++++++++++----------------
 4 files changed, 45 insertions(+), 46 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index f6c521687535..77ddc04c4975 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -10,8 +10,14 @@ extern unsigned int memory_caching_control;
 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
-void cache_disable(void);
-void cache_enable(void);
+struct cache_state {
+	unsigned long cr4;
+	u32 mtrr_deftype_lo;
+	u32 mtrr_deftype_hi;
+};
+
+void cache_disable(struct cache_state *state);
+void cache_enable(struct cache_state *state);
 void set_cache_aps_delayed_init(void);
 void cache_bp_init(void);
 void cache_bp_restore(void);
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index ec73d1e5bafb..67c16c813259 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -23,6 +23,7 @@
 #ifndef _ASM_X86_MTRR_H
 #define _ASM_X86_MTRR_H
 
+#include <asm/cacheinfo.h>
 #include <uapi/asm/mtrr.h>
 
 void mtrr_bp_init(void);
@@ -45,9 +46,9 @@ extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
-void mtrr_disable(void);
-void mtrr_enable(void);
-void mtrr_generic_set_state(void);
+void mtrr_disable(struct cache_state *state);
+void mtrr_enable(struct cache_state *state);
+void mtrr_generic_set_state(struct cache_state *state);
 #  else
 static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
@@ -84,9 +85,9 @@ static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
 #define mtrr_bp_restore() do {} while (0)
-#define mtrr_disable() do {} while (0)
-#define mtrr_enable() do {} while (0)
-#define mtrr_generic_set_state() do {} while (0)
+#define mtrr_disable(s) do {} while (0)
+#define mtrr_enable(s) do {} while (0)
+#define mtrr_generic_set_state(s) do {} while (0)
 #  endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 48ce48827f87..84684b50a5ce 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -1057,10 +1057,7 @@ int populate_cache_leaves(unsigned int cpu)
  * The caller must ensure that local interrupts are disabled and
  * are reenabled after cache_enable() has been called.
  */
-static unsigned long saved_cr4;
-static DEFINE_RAW_SPINLOCK(cache_disable_lock);
-
-void cache_disable(void) __acquires(cache_disable_lock)
+void cache_disable(struct cache_state *state)
 {
 	unsigned long cr0;
 
@@ -1071,8 +1068,6 @@ void cache_disable(void) __acquires(cache_disable_lock)
 	 * changes to the way the kernel boots
 	 */
 
-	raw_spin_lock(&cache_disable_lock);
-
 	/* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
 	cr0 = read_cr0() | X86_CR0_CD;
 	write_cr0(cr0);
@@ -1088,8 +1083,8 @@ void cache_disable(void) __acquires(cache_disable_lock)
 
 	/* Save value of CR4 and clear Page Global Enable (bit 7) */
 	if (boot_cpu_has(X86_FEATURE_PGE)) {
-		saved_cr4 = __read_cr4();
-		__write_cr4(saved_cr4 & ~X86_CR4_PGE);
+		state->cr4 = __read_cr4();
+		__write_cr4(state->cr4 & ~X86_CR4_PGE);
 	}
 
 	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
@@ -1097,46 +1092,45 @@ void cache_disable(void) __acquires(cache_disable_lock)
 	flush_tlb_local();
 
 	if (boot_cpu_has(X86_FEATURE_MTRR))
-		mtrr_disable();
+		mtrr_disable(state);
 
 	/* Again, only flush caches if we have to. */
 	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
 		wbinvd();
 }
 
-void cache_enable(void) __releases(cache_disable_lock)
+void cache_enable(struct cache_state *state)
 {
 	/* Flush TLBs (no need to flush caches - they are disabled) */
 	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
 	flush_tlb_local();
 
 	if (boot_cpu_has(X86_FEATURE_MTRR))
-		mtrr_enable();
+		mtrr_enable(state);
 
 	/* Enable caches */
 	write_cr0(read_cr0() & ~X86_CR0_CD);
 
 	/* Restore value of CR4 */
 	if (boot_cpu_has(X86_FEATURE_PGE))
-		__write_cr4(saved_cr4);
-
-	raw_spin_unlock(&cache_disable_lock);
+		__write_cr4(state->cr4);
 }
 
 static void cache_cpu_init(void)
 {
 	unsigned long flags;
+	struct cache_state state;
 
 	local_irq_save(flags);
-	cache_disable();
+	cache_disable(&state);
 
 	if (memory_caching_control & CACHE_MTRR)
-		mtrr_generic_set_state();
+		mtrr_generic_set_state(&state);
 
 	if (memory_caching_control & CACHE_PAT)
 		pat_cpu_init();
 
-	cache_enable();
+	cache_enable(&state);
 	local_irq_restore(flags);
 }
 
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 2f2485d6657f..cddb440f330d 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -663,18 +663,13 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
 	return changed;
 }
 
-static u32 deftype_lo, deftype_hi;
-
 /**
  * set_mtrr_state - Set the MTRR state for this CPU.
  *
- * NOTE: The CPU must already be in a safe state for MTRR changes, including
- *       measures that only a single CPU can be active in set_mtrr_state() in
- *       order to not be subject to races for usage of deftype_lo (this is
- *       accomplished by taking cache_disable_lock).
+ * NOTE: The CPU must already be in a safe state for MTRR changes.
  * RETURNS: 0 if no changes made, else a mask indicating what was changed.
  */
-static unsigned long set_mtrr_state(void)
+static unsigned long set_mtrr_state(struct cache_state *state)
 {
 	unsigned long change_mask = 0;
 	unsigned int i;
@@ -691,38 +686,40 @@ static unsigned long set_mtrr_state(void)
 	 * Set_mtrr_restore restores the old value of MTRRdefType,
 	 * so to set it we fiddle with the saved value:
 	 */
-	if ((deftype_lo & 0xff) != mtrr_state.def_type
-	    || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
-
-		deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type |
-			     (mtrr_state.enabled << 10);
+	if ((state->mtrr_deftype_lo & 0xff) != mtrr_state.def_type
+	    || ((state->mtrr_deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
+		state->mtrr_deftype_lo = (state->mtrr_deftype_lo & ~0xcff) |
+					 mtrr_state.def_type |
+					 (mtrr_state.enabled << 10);
 		change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
 	}
 
 	return change_mask;
 }
 
-void mtrr_disable(void)
+void mtrr_disable(struct cache_state *state)
 {
 	/* Save MTRR state */
-	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
+	rdmsr(MSR_MTRRdefType, state->mtrr_deftype_lo, state->mtrr_deftype_hi);
 
 	/* Disable MTRRs, and set the default type to uncached */
-	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
+	mtrr_wrmsr(MSR_MTRRdefType, state->mtrr_deftype_lo & ~0xcff,
+		   state->mtrr_deftype_hi);
 }
 
-void mtrr_enable(void)
+void mtrr_enable(struct cache_state *state)
 {
 	/* Intel (P6) standard MTRRs */
-	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
+	mtrr_wrmsr(MSR_MTRRdefType, state->mtrr_deftype_lo,
+		   state->mtrr_deftype_hi);
 }
 
-void mtrr_generic_set_state(void)
+void mtrr_generic_set_state(struct cache_state *state)
 {
 	unsigned long mask, count;
 
 	/* Actually set the state */
-	mask = set_mtrr_state();
+	mask = set_mtrr_state(state);
 
 	/* Use the atomic bitops to update the global mask */
 	for (count = 0; count < sizeof(mask) * 8; ++count) {
@@ -747,11 +744,12 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
 {
 	unsigned long flags;
 	struct mtrr_var_range *vr;
+	struct cache_state state;
 
 	vr = &mtrr_state.var_ranges[reg];
 
 	local_irq_save(flags);
-	cache_disable();
+	cache_disable(&state);
 
 	if (size == 0) {
 		/*
@@ -770,7 +768,7 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
 		mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
 	}
 
-	cache_enable();
+	cache_enable(&state);
 	local_irq_restore(flags);
 }
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (14 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 15/16] x86: do MTRR/PAT setup on all secondary CPUs in parallel Juergen Gross
@ 2022-10-04  8:10 ` Juergen Gross
  2022-10-30 12:06   ` Borislav Petkov
  2022-10-19  7:18 ` [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
  16 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-04  8:10 UTC (permalink / raw)
  To: linux-kernel, x86
  Cc: Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin

The way mtrr_if is initialized with the correct mtrr_ops structure is
quite weird.

Simplify that by dropping the vendor specific init functions and the
mtrr_ops[] array. Replace those with direct assignments of the related
vendor specific ops array to mtrr_if.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4:
- new patch
---
 arch/x86/kernel/cpu/mtrr/amd.c     |  8 +-------
 arch/x86/kernel/cpu/mtrr/centaur.c |  8 +-------
 arch/x86/kernel/cpu/mtrr/cyrix.c   |  8 +-------
 arch/x86/kernel/cpu/mtrr/mtrr.c    | 30 +++---------------------------
 arch/x86/kernel/cpu/mtrr/mtrr.h    | 15 +++++++++------
 5 files changed, 15 insertions(+), 54 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c
index a65a0272096d..eff6ac62c0ff 100644
--- a/arch/x86/kernel/cpu/mtrr/amd.c
+++ b/arch/x86/kernel/cpu/mtrr/amd.c
@@ -109,7 +109,7 @@ amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
 	return 0;
 }
 
-static const struct mtrr_ops amd_mtrr_ops = {
+const struct mtrr_ops amd_mtrr_ops = {
 	.vendor            = X86_VENDOR_AMD,
 	.set               = amd_set_mtrr,
 	.get               = amd_get_mtrr,
@@ -117,9 +117,3 @@ static const struct mtrr_ops amd_mtrr_ops = {
 	.validate_add_page = amd_validate_add_page,
 	.have_wrcomb       = positive_have_wrcomb,
 };
-
-int __init amd_init_mtrr(void)
-{
-	set_mtrr_ops(&amd_mtrr_ops);
-	return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c
index f27177816569..b8a74eddde83 100644
--- a/arch/x86/kernel/cpu/mtrr/centaur.c
+++ b/arch/x86/kernel/cpu/mtrr/centaur.c
@@ -111,7 +111,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t
 	return 0;
 }
 
-static const struct mtrr_ops centaur_mtrr_ops = {
+const struct mtrr_ops centaur_mtrr_ops = {
 	.vendor            = X86_VENDOR_CENTAUR,
 	.set               = centaur_set_mcr,
 	.get               = centaur_get_mcr,
@@ -119,9 +119,3 @@ static const struct mtrr_ops centaur_mtrr_ops = {
 	.validate_add_page = centaur_validate_add_page,
 	.have_wrcomb       = positive_have_wrcomb,
 };
-
-int __init centaur_init_mtrr(void)
-{
-	set_mtrr_ops(&centaur_mtrr_ops);
-	return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index c77d3b0a5bf2..173b9e01e623 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -234,7 +234,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
 	post_set();
 }
 
-static const struct mtrr_ops cyrix_mtrr_ops = {
+const struct mtrr_ops cyrix_mtrr_ops = {
 	.vendor            = X86_VENDOR_CYRIX,
 	.set               = cyrix_set_arr,
 	.get               = cyrix_get_arr,
@@ -242,9 +242,3 @@ static const struct mtrr_ops cyrix_mtrr_ops = {
 	.validate_add_page = generic_validate_add_page,
 	.have_wrcomb       = positive_have_wrcomb,
 };
-
-int __init cyrix_init_mtrr(void)
-{
-	set_mtrr_ops(&cyrix_mtrr_ops);
-	return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 1b652fa768a6..7ba68356c0ff 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -65,16 +65,8 @@ static DEFINE_MUTEX(mtrr_mutex);
 
 u64 size_or_mask, size_and_mask;
 
-static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
-
 const struct mtrr_ops *mtrr_if;
 
-void __init set_mtrr_ops(const struct mtrr_ops *ops)
-{
-	if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
-		mtrr_ops[ops->vendor] = ops;
-}
-
 /*  Returns non-zero if we have the write-combining memory type  */
 static int have_wrcomb(void)
 {
@@ -578,20 +570,6 @@ int arch_phys_wc_index(int handle)
 }
 EXPORT_SYMBOL_GPL(arch_phys_wc_index);
 
-/*
- * HACK ALERT!
- * These should be called implicitly, but we can't yet until all the initcall
- * stuff is done...
- */
-static void __init init_ifs(void)
-{
-#ifndef CONFIG_X86_64
-	amd_init_mtrr();
-	cyrix_init_mtrr();
-	centaur_init_mtrr();
-#endif
-}
-
 /* The suspend/resume methods are only for CPU without MTRR. CPU using generic
  * MTRR driver doesn't require this
  */
@@ -649,8 +627,6 @@ void __init mtrr_bp_init(void)
 {
 	u32 phys_addr;
 
-	init_ifs();
-
 	phys_addr = 32;
 
 	if (boot_cpu_has(X86_FEATURE_MTRR)) {
@@ -691,21 +667,21 @@ void __init mtrr_bp_init(void)
 		case X86_VENDOR_AMD:
 			if (cpu_feature_enabled(X86_FEATURE_K6_MTRR)) {
 				/* Pre-Athlon (K6) AMD CPU MTRRs */
-				mtrr_if = mtrr_ops[X86_VENDOR_AMD];
+				mtrr_if = vendor_mtrr_ops(amd_mtrr_ops);
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
 			break;
 		case X86_VENDOR_CENTAUR:
 			if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR)) {
-				mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
+				mtrr_if = vendor_mtrr_ops(centaur_mtrr_ops);
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
 			break;
 		case X86_VENDOR_CYRIX:
 			if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR)) {
-				mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
+				mtrr_if = vendor_mtrr_ops(cyrix_mtrr_ops);
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index c98928ceee6a..7a7387356192 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -51,8 +51,6 @@ 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);
 
-extern void __init set_mtrr_ops(const struct mtrr_ops *ops);
-
 extern u64 size_or_mask, size_and_mask;
 extern const struct mtrr_ops *mtrr_if;
 
@@ -66,10 +64,15 @@ void mtrr_state_warn(void);
 const char *mtrr_attrib_to_str(int x);
 void mtrr_wrmsr(unsigned, unsigned, unsigned);
 
-/* CPU specific mtrr init functions */
-int amd_init_mtrr(void);
-int cyrix_init_mtrr(void);
-int centaur_init_mtrr(void);
+/* CPU specific mtrr_ops vectors. */
+extern const struct mtrr_ops amd_mtrr_ops;
+extern const struct mtrr_ops cyrix_mtrr_ops;
+extern const struct mtrr_ops centaur_mtrr_ops;
+#ifdef CONFIG_X86_64
+#define vendor_mtrr_ops(x) NULL
+#else
+#define vendor_mtrr_ops(x) &(x)
+#endif
 
 extern int changed_by_mtrr_cleanup;
 extern int mtrr_cleanup(unsigned address_bits);
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 00/16] x86: make pat and mtrr independent from each other
  2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
                   ` (15 preceding siblings ...)
  2022-10-04  8:10 ` [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization Juergen Gross
@ 2022-10-19  7:18 ` Juergen Gross
  16 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-19  7:18 UTC (permalink / raw)
  To: linux-kernel, x86, linux-pm
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Rafael J. Wysocki, Pavel Machek, Andy Lutomirski,
	Peter Zijlstra


[-- Attachment #1.1.1: Type: text/plain, Size: 3277 bytes --]

Ping?

On 04.10.22 10:10, Juergen Gross wrote:
> Today PAT can't be used without MTRR being available, unless MTRR is at
> least configured via CONFIG_MTRR and the system is running as Xen PV
> guest. In this case PAT is automatically available via the hypervisor,
> but the PAT MSR can't be modified by the kernel and MTRR is disabled.
> 
> The same applies to a kernel built with no MTRR support: it won't
> allow to use the PAT MSR, even if there is no technical reason for
> that, other than setting up PAT on all cpus the same way (which is a
> requirement of the processor's cache management) is relying on some
> MTRR specific code.
> 
> Fix all of that by:
> 
> - moving the function needed by PAT from MTRR specific code one level
>    up
> - reworking the init sequences of MTRR and PAT to be more similar to
>    each other without calling PAT from MTRR code
> - removing the dependency of PAT on MTRR
> 
> While working on that I discovered two minor bugs in MTRR code, which
> are fixed, too.
> 
> There is some more cleanup done reducing code size.
> 
> Changes in V4:
> - new patches 10, 14, 15, 16
> - split up old patch 4 into 3 patches
> - addressed comments
> 
> Changes in V3:
> - replace patch 1 by just adding a comment
> 
> Changes in V2:
> - complete rework of the patches based on comments by Boris Petkov
> - added several patches to the series
> 
> Juergen Gross (16):
>    x86/mtrr: add comment for set_mtrr_state() serialization
>    x86/mtrr: remove unused cyrix_set_all() function
>    x86/mtrr: replace use_intel() with a local flag
>    x86/mtrr: rename prepare_set() and post_set()
>    x86/mtrr: split MTRR specific handling from cache dis/enabling
>    x86: move some code out of arch/x86/kernel/cpu/mtrr
>    x86/mtrr: split generic_set_all()
>    x86/mtrr: remove set_all callback from struct mtrr_ops
>    x86/mtrr: simplify mtrr_bp_init()
>    x86/mtrr: get rid of mtrr_enabled bool
>    x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init
>    x86/mtrr: add a stop_machine() handler calling only cache_cpu_init()
>    x86: decouple pat and mtrr handling
>    x86: switch cache_ap_init() to hotplug callback
>    x86: do MTRR/PAT setup on all secondary CPUs in parallel
>    x86/mtrr: simplify mtrr_ops initialization
> 
>   arch/x86/include/asm/cacheinfo.h   |  18 +++
>   arch/x86/include/asm/memtype.h     |   5 +-
>   arch/x86/include/asm/mtrr.h        |  13 +-
>   arch/x86/kernel/cpu/cacheinfo.c    | 168 ++++++++++++++++++++++++++
>   arch/x86/kernel/cpu/common.c       |   2 +-
>   arch/x86/kernel/cpu/mtrr/amd.c     |   8 +-
>   arch/x86/kernel/cpu/mtrr/centaur.c |   8 +-
>   arch/x86/kernel/cpu/mtrr/cyrix.c   |  42 +------
>   arch/x86/kernel/cpu/mtrr/generic.c | 127 +++-----------------
>   arch/x86/kernel/cpu/mtrr/mtrr.c    | 185 ++++-------------------------
>   arch/x86/kernel/cpu/mtrr/mtrr.h    |  20 ++--
>   arch/x86/kernel/setup.c            |  14 +--
>   arch/x86/kernel/smpboot.c          |   9 +-
>   arch/x86/mm/pat/memtype.c          | 127 ++++++--------------
>   arch/x86/power/cpu.c               |   3 +-
>   include/linux/cpuhotplug.h         |   1 +
>   16 files changed, 298 insertions(+), 452 deletions(-)
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [tip: x86/cpu] x86/mtrr: Remove unused cyrix_set_all() function
  2022-10-04  8:10 ` [PATCH v4 02/16] x86/mtrr: remove unused cyrix_set_all() function Juergen Gross
@ 2022-10-20 14:13   ` tip-bot2 for Juergen Gross
  0 siblings, 0 replies; 39+ messages in thread
From: tip-bot2 for Juergen Gross @ 2022-10-20 14:13 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Juergen Gross, Borislav Petkov, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     04ba8747e1329fa9e274b4634d792f811a3b0677
Gitweb:        https://git.kernel.org/tip/04ba8747e1329fa9e274b4634d792f811a3b0677
Author:        Juergen Gross <jgross@suse.com>
AuthorDate:    Tue, 04 Oct 2022 10:10:09 +02:00
Committer:     Borislav Petkov <bp@suse.de>
CommitterDate: Thu, 20 Oct 2022 15:58:11 +02:00

x86/mtrr: Remove unused cyrix_set_all() function

The Cyrix CPU specific MTRR function cyrix_set_all() will never be
called as the mtrr_ops->set_all() callback will only be called in the
use_intel() case, which would require the use_intel_if member of struct
mtrr_ops to be set, which isn't the case for Cyrix.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20221004081023.32402-3-jgross@suse.com
---
 arch/x86/kernel/cpu/mtrr/cyrix.c | 34 +-------------------------------
 1 file changed, 34 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index ca67091..c77d3b0 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -234,42 +234,8 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
 	post_set();
 }
 
-typedef struct {
-	unsigned long	base;
-	unsigned long	size;
-	mtrr_type	type;
-} arr_state_t;
-
-static arr_state_t arr_state[8] = {
-	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
-	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
-};
-
-static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
-
-static void cyrix_set_all(void)
-{
-	int i;
-
-	prepare_set();
-
-	/* the CCRs are not contiguous */
-	for (i = 0; i < 4; i++)
-		setCx86(CX86_CCR0 + i, ccr_state[i]);
-	for (; i < 7; i++)
-		setCx86(CX86_CCR4 + i, ccr_state[i]);
-
-	for (i = 0; i < 8; i++) {
-		cyrix_set_arr(i, arr_state[i].base,
-			      arr_state[i].size, arr_state[i].type);
-	}
-
-	post_set();
-}
-
 static const struct mtrr_ops cyrix_mtrr_ops = {
 	.vendor            = X86_VENDOR_CYRIX,
-	.set_all	   = cyrix_set_all,
 	.set               = cyrix_set_arr,
 	.get               = cyrix_get_arr,
 	.get_free_region   = cyrix_get_free_region,

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag
  2022-10-04  8:10 ` [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag Juergen Gross
@ 2022-10-21 17:19   ` Borislav Petkov
  2022-10-21 18:05     ` Juergen Gross
  0 siblings, 1 reply; 39+ messages in thread
From: Borislav Petkov @ 2022-10-21 17:19 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:10AM +0200, Juergen Gross wrote:
> In MTRR code use_intel() is only used in one source file, and the
> relevant use_intel_if member of struct mtrr_ops is set only in
> generic_mtrr_ops.
> 
> Replace use_intel() with a single flag in cacheinfo.c, which can be set
> when assigning generic_mtrr_ops to mtrr_if. This allows to drop
> use_intel_if from mtrr_ops, while preparing to support PAT without
> MTRR. As another preparation for the PAT/MTRR decoupling use a bit for
> MTRR control and one for PAT control. For now set both bits together,
> this can be changed later.
> 
> As the new flag will be set only if mtrr_enabled is set, the test for
> mtrr_enabled can be dropped at some places.
> 
> At the same time drop the local mtrr_enabled() function and rename
> the __mtrr_enabled flag to mtrr_enabled.

So, I kinda like your idea about "replace the bool with mtrr_if != NULL"
to test whether MTRRs are enabled.

IOW, how does this look ontop of yours?

At the end of mtrr_bp_init() I need to do some careful dancing but I
think this way it is even clearer. I'm pretty sure it can be simplified
even more but one thing at a time...

Thx.

---
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index dacb537da126..927b463a22bd 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -59,7 +59,6 @@
 #define MTRR_TO_PHYS_WC_OFFSET 1000
 
 u32 num_var_ranges;
-static bool mtrr_enabled;
 
 unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
 static DEFINE_MUTEX(mtrr_mutex);
@@ -71,15 +70,17 @@ static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
 
 const struct mtrr_ops *mtrr_if;
 
-static void set_mtrr(unsigned int reg, unsigned long base,
-		     unsigned long size, mtrr_type type);
-
 void __init set_mtrr_ops(const struct mtrr_ops *ops)
 {
 	if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
 		mtrr_ops[ops->vendor] = ops;
 }
 
+static bool mtrr_enabled(void)
+{
+	return !!mtrr_if;
+}
+
 /*  Returns non-zero if we have the write-combining memory type  */
 static int have_wrcomb(void)
 {
@@ -299,7 +300,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
 	int i, replace, error;
 	mtrr_type ltype;
 
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return -ENXIO;
 
 	error = mtrr_if->validate_add_page(base, size, type);
@@ -447,7 +448,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
 int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
 	     bool increment)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -476,7 +477,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
 	unsigned long lbase, lsize;
 	int error = -EINVAL;
 
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return -ENODEV;
 
 	max = num_var_ranges;
@@ -536,7 +537,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
  */
 int mtrr_del(int reg, unsigned long base, unsigned long size)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return -ENODEV;
 	if (mtrr_check(base, size))
 		return -EINVAL;
@@ -562,7 +563,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled() || !mtrr_enabled)
+	if (pat_enabled() || !mtrr_enabled())
 		return 0;  /* Success!  (We don't need to do anything.) */
 
 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
@@ -750,15 +751,18 @@ void __init mtrr_bp_init(void)
 		}
 	}
 
-	if (mtrr_if) {
-		mtrr_enabled = true;
-		set_num_var_ranges(mtrr_if == &generic_mtrr_ops);
+	if (mtrr_enabled()) {
+		bool use_generic = mtrr_if == &generic_mtrr_ops;
+		bool mtrr_state_enabled = true;
+
+		set_num_var_ranges(use_generic);
 		init_table();
-		if (mtrr_if == &generic_mtrr_ops) {
+
+		if (use_generic) {
 			/* BIOS may override */
-			mtrr_enabled = get_mtrr_state();
+			mtrr_state_enabled = get_mtrr_state();
 
-			if (mtrr_enabled) {
+			if (mtrr_state_enabled) {
 				mtrr_bp_pat_init();
 				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
 			}
@@ -767,10 +771,13 @@ void __init mtrr_bp_init(void)
 				changed_by_mtrr_cleanup = 1;
 				mtrr_if->set_all();
 			}
+
+			if (!mtrr_state_enabled)
+				mtrr_if = NULL;
 		}
 	}
 
-	if (!mtrr_enabled) {
+	if (!mtrr_enabled()) {
 		pr_info("Disabled\n");
 
 		/*
@@ -811,7 +818,7 @@ void mtrr_save_state(void)
 {
 	int first_cpu;
 
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return;
 
 	first_cpu = cpumask_first(cpu_online_mask);
@@ -856,7 +863,7 @@ void mtrr_bp_restore(void)
 
 static int __init mtrr_init_finialize(void)
 {
-	if (!mtrr_enabled)
+	if (!mtrr_enabled())
 		return 0;
 
 	if (memory_caching_control & CACHE_MTRR) {

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag
  2022-10-21 17:19   ` Borislav Petkov
@ 2022-10-21 18:05     ` Juergen Gross
  2022-10-21 18:10       ` Borislav Petkov
  0 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-21 18:05 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 5470 bytes --]

On 21.10.22 19:19, Borislav Petkov wrote:
> On Tue, Oct 04, 2022 at 10:10:10AM +0200, Juergen Gross wrote:
>> In MTRR code use_intel() is only used in one source file, and the
>> relevant use_intel_if member of struct mtrr_ops is set only in
>> generic_mtrr_ops.
>>
>> Replace use_intel() with a single flag in cacheinfo.c, which can be set
>> when assigning generic_mtrr_ops to mtrr_if. This allows to drop
>> use_intel_if from mtrr_ops, while preparing to support PAT without
>> MTRR. As another preparation for the PAT/MTRR decoupling use a bit for
>> MTRR control and one for PAT control. For now set both bits together,
>> this can be changed later.
>>
>> As the new flag will be set only if mtrr_enabled is set, the test for
>> mtrr_enabled can be dropped at some places.
>>
>> At the same time drop the local mtrr_enabled() function and rename
>> the __mtrr_enabled flag to mtrr_enabled.
> 
> So, I kinda like your idea about "replace the bool with mtrr_if != NULL"
> to test whether MTRRs are enabled.
> 
> IOW, how does this look ontop of yours?
> 
> At the end of mtrr_bp_init() I need to do some careful dancing but I
> think this way it is even clearer. I'm pretty sure it can be simplified
> even more but one thing at a time...

Please have a look at patch 10 (I've put it after the rework of mtrr_bp_init()
exactly in order to avoid the dance you had to do).


Juergen

> 
> Thx.
> 
> ---
> diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
> index dacb537da126..927b463a22bd 100644
> --- a/arch/x86/kernel/cpu/mtrr/mtrr.c
> +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
> @@ -59,7 +59,6 @@
>   #define MTRR_TO_PHYS_WC_OFFSET 1000
>   
>   u32 num_var_ranges;
> -static bool mtrr_enabled;
>   
>   unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
>   static DEFINE_MUTEX(mtrr_mutex);
> @@ -71,15 +70,17 @@ static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
>   
>   const struct mtrr_ops *mtrr_if;
>   
> -static void set_mtrr(unsigned int reg, unsigned long base,
> -		     unsigned long size, mtrr_type type);
> -
>   void __init set_mtrr_ops(const struct mtrr_ops *ops)
>   {
>   	if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
>   		mtrr_ops[ops->vendor] = ops;
>   }
>   
> +static bool mtrr_enabled(void)
> +{
> +	return !!mtrr_if;
> +}
> +
>   /*  Returns non-zero if we have the write-combining memory type  */
>   static int have_wrcomb(void)
>   {
> @@ -299,7 +300,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
>   	int i, replace, error;
>   	mtrr_type ltype;
>   
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return -ENXIO;
>   
>   	error = mtrr_if->validate_add_page(base, size, type);
> @@ -447,7 +448,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
>   int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
>   	     bool increment)
>   {
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return -ENODEV;
>   	if (mtrr_check(base, size))
>   		return -EINVAL;
> @@ -476,7 +477,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
>   	unsigned long lbase, lsize;
>   	int error = -EINVAL;
>   
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return -ENODEV;
>   
>   	max = num_var_ranges;
> @@ -536,7 +537,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
>    */
>   int mtrr_del(int reg, unsigned long base, unsigned long size)
>   {
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return -ENODEV;
>   	if (mtrr_check(base, size))
>   		return -EINVAL;
> @@ -562,7 +563,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
>   {
>   	int ret;
>   
> -	if (pat_enabled() || !mtrr_enabled)
> +	if (pat_enabled() || !mtrr_enabled())
>   		return 0;  /* Success!  (We don't need to do anything.) */
>   
>   	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
> @@ -750,15 +751,18 @@ void __init mtrr_bp_init(void)
>   		}
>   	}
>   
> -	if (mtrr_if) {
> -		mtrr_enabled = true;
> -		set_num_var_ranges(mtrr_if == &generic_mtrr_ops);
> +	if (mtrr_enabled()) {
> +		bool use_generic = mtrr_if == &generic_mtrr_ops;
> +		bool mtrr_state_enabled = true;
> +
> +		set_num_var_ranges(use_generic);
>   		init_table();
> -		if (mtrr_if == &generic_mtrr_ops) {
> +
> +		if (use_generic) {
>   			/* BIOS may override */
> -			mtrr_enabled = get_mtrr_state();
> +			mtrr_state_enabled = get_mtrr_state();
>   
> -			if (mtrr_enabled) {
> +			if (mtrr_state_enabled) {
>   				mtrr_bp_pat_init();
>   				memory_caching_control |= CACHE_MTRR | CACHE_PAT;
>   			}
> @@ -767,10 +771,13 @@ void __init mtrr_bp_init(void)
>   				changed_by_mtrr_cleanup = 1;
>   				mtrr_if->set_all();
>   			}
> +
> +			if (!mtrr_state_enabled)
> +				mtrr_if = NULL;
>   		}
>   	}
>   
> -	if (!mtrr_enabled) {
> +	if (!mtrr_enabled()) {
>   		pr_info("Disabled\n");
>   
>   		/*
> @@ -811,7 +818,7 @@ void mtrr_save_state(void)
>   {
>   	int first_cpu;
>   
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return;
>   
>   	first_cpu = cpumask_first(cpu_online_mask);
> @@ -856,7 +863,7 @@ void mtrr_bp_restore(void)
>   
>   static int __init mtrr_init_finialize(void)
>   {
> -	if (!mtrr_enabled)
> +	if (!mtrr_enabled())
>   		return 0;
>   
>   	if (memory_caching_control & CACHE_MTRR) {
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag
  2022-10-21 18:05     ` Juergen Gross
@ 2022-10-21 18:10       ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-21 18:10 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Fri, Oct 21, 2022 at 08:05:39PM +0200, Juergen Gross wrote:
> Please have a look at patch 10 (I've put it after the rework of
> mtrr_bp_init() exactly in order to avoid the dance you had to do).

/me goes and looks.

Yeah,

	if (mtrr_enabled())

seems more readable to me than

	if (mtrr_if)

but ok, changing that is easy.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling
  2022-10-04  8:10 ` [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling Juergen Gross
@ 2022-10-26  9:24   ` Borislav Petkov
  2022-10-26 11:42     ` Juergen Gross
  0 siblings, 1 reply; 39+ messages in thread
From: Borislav Petkov @ 2022-10-26  9:24 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:12AM +0200, Juergen Gross wrote:
> @@ -764,11 +779,8 @@ void cache_disable(void) __acquires(cache_disable_lock)
>  	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
>  	flush_tlb_local();
>  
> -	/* Save MTRR state */
> -	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
> -
> -	/* Disable MTRRs, and set the default type to uncached */
> -	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
> +	if (boot_cpu_has(X86_FEATURE_MTRR))

check_for_deprecated_apis: Warning: arch/x86/kernel/cpu/mtrr/generic.c:782: Do not use boot_cpu_has() - use cpu_feature_enabled() instead.

> +		mtrr_disable();
>  
>  	/* Again, only flush caches if we have to. */
>  	if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
> @@ -781,8 +793,8 @@ void cache_enable(void) __releases(cache_disable_lock)
>  	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
>  	flush_tlb_local();
>  
> -	/* Intel (P6) standard MTRRs */
> -	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
> +	if (boot_cpu_has(X86_FEATURE_MTRR))

Ditto.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 07/16] x86/mtrr: split generic_set_all()
  2022-10-04  8:10 ` [PATCH v4 07/16] x86/mtrr: split generic_set_all() Juergen Gross
@ 2022-10-26 10:37   ` Borislav Petkov
  2022-10-26 11:43     ` Juergen Gross
  0 siblings, 1 reply; 39+ messages in thread
From: Borislav Petkov @ 2022-10-26 10:37 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:14AM +0200, Juergen Gross wrote:
> Split generic_set_all() into multiple parts, while moving the main
> function body into cacheinfo.c.
> 
> Prepare the support of PAT without needing MTRR support by
> moving the main function body of generic_set_all() into cacheinfo.c
> while renaming it to cache_cpu_init(). The MTRR specific parts are
> moved into a dedicated small function called by cache_cpu_init() in
> order to make cache_cpu_init() as MTRR agnostic as possible.
> 
> The setting of smp_changes_mask is merged into the (new) function
> mtrr_generic_set_state() used to call set_mtrr_state(). It was
> probably split in ancient times, as atomic operations while running
> uncached might be quite expensive, but OTOH only systems with a
> broken BIOS should ever require to set any bit in smp_changes_mask,
> so just hurting those devices with a penalty of a few microseconds
> during boot shouldn't be a real issue.

This still needs addressing

"So the commit message should not say what you're doing - that should
be visible from the diff itself. It should talk more about the *why*
you're doing it."

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling
  2022-10-26  9:24   ` Borislav Petkov
@ 2022-10-26 11:42     ` Juergen Gross
  0 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-26 11:42 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 704 bytes --]

On 26.10.22 11:24, Borislav Petkov wrote:
> On Tue, Oct 04, 2022 at 10:10:12AM +0200, Juergen Gross wrote:
>> @@ -764,11 +779,8 @@ void cache_disable(void) __acquires(cache_disable_lock)
>>   	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
>>   	flush_tlb_local();
>>   
>> -	/* Save MTRR state */
>> -	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
>> -
>> -	/* Disable MTRRs, and set the default type to uncached */
>> -	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
>> +	if (boot_cpu_has(X86_FEATURE_MTRR))
> 
> check_for_deprecated_apis: Warning: arch/x86/kernel/cpu/mtrr/generic.c:782: Do not use boot_cpu_has() - use cpu_feature_enabled() instead.

Okay.


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 07/16] x86/mtrr: split generic_set_all()
  2022-10-26 10:37   ` Borislav Petkov
@ 2022-10-26 11:43     ` Juergen Gross
  2022-10-26 12:10       ` Borislav Petkov
  0 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-26 11:43 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 1388 bytes --]

On 26.10.22 12:37, Borislav Petkov wrote:
> On Tue, Oct 04, 2022 at 10:10:14AM +0200, Juergen Gross wrote:
>> Split generic_set_all() into multiple parts, while moving the main
>> function body into cacheinfo.c.
>>
>> Prepare the support of PAT without needing MTRR support by
>> moving the main function body of generic_set_all() into cacheinfo.c
>> while renaming it to cache_cpu_init(). The MTRR specific parts are
>> moved into a dedicated small function called by cache_cpu_init() in
>> order to make cache_cpu_init() as MTRR agnostic as possible.
>>
>> The setting of smp_changes_mask is merged into the (new) function
>> mtrr_generic_set_state() used to call set_mtrr_state(). It was
>> probably split in ancient times, as atomic operations while running
>> uncached might be quite expensive, but OTOH only systems with a
>> broken BIOS should ever require to set any bit in smp_changes_mask,
>> so just hurting those devices with a penalty of a few microseconds
>> during boot shouldn't be a real issue.
> 
> This still needs addressing
> 
> "So the commit message should not say what you're doing - that should
> be visible from the diff itself. It should talk more about the *why*
> you're doing it."
> 

The reason is "Prepare the support of PAT without needing MTRR support".

DYM I should just remove the rest of the commit message?


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 07/16] x86/mtrr: split generic_set_all()
  2022-10-26 11:43     ` Juergen Gross
@ 2022-10-26 12:10       ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-26 12:10 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Wed, Oct 26, 2022 at 01:43:52PM +0200, Juergen Gross wrote:
> The reason is "Prepare the support of PAT without needing MTRR support".
> 
> DYM I should just remove the rest of the commit message?

I mean something like this:

"Disentangle MTRR init from PAT init.

Add a main cache_cpu_init() init routine which initializes MTRR and/or
PAT support depending on what has been detected on the system.

Leave the MTRR-specific initialization in a MTRR-specific init function
where the smp_changes_mask setting happens now with caches disabled.

This global mask update was done with caches enabled before probably
because atomic operations while running uncached might have been quite
expensive.

But since only systems with a broken BIOS should ever require to set any
bit in smp_changes_mask, hurting those devices with a penalty of a few
microseconds during boot shouldn't be a real issue."

A commit message should talk about why the change is done - not, what is
being done. The what is clear from the diff.

It is way more important to state why and the direction this is
taking and what the author's concerns were while doing it. Like the
bit about the smp_changes_mask - that is important.

 The fact that generic_set_all() is gutted out and renamed to
mtrr_generic_set_state() - not so much and also visible.

:-)

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops
  2022-10-04  8:10 ` [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops Juergen Gross
@ 2022-10-27  9:18   ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-27  9:18 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:15AM +0200, Juergen Gross wrote:
> diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
> index dacb537da126..501ca1747d55 100644
> --- a/arch/x86/kernel/cpu/mtrr/mtrr.c
> +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
> @@ -165,15 +165,15 @@ static int mtrr_rendezvous_handler(void *info)
>  	 * saved, and we want to replicate that across all the cpus that come
>  	 * online (either at the end of boot or resume or during a runtime cpu
>  	 * online). If we're doing that, @reg is set to something special and on
> -	 * all the cpu's we do mtrr_if->set_all() (On the logical cpu that
> +	 * all the cpu's we do cache_cpu_init() (On the logical cpu that

s/cpu's/CPUs/
s/cpu/CPU/

while at it.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init()
  2022-10-04  8:10 ` [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init() Juergen Gross
@ 2022-10-27  9:32   ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-27  9:32 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:16AM +0200, Juergen Gross wrote:
> In case of the generic cache interface being used (Intel CPUs or a
> 64-bit system), the initialization sequence of the boot CPU is more
> complicated as necessary:

s/as/than/

> 
> - check if MTRR enabled, if yes, call mtrr_bp_pat_init() which will
>   disable caching, set the PAT MSR, and reenable caching
> 
> - call mtrr_cleanup(), in case that changed anything, call
>   cache_cpu_init() doing the same caching disable/enable dance as
>   above, but this time with setting the (modified) MTRR state (even
>   if MTRR was disabled) AND setting the PAT MSR (again even with
>   disabled MTRR)
> 
> The sequence can be simplified a lot while removing potential
> inconsistencies:
> 
> - check if MTRR enabled, if yes, call mtrr_cleanup() and then
>   cache_cpu_init()
> 
> This ensures to:
> 
> - no longer disable/enable caching more than once
> 
> - avoid to set MTRRs and/or the PAT MSR on the boot processor in case
>   of MTRR cleanups even if MTRRs meant to be disabled
> 
> With that mtrr_bp_pat_init() can be removed.

I like that simplification - I just hope there's not some weird ordering
that is still needed. But we'll see when this hits the wider audiences.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init
  2022-10-04  8:10 ` [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init Juergen Gross
@ 2022-10-27 12:18   ` Borislav Petkov
  2022-10-27 13:08     ` Juergen Gross
  0 siblings, 1 reply; 39+ messages in thread
From: Borislav Petkov @ 2022-10-27 12:18 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:18AM +0200, Juergen Gross wrote:
> diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
> index 49b60a427fc9..330aa412be63 100644
> --- a/arch/x86/kernel/cpu/cacheinfo.c
> +++ b/arch/x86/kernel/cpu/cacheinfo.c
> @@ -1137,3 +1137,10 @@ void cache_cpu_init(void)
>  	cache_enable();
>  	local_irq_restore(flags);
>  }
> +
> +bool cache_aps_delayed_init;

Why isn't that static and only the accessors set it or clear it?

> +void set_cache_aps_delayed_init(void)
> +{
> +	cache_aps_delayed_init = true;
> +}

Otherwise, there's no point for this thing.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init
  2022-10-27 12:18   ` Borislav Petkov
@ 2022-10-27 13:08     ` Juergen Gross
  0 siblings, 0 replies; 39+ messages in thread
From: Juergen Gross @ 2022-10-27 13:08 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 779 bytes --]

On 27.10.22 14:18, Borislav Petkov wrote:
> On Tue, Oct 04, 2022 at 10:10:18AM +0200, Juergen Gross wrote:
>> diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
>> index 49b60a427fc9..330aa412be63 100644
>> --- a/arch/x86/kernel/cpu/cacheinfo.c
>> +++ b/arch/x86/kernel/cpu/cacheinfo.c
>> @@ -1137,3 +1137,10 @@ void cache_cpu_init(void)
>>   	cache_enable();
>>   	local_irq_restore(flags);
>>   }
>> +
>> +bool cache_aps_delayed_init;
> 
> Why isn't that static and only the accessors set it or clear it?
> 
>> +void set_cache_aps_delayed_init(void)
>> +{
>> +	cache_aps_delayed_init = true;
>> +}
> 
> Otherwise, there's no point for this thing.

Hmm, right.

I'll add a get_cache_aps_delayed_init() accessor.


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init()
  2022-10-04  8:10 ` [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init() Juergen Gross
@ 2022-10-29 10:07   ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-29 10:07 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, linux-pm, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, H. Peter Anvin, Rafael J. Wysocki, Pavel Machek

On Tue, Oct 04, 2022 at 10:10:19AM +0200, Juergen Gross wrote:
> +void cache_ap_init(void)
> +{
> +	if (!memory_caching_control || cache_aps_delayed_init)
> +		return;
> +
> +	/*
> +	 * Ideally we should hold mtrr_mutex here to avoid mtrr entries
> +	 * changed, but this routine will be called in cpu boot time,

In all new text you're adding

s/mtrr/MTRR/g
s/cpu/CPU/g

so that it is all consistent.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 13/16] x86: decouple pat and mtrr handling
  2022-10-04  8:10 ` [PATCH v4 13/16] x86: decouple pat and mtrr handling Juergen Gross
@ 2022-10-29 12:15   ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-29 12:15 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin, Andy Lutomirski, Peter Zijlstra

On Tue, Oct 04, 2022 at 10:10:20AM +0200, Juergen Gross wrote:
> diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c
> index 66a209f7eb86..ce1f3246a3e3 100644
> --- a/arch/x86/mm/pat/memtype.c
> +++ b/arch/x86/mm/pat/memtype.c
> @@ -43,6 +43,7 @@
>  #include <linux/rbtree.h>
>  
>  #include <asm/cacheflush.h>
> +#include <asm/cacheinfo.h>
>  #include <asm/processor.h>
>  #include <asm/tlbflush.h>
>  #include <asm/x86_init.h>
> @@ -60,41 +61,34 @@
>  #undef pr_fmt
>  #define pr_fmt(fmt) "" fmt
>  
> -static bool __read_mostly pat_bp_initialized;
>  static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
> -static bool __initdata pat_force_disabled = !IS_ENABLED(CONFIG_X86_PAT);
> -static bool __read_mostly pat_bp_enabled;
> -static bool __read_mostly pat_cm_initialized;
> +static u64 __read_mostly pat_msr_val;

__ro_after_init perhaps. Looks like this thing gets set only during CPU
init anyway.

...

> +void __init pat_bp_init(void)
>  {
> +	struct cpuinfo_x86 *c = &boot_cpu_data;
>  	u64 pat = 0;

Might as well get rid of that local var and use pat_msr_val directly.

>  
> -	if (pat_cm_initialized)
> -		return;
> +#ifndef CONFIG_X86_PAT
> +	pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
> +#endif

	if (!IS_ENABLED(CONFIG...))
		pr_info_once(..)

and one more ifdeffery is gone.

> -	if (boot_cpu_has(X86_FEATURE_PAT)) {
> -		/*
> -		 * CPU supports PAT. Set PAT table to be consistent with
> -		 * PAT MSR. This case supports "nopat" boot option, and
> -		 * virtual machine environments which support PAT without
> -		 * MTRRs. In specific, Xen has unique setup to PAT MSR.
> -		 *
> -		 * If PAT MSR returns 0, it is considered invalid and emulates
> -		 * as No PAT.
> -		 */
> +	if (!boot_cpu_has(X86_FEATURE_PAT))

check_for_deprecated_apis: Warning: arch/x86/mm/pat/memtype.c:265: Do not use boot_cpu_has() - use cpu_feature_enabled() instead.

> +		pat_disable("PAT not supported by the CPU.");
> +	else
>  		rdmsrl(MSR_IA32_CR_PAT, pat);
> -	}

...

> -void pat_init(void)
> -{
> -	u64 pat;
> -	struct cpuinfo_x86 *c = &boot_cpu_data;
> -
> -#ifndef CONFIG_X86_PAT
> -	pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
> -#endif
> +	/* Xen PV doesn't allow to set PAT MSR, but all cache modes are fine. */

... all cache modes are supported" perhaps? "fine" sounds weird here.

> +	if (pat_disabled || cpu_feature_enabled(X86_FEATURE_XENPV)) {
> +		init_cache_modes(pat);
>  

Drop that resulting newline here.

> -	if (pat_disabled)
>  		return;
> +	}
>  
>  	if ((c->x86_vendor == X86_VENDOR_INTEL) &&
>  	    (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-04  8:10 ` [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization Juergen Gross
@ 2022-10-30 12:06   ` Borislav Petkov
  2022-10-30 15:05     ` Juergen Gross
  0 siblings, 1 reply; 39+ messages in thread
From: Borislav Petkov @ 2022-10-30 12:06 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Oct 04, 2022 at 10:10:23AM +0200, Juergen Gross wrote:
> +#ifdef CONFIG_X86_64
> +#define vendor_mtrr_ops(x) NULL
> +#else
> +#define vendor_mtrr_ops(x) &(x)
> +#endif

The idea is good but this is just as hacky.

Just assign the correct one in each branch without this funky ifdeffery.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-30 12:06   ` Borislav Petkov
@ 2022-10-30 15:05     ` Juergen Gross
  2022-10-30 16:39       ` Borislav Petkov
  0 siblings, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-10-30 15:05 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 573 bytes --]

On 30.10.22 13:06, Borislav Petkov wrote:
> On Tue, Oct 04, 2022 at 10:10:23AM +0200, Juergen Gross wrote:
>> +#ifdef CONFIG_X86_64
>> +#define vendor_mtrr_ops(x) NULL
>> +#else
>> +#define vendor_mtrr_ops(x) &(x)
>> +#endif
> 
> The idea is good but this is just as hacky.
> 
> Just assign the correct one in each branch without this funky ifdeffery.

As the specific ops variables are available for X86_32 only, this
would require to add an "#ifdef CONFIG_X86_32" around the code block
doing the assignments. Otherwise the build would fail.


Juergen


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-30 15:05     ` Juergen Gross
@ 2022-10-30 16:39       ` Borislav Petkov
  2022-10-30 17:48         ` Borislav Petkov
  2022-11-01  9:48         ` Juergen Gross
  0 siblings, 2 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-30 16:39 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Sun, Oct 30, 2022 at 04:05:29PM +0100, Juergen Gross wrote:
> As the specific ops variables are available for X86_32 only, this
> would require to add an "#ifdef CONFIG_X86_32" around the code block
> doing the assignments. Otherwise the build would fail.

Well, it looks like my compiler is smart enough and eliminates all that
dead code, see diff below.

I've added the asm markers "#begin" and "#end" and the resulting asm
looks like this:

# arch/x86/kernel/cpu/mtrr/mtrr.c:666:          asm volatile("#begin");
        call    __sanitizer_cov_trace_pc        #
#APP
# 666 "arch/x86/kernel/cpu/mtrr/mtrr.c" 1
        #begin
# 0 "" 2
# arch/x86/kernel/cpu/mtrr/mtrr.c:693:          asm volatile("#end");
# 693 "arch/x86/kernel/cpu/mtrr/mtrr.c" 1
        #end
# 0 "" 2
# arch/x86/kernel/cpu/mtrr/mtrr.c:630:  phys_addr = 32;
#NO_APP

which basically says that all between line 666 and 693 has been
eliminated.

I have the suspicion, though, that clang might not be that smart.

Lemme test it a bit.

---

diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 7ba68356c0ff..d499c83b2ad7 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -663,25 +663,26 @@ void __init mtrr_bp_init(void)
 			phys_addr = 32;
 		}
 	} else {
+		asm volatile("#begin");
 		switch (boot_cpu_data.x86_vendor) {
 		case X86_VENDOR_AMD:
 			if (cpu_feature_enabled(X86_FEATURE_K6_MTRR)) {
 				/* Pre-Athlon (K6) AMD CPU MTRRs */
-				mtrr_if = vendor_mtrr_ops(amd_mtrr_ops);
+				mtrr_if = &amd_mtrr_ops;
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
 			break;
 		case X86_VENDOR_CENTAUR:
 			if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR)) {
-				mtrr_if = vendor_mtrr_ops(centaur_mtrr_ops);
+				mtrr_if = &centaur_mtrr_ops;
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
 			break;
 		case X86_VENDOR_CYRIX:
 			if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR)) {
-				mtrr_if = vendor_mtrr_ops(cyrix_mtrr_ops);
+				mtrr_if = &cyrix_mtrr_ops;
 				size_or_mask = SIZE_OR_MASK_BITS(32);
 				size_and_mask = 0;
 			}
@@ -689,6 +690,7 @@ void __init mtrr_bp_init(void)
 		default:
 			break;
 		}
+		asm volatile("#end");
 	}
 
 	if (mtrr_if) {
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 7a7387356192..02eb5871492d 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -68,11 +68,6 @@ void mtrr_wrmsr(unsigned, unsigned, unsigned);
 extern const struct mtrr_ops amd_mtrr_ops;
 extern const struct mtrr_ops cyrix_mtrr_ops;
 extern const struct mtrr_ops centaur_mtrr_ops;
-#ifdef CONFIG_X86_64
-#define vendor_mtrr_ops(x) NULL
-#else
-#define vendor_mtrr_ops(x) &(x)
-#endif
 
 extern int changed_by_mtrr_cleanup;
 extern int mtrr_cleanup(unsigned address_bits);


-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-30 16:39       ` Borislav Petkov
@ 2022-10-30 17:48         ` Borislav Petkov
  2022-11-01  9:48         ` Juergen Gross
  1 sibling, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-10-30 17:48 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

Another randconfig build failure in the meantime. Pretty easy to
trigger:

ld: arch/x86/kernel/cpu/cacheinfo.o: in function `cache_bp_init':
cacheinfo.c:(.init.text+0x1): undefined reference to `mtrr_bp_init'
make[1]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1
make: *** [Makefile:1236: vmlinux] Error 2

the reason being:

# CONFIG_MTRR is not set

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-10-30 16:39       ` Borislav Petkov
  2022-10-30 17:48         ` Borislav Petkov
@ 2022-11-01  9:48         ` Juergen Gross
  2022-11-01 10:02           ` Borislav Petkov
  1 sibling, 1 reply; 39+ messages in thread
From: Juergen Gross @ 2022-11-01  9:48 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin


[-- Attachment #1.1.1: Type: text/plain, Size: 680 bytes --]

On 30.10.22 17:39, Borislav Petkov wrote:
> On Sun, Oct 30, 2022 at 04:05:29PM +0100, Juergen Gross wrote:
>> As the specific ops variables are available for X86_32 only, this
>> would require to add an "#ifdef CONFIG_X86_32" around the code block
>> doing the assignments. Otherwise the build would fail.
> 
> Well, it looks like my compiler is smart enough and eliminates all that
> dead code, see diff below.
> 
> I have the suspicion, though, that clang might not be that smart.

Hmm, with the cpu_feature_enabled() implementation it should be quite
obvious that this is all dead code.

I'm going with dropping the vendor_mtrr_ops() macro for now.


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization
  2022-11-01  9:48         ` Juergen Gross
@ 2022-11-01 10:02           ` Borislav Petkov
  0 siblings, 0 replies; 39+ messages in thread
From: Borislav Petkov @ 2022-11-01 10:02 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, x86, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	H. Peter Anvin

On Tue, Nov 01, 2022 at 10:48:10AM +0100, Juergen Gross wrote:
> Hmm, with the cpu_feature_enabled() implementation it should be quite
> obvious that this is all dead code.

Yes it is. I ran ~100 randconfigs with both gcc and clang and not a
single one failed the build so I guess you can say in the commit message
that it is ok for this symbol to be not present on 64-bit as it will be
eliminated anyway.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2022-11-01 10:03 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-04  8:10 [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross
2022-10-04  8:10 ` [PATCH v4 01/16] x86/mtrr: add comment for set_mtrr_state() serialization Juergen Gross
2022-10-04  8:10 ` [PATCH v4 02/16] x86/mtrr: remove unused cyrix_set_all() function Juergen Gross
2022-10-20 14:13   ` [tip: x86/cpu] x86/mtrr: Remove " tip-bot2 for Juergen Gross
2022-10-04  8:10 ` [PATCH v4 03/16] x86/mtrr: replace use_intel() with a local flag Juergen Gross
2022-10-21 17:19   ` Borislav Petkov
2022-10-21 18:05     ` Juergen Gross
2022-10-21 18:10       ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 04/16] x86/mtrr: rename prepare_set() and post_set() Juergen Gross
2022-10-04  8:10 ` [PATCH v4 05/16] x86/mtrr: split MTRR specific handling from cache dis/enabling Juergen Gross
2022-10-26  9:24   ` Borislav Petkov
2022-10-26 11:42     ` Juergen Gross
2022-10-04  8:10 ` [PATCH v4 06/16] x86: move some code out of arch/x86/kernel/cpu/mtrr Juergen Gross
2022-10-04  8:10 ` [PATCH v4 07/16] x86/mtrr: split generic_set_all() Juergen Gross
2022-10-26 10:37   ` Borislav Petkov
2022-10-26 11:43     ` Juergen Gross
2022-10-26 12:10       ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 08/16] x86/mtrr: remove set_all callback from struct mtrr_ops Juergen Gross
2022-10-27  9:18   ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 09/16] x86/mtrr: simplify mtrr_bp_init() Juergen Gross
2022-10-27  9:32   ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 10/16] x86/mtrr: get rid of mtrr_enabled bool Juergen Gross
2022-10-04  8:10 ` [PATCH v4 11/16] x86/mtrr: let cache_aps_delayed_init replace mtrr_aps_delayed_init Juergen Gross
2022-10-27 12:18   ` Borislav Petkov
2022-10-27 13:08     ` Juergen Gross
2022-10-04  8:10 ` [PATCH v4 12/16] x86/mtrr: add a stop_machine() handler calling only cache_cpu_init() Juergen Gross
2022-10-29 10:07   ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 13/16] x86: decouple pat and mtrr handling Juergen Gross
2022-10-29 12:15   ` Borislav Petkov
2022-10-04  8:10 ` [PATCH v4 14/16] x86: switch cache_ap_init() to hotplug callback Juergen Gross
2022-10-04  8:10 ` [PATCH v4 15/16] x86: do MTRR/PAT setup on all secondary CPUs in parallel Juergen Gross
2022-10-04  8:10 ` [PATCH v4 16/16] x86/mtrr: simplify mtrr_ops initialization Juergen Gross
2022-10-30 12:06   ` Borislav Petkov
2022-10-30 15:05     ` Juergen Gross
2022-10-30 16:39       ` Borislav Petkov
2022-10-30 17:48         ` Borislav Petkov
2022-11-01  9:48         ` Juergen Gross
2022-11-01 10:02           ` Borislav Petkov
2022-10-19  7:18 ` [PATCH v4 00/16] x86: make pat and mtrr independent from each other Juergen Gross

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).