diff mbox

[v2,2/6] x86/mm/pat: Add pat_disable() interface

Message ID 1458175619-32206-1-git-send-email-toshi.kani@hpe.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kani, Toshi March 17, 2016, 12:46 a.m. UTC
In preparation to fix a regression caused by 'commit 9cd25aac1f44
("x86/mm/pat: Emulate PAT when it is disabled")', PAT needs to
provide an interface that disables the OS to initialize PAT MSR.

PAT MSR initialization must be done on all CPUs with the specific
sequence of operations defined in Intel SDM.  This requires MTRR
to be enabled since pat_init() is called as part of MTRR init
from mtrr_rendezvous_handler().

Change pat_disable() as the interface to disable the OS to initialize
PAT MSR, and set PAT table with pat_keep_handoff_state().  This
interface can be called when PAT initialization may not be performed.

This also assures that pat_disable() called from pat_bsp_init()
to set PAT table properly when CPU does not support PAT.

Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Robert Elliott <elliott@hpe.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/pat.h |    1 +
 arch/x86/mm/pat.c          |   21 ++++++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

Comments

Borislav Petkov March 22, 2016, 4:59 p.m. UTC | #1
On Wed, Mar 16, 2016 at 06:46:55PM -0600, Toshi Kani wrote:
> In preparation to fix a regression caused by 'commit 9cd25aac1f44
> ("x86/mm/pat: Emulate PAT when it is disabled")', PAT needs to
> provide an interface that disables the OS to initialize PAT MSR.

			prevents the OS from initializing the PAT MSR.

> 
> PAT MSR initialization must be done on all CPUs with the specific

s/with/using/

> sequence of operations defined in Intel SDM.  This requires MTRR
				   ^
				  the

s/MTRR/MTRRs/

> to be enabled since pat_init() is called as part of MTRR init
> from mtrr_rendezvous_handler().
> 
> Change pat_disable() as the interface to disable the OS to initialize
> PAT MSR, and set PAT table with pat_keep_handoff_state().  This
> interface can be called when PAT initialization may not be performed.

This paragraph reads funky and I can't really parse what it is trying to
say.

> This also assures that pat_disable() called from pat_bsp_init()
> to set PAT table properly when CPU does not support PAT.
> 
> Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Luis R. Rodriguez <mcgrof@suse.com>
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Robert Elliott <elliott@hpe.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/x86/include/asm/pat.h |    1 +
>  arch/x86/mm/pat.c          |   21 ++++++++++++++++++---
>  2 files changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
> index ca6c228..016142b 100644
> --- a/arch/x86/include/asm/pat.h
> +++ b/arch/x86/include/asm/pat.h
> @@ -5,6 +5,7 @@
>  #include <asm/pgtable_types.h>
>  
>  bool pat_enabled(void);
> +void pat_disable(const char *reason);
>  extern void pat_init(void);
>  void pat_init_cache_modes(u64);
>  
> diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
> index e0a34b0..48d1619 100644
> --- a/arch/x86/mm/pat.c
> +++ b/arch/x86/mm/pat.c
> @@ -40,11 +40,26 @@
>  static bool boot_cpu_done;
>  
>  static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
> +static void pat_keep_handoff_state(void);
>  
> -static inline void pat_disable(const char *reason)
> +/**
> + * pat_disable() - Disable the OS to initialize PAT MSR

			^^^^

Err, what? The function name can't be more clear.

> + *
> + * This function disables the OS to initialize PAT MSR, and calls

		    "prevents the OS from initializing the PAT MSR..."

> + * pat_keep_handoff_state() to set PAT table to the handoff state.

We can see what is calls. You're explaining *what* the code does instead
of *why* again.

> + */
> +void pat_disable(const char *reason)
>  {

Why aren't you checking __pat_enabled here?

	if (!__pat_enabled)
		return;

You can save yourself the other guards in that function, especially that
pr_err() below.

> +	if (boot_cpu_done) {
> +		pr_err("x86/PAT: PAT cannot be disabled after initialization "
> +		       "(attempting: %s)\n", reason);

Please integrate checkpatch.pl into your patch creation workflow as it
sometimes has valid complaints:

WARNING: quoted string split across lines
#79: FILE: arch/x86/mm/pat.c:55:
+               pr_err("x86/PAT: PAT cannot be disabled after initialization "
+                      "(attempting: %s)\n", reason);

More to the point: why do we need that pr_err() call? What is that
supposed to tell the user?

I think it is more for the programmer to catch wrong use of
pat_disable() and then it should be WARN_ONCE() or so...

> +		return;
> +	}
> +
>  	__pat_enabled = 0;
>  	pr_info("x86/PAT: %s\n", reason);
> +
> +	pat_keep_handoff_state();
>  }
>  
>  static int __init nopat(char *str)
> @@ -202,7 +217,7 @@ static void pat_bsp_init(u64 pat)
>  {
>  	u64 tmp_pat;
>  
> -	if (!cpu_has_pat) {
> +	if (!boot_cpu_has(X86_FEATURE_PAT)) {
>  		pat_disable("PAT not supported by CPU.");
>  		return;
>  	}
> @@ -220,7 +235,7 @@ static void pat_bsp_init(u64 pat)
>  
>  static void pat_ap_init(u64 pat)
>  {
> -	if (!cpu_has_pat) {
> +	if (!boot_cpu_has(X86_FEATURE_PAT)) {
>  		/*
>  		 * If this happens we are on a secondary CPU, but switched to
>  		 * PAT on the boot CPU. We have no way to undo PAT.

Those last two hunks are unrelated changes and should be a separate
patch.
Kani, Toshi March 22, 2016, 9:40 p.m. UTC | #2
On Tue, 2016-03-22 at 17:59 +0100, Borislav Petkov wrote:
> On Wed, Mar 16, 2016 at 06:46:55PM -0600, Toshi Kani wrote:
> > In preparation to fix a regression caused by 'commit 9cd25aac1f44
> > ("x86/mm/pat: Emulate PAT when it is disabled")', PAT needs to
> > provide an interface that disables the OS to initialize PAT MSR.
> 
> 			prevents the OS from initializing the PAT MSR.

Right. Will do.

> > 
> > PAT MSR initialization must be done on all CPUs with the specific
> 
> s/with/using/

Ditto.

> > sequence of operations defined in Intel SDM.  This requires MTRR
> 				   ^
> 				  the
> 
> s/MTRR/MTRRs/

Ditto.

> > to be enabled since pat_init() is called as part of MTRR init
> > from mtrr_rendezvous_handler().
> > 
> > Change pat_disable() as the interface to disable the OS to initialize
> > PAT MSR, and set PAT table with pat_keep_handoff_state().  This
> > interface can be called when PAT initialization may not be performed.
> 
> This paragraph reads funky and I can't really parse what it is trying to
> say.

Sorry... Here is a retry:

Make pat_disable() as the interface that prevents the OS from initializing
the PAT MSR.  MTRR will call this interface when it cannot provide the SDM-
defined sequence to initialize PAT.

> > This also assures that pat_disable() called from pat_bsp_init()
> > to set PAT table properly when CPU does not support PAT.
> > 
 :
> >  
> > -static inline void pat_disable(const char *reason)
> > +/**
> > + * pat_disable() - Disable the OS to initialize PAT MSR
> 
> 			^^^^
> 
> Err, what? The function name can't be more clear.

Will change to "Prevent the OS from initializing the PAT MSR".

I wanted to clarify that "disable" does not mean to disable PAT MSR.

> > + *
> > + * This function disables the OS to initialize PAT MSR, and calls
> 
> 		    "prevents the OS from initializing the PAT MSR..."

Will do.

> > + * pat_keep_handoff_state() to set PAT table to the handoff state.
> 
> We can see what is calls. You're explaining *what* the code does instead
> of *why* again.

Right...

> > + */
> > +void pat_disable(const char *reason)
> >  {
> 
> Why aren't you checking __pat_enabled here?
> 
> 	if (!__pat_enabled)
> 		return;

pat_keep_handoff_state() is a no-op after the initial call, but I agree
that having this check is better.  Will do.

> You can save yourself the other guards in that function, especially that
> pr_err() below.

The pr_err() below is for a difference case -- PAT is enabled, but a call
is made to disable it after pat_init() is called.  We cannot allow this
case.

> > +	if (boot_cpu_done) {
> > +		pr_err("x86/PAT: PAT cannot be disabled after
> > initialization "
> > +		       "(attempting: %s)\n", reason);
> 
> Please integrate checkpatch.pl into your patch creation workflow as it
> sometimes has valid complaints:
> 
> WARNING: quoted string split across lines
> #79: FILE: arch/x86/mm/pat.c:55:
> +               pr_err("x86/PAT: PAT cannot be disabled after
> initialization "
> +                      "(attempting: %s)\n", reason);

I've run checkpatch.pl and thought it was OK to have this warning (instead
of a >80 warning) since the error message part was not split.  The
"attempting" part is for debugging and its string is passed from the
caller. 

> More to the point: why do we need that pr_err() call? What is that
> supposed to tell the user?
> 
> I think it is more for the programmer to catch wrong use of
> pat_disable() and then it should be WARN_ONCE() or so...

Yes, this case is for the programmer to catch wrong use.  I will change it
to use WARN_ONCE() and remove the "(attempting: %s)\n" part of the message.

> > +		return;
> > +	}
> > +
> >  	__pat_enabled = 0;
> >  	pr_info("x86/PAT: %s\n", reason);
> > +
> > +	pat_keep_handoff_state();
> >  }
> >  
> >  static int __init nopat(char *str)
> > @@ -202,7 +217,7 @@ static void pat_bsp_init(u64 pat)
> >  {
> >  	u64 tmp_pat;
> >  
> > -	if (!cpu_has_pat) {
> > +	if (!boot_cpu_has(X86_FEATURE_PAT)) {
> >  		pat_disable("PAT not supported by CPU.");
> >  		return;
> >  	}
> > @@ -220,7 +235,7 @@ static void pat_bsp_init(u64 pat)
> >  
> >  static void pat_ap_init(u64 pat)
> >  {
> > -	if (!cpu_has_pat) {
> > +	if (!boot_cpu_has(X86_FEATURE_PAT)) {
> >  		/*
> >  		 * If this happens we are on a secondary CPU, but
> > switched to
> >  		 * PAT on the boot CPU. We have no way to undo PAT.
> 
> Those last two hunks are unrelated changes and should be a separate
> patch.

Will do.

Thanks,
-Toshi
Borislav Petkov March 23, 2016, 8:51 a.m. UTC | #3
On Tue, Mar 22, 2016 at 03:40:45PM -0600, Toshi Kani wrote:
> Will change to "Prevent the OS from initializing the PAT MSR".
> 
> I wanted to clarify that "disable" does not mean to disable PAT MSR.

How do you "disable PAT MSR" ?

I think you're overdocumenting this. pat_disable() is as clear as day
what it does. It doesn't need any commenting...

> I've run checkpatch.pl and thought it was OK to have this warning (instead
> of a >80 warning) since the error message part was not split.  The
> "attempting" part is for debugging and its string is passed from the
> caller. 

We always put the quoted strings on a single line for easier grepping.
Forget the 80-cols rule.
Kani, Toshi March 23, 2016, 3:49 p.m. UTC | #4
On Wed, 2016-03-23 at 09:51 +0100, Borislav Petkov wrote:
> On Tue, Mar 22, 2016 at 03:40:45PM -0600, Toshi Kani wrote:
> > Will change to "Prevent the OS from initializing the PAT MSR".
> > 
> > I wanted to clarify that "disable" does not mean to disable PAT MSR.
> 
> How do you "disable PAT MSR" ?

We can't, but I thought not everyone knows how it works...

> I think you're overdocumenting this. pat_disable() is as clear as day
> what it does. It doesn't need any commenting...

Right, maybe I am just paranoid.  I will remove the comment as you
suggested.

> > I've run checkpatch.pl and thought it was OK to have this warning
> > (instead of a >80 warning) since the error message part was not split.
> >  The "attempting" part is for debugging and its string is passed from
> > the caller. 
> 
> We always put the quoted strings on a single line for easier grepping.
> Forget the 80-cols rule.

OK.

Thanks,
-Toshi
diff mbox

Patch

diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index ca6c228..016142b 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -5,6 +5,7 @@ 
 #include <asm/pgtable_types.h>
 
 bool pat_enabled(void);
+void pat_disable(const char *reason);
 extern void pat_init(void);
 void pat_init_cache_modes(u64);
 
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index e0a34b0..48d1619 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -40,11 +40,26 @@ 
 static bool boot_cpu_done;
 
 static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
+static void pat_keep_handoff_state(void);
 
-static inline void pat_disable(const char *reason)
+/**
+ * pat_disable() - Disable the OS to initialize PAT MSR
+ *
+ * This function disables the OS to initialize PAT MSR, and calls
+ * pat_keep_handoff_state() to set PAT table to the handoff state.
+ */
+void pat_disable(const char *reason)
 {
+	if (boot_cpu_done) {
+		pr_err("x86/PAT: PAT cannot be disabled after initialization "
+		       "(attempting: %s)\n", reason);
+		return;
+	}
+
 	__pat_enabled = 0;
 	pr_info("x86/PAT: %s\n", reason);
+
+	pat_keep_handoff_state();
 }
 
 static int __init nopat(char *str)
@@ -202,7 +217,7 @@  static void pat_bsp_init(u64 pat)
 {
 	u64 tmp_pat;
 
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		pat_disable("PAT not supported by CPU.");
 		return;
 	}
@@ -220,7 +235,7 @@  static void pat_bsp_init(u64 pat)
 
 static void pat_ap_init(u64 pat)
 {
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		/*
 		 * If this happens we are on a secondary CPU, but switched to
 		 * PAT on the boot CPU. We have no way to undo PAT.