linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()
@ 2018-01-17 23:41 Tom Lendacky
  2018-01-17 23:47 ` Tom Lendacky
  2018-01-18 10:54 ` [tip:x86/urgent] " tip-bot for Tom Lendacky
  0 siblings, 2 replies; 4+ messages in thread
From: Tom Lendacky @ 2018-01-17 23:41 UTC (permalink / raw)
  To: x86, linux-kernel
  Cc: Juergen Gross, Tony Luck, Arjan van de Ven, Yu Chen, Baoquan He,
	Linus Torvalds, Ingo Molnar, kexec, Rui Zhang, ebiederm,
	Borislav Petkov, H. Peter Anvin, Thomas Gleixner, Dave Young,
	Boris Ostrovsky, Dan Williams

Some issues have been reported with the for loop in stop_this_cpu() that
issues the 'wbinvd; hlt' sequence.  Reverting this sequence to halt()
has been shown to resolve the issue.

However, the wbinvd is needed when running with SME.  The reason for the
wbinvd is to prevent cache flush races between encrypted and non-encrypted
entries that have the same physical address.  This can occur when
kexec'ing from memory encryption active to inactive or vice-versa.  The
important thing is to not have outside of kernel text memory references
(such as stack usage), so the usage of the native_*() functions is needed
since these expand as inline asm sequences.  So instead of reverting the
change, rework the sequence.

Move the wbinvd instruction outside of the for loop as native_wbinvd()
and make its execution conditional on X86_FEATURE_SME.  In the for loop,
change the asm 'wbinvd; hlt' sequence back to a halt sequence but use
the native_halt() call.

Cc: <stable@vger.kernel.org> # 4.14.x
Fixes: bba4ed011a52 ("x86/mm, kexec: Allow kexec to be used with SME")
Reported-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/process.c |   25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 63711fe..03408b9 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -379,19 +379,24 @@ void stop_this_cpu(void *dummy)
 	disable_local_APIC();
 	mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
 
+	/*
+	 * Use wbinvd on processors that support SME. This provides support
+	 * for performing a successful kexec when going from SME inactive
+	 * to SME active (or vice-versa). The cache must be cleared so that
+	 * if there are entries with the same physical address, both with and
+	 * without the encryption bit, they don't race each other when flushed
+	 * and potentially end up with the wrong entry being committed to
+	 * memory.
+	 */
+	if (boot_cpu_has(X86_FEATURE_SME))
+		native_wbinvd();
 	for (;;) {
 		/*
-		 * Use wbinvd followed by hlt to stop the processor. This
-		 * provides support for kexec on a processor that supports
-		 * SME. With kexec, going from SME inactive to SME active
-		 * requires clearing cache entries so that addresses without
-		 * the encryption bit set don't corrupt the same physical
-		 * address that has the encryption bit set when caches are
-		 * flushed. To achieve this a wbinvd is performed followed by
-		 * a hlt. Even if the processor is not in the kexec/SME
-		 * scenario this only adds a wbinvd to a halting processor.
+		 * Use native_halt() so that memory contents don't change
+		 * (stack usage and variables) after possibly issuing the
+		 * native_wbinvd() above.
 		 */
-		asm volatile("wbinvd; hlt" : : : "memory");
+		native_halt();
 	}
 }
 

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

* Re: [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()
  2018-01-17 23:41 [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu() Tom Lendacky
@ 2018-01-17 23:47 ` Tom Lendacky
  2018-01-18  1:27   ` Dave Young
  2018-01-18 10:54 ` [tip:x86/urgent] " tip-bot for Tom Lendacky
  1 sibling, 1 reply; 4+ messages in thread
From: Tom Lendacky @ 2018-01-17 23:47 UTC (permalink / raw)
  To: x86, linux-kernel
  Cc: Juergen Gross, Tony Luck, Arjan van de Ven, Yu Chen, Baoquan He,
	Linus Torvalds, Ingo Molnar, kexec, Rui Zhang, ebiederm,
	Borislav Petkov, H. Peter Anvin, Thomas Gleixner, Dave Young,
	Boris Ostrovsky, Dan Williams

On 1/17/2018 5:41 PM, Tom Lendacky wrote:
> Some issues have been reported with the for loop in stop_this_cpu() that
> issues the 'wbinvd; hlt' sequence.  Reverting this sequence to halt()
> has been shown to resolve the issue.
> 
> However, the wbinvd is needed when running with SME.  The reason for the
> wbinvd is to prevent cache flush races between encrypted and non-encrypted
> entries that have the same physical address.  This can occur when
> kexec'ing from memory encryption active to inactive or vice-versa.  The
> important thing is to not have outside of kernel text memory references
> (such as stack usage), so the usage of the native_*() functions is needed
> since these expand as inline asm sequences.  So instead of reverting the
> change, rework the sequence.
> 
> Move the wbinvd instruction outside of the for loop as native_wbinvd()
> and make its execution conditional on X86_FEATURE_SME.  In the for loop,
> change the asm 'wbinvd; hlt' sequence back to a halt sequence but use
> the native_halt() call.
> 
> Cc: <stable@vger.kernel.org> # 4.14.x
> Fixes: bba4ed011a52 ("x86/mm, kexec: Allow kexec to be used with SME")
> Reported-by: Dave Young <dyoung@redhat.com>

Dave,

Can you test this and see if it resolves your issue?

Thanks,
Tom

> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/kernel/process.c |   25 +++++++++++++++----------
>  1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
> index 63711fe..03408b9 100644
> --- a/arch/x86/kernel/process.c
> +++ b/arch/x86/kernel/process.c
> @@ -379,19 +379,24 @@ void stop_this_cpu(void *dummy)
>  	disable_local_APIC();
>  	mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
>  
> +	/*
> +	 * Use wbinvd on processors that support SME. This provides support
> +	 * for performing a successful kexec when going from SME inactive
> +	 * to SME active (or vice-versa). The cache must be cleared so that
> +	 * if there are entries with the same physical address, both with and
> +	 * without the encryption bit, they don't race each other when flushed
> +	 * and potentially end up with the wrong entry being committed to
> +	 * memory.
> +	 */
> +	if (boot_cpu_has(X86_FEATURE_SME))
> +		native_wbinvd();
>  	for (;;) {
>  		/*
> -		 * Use wbinvd followed by hlt to stop the processor. This
> -		 * provides support for kexec on a processor that supports
> -		 * SME. With kexec, going from SME inactive to SME active
> -		 * requires clearing cache entries so that addresses without
> -		 * the encryption bit set don't corrupt the same physical
> -		 * address that has the encryption bit set when caches are
> -		 * flushed. To achieve this a wbinvd is performed followed by
> -		 * a hlt. Even if the processor is not in the kexec/SME
> -		 * scenario this only adds a wbinvd to a halting processor.
> +		 * Use native_halt() so that memory contents don't change
> +		 * (stack usage and variables) after possibly issuing the
> +		 * native_wbinvd() above.
>  		 */
> -		asm volatile("wbinvd; hlt" : : : "memory");
> +		native_halt();
>  	}
>  }
>  
> 

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

* Re: [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()
  2018-01-17 23:47 ` Tom Lendacky
@ 2018-01-18  1:27   ` Dave Young
  0 siblings, 0 replies; 4+ messages in thread
From: Dave Young @ 2018-01-18  1:27 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: x86, linux-kernel, Juergen Gross, Tony Luck, Arjan van de Ven,
	Yu Chen, Baoquan He, Linus Torvalds, Ingo Molnar, kexec,
	Rui Zhang, ebiederm, Borislav Petkov, H. Peter Anvin,
	Thomas Gleixner, Boris Ostrovsky, Dan Williams

On 01/17/18 at 05:47pm, Tom Lendacky wrote:
> On 1/17/2018 5:41 PM, Tom Lendacky wrote:
> > Some issues have been reported with the for loop in stop_this_cpu() that
> > issues the 'wbinvd; hlt' sequence.  Reverting this sequence to halt()
> > has been shown to resolve the issue.
> > 
> > However, the wbinvd is needed when running with SME.  The reason for the
> > wbinvd is to prevent cache flush races between encrypted and non-encrypted
> > entries that have the same physical address.  This can occur when
> > kexec'ing from memory encryption active to inactive or vice-versa.  The
> > important thing is to not have outside of kernel text memory references
> > (such as stack usage), so the usage of the native_*() functions is needed
> > since these expand as inline asm sequences.  So instead of reverting the
> > change, rework the sequence.
> > 
> > Move the wbinvd instruction outside of the for loop as native_wbinvd()
> > and make its execution conditional on X86_FEATURE_SME.  In the for loop,
> > change the asm 'wbinvd; hlt' sequence back to a halt sequence but use
> > the native_halt() call.
> > 
> > Cc: <stable@vger.kernel.org> # 4.14.x
> > Fixes: bba4ed011a52 ("x86/mm, kexec: Allow kexec to be used with SME")
> > Reported-by: Dave Young <dyoung@redhat.com>
> 
> Dave,
> 
> Can you test this and see if it resolves your issue?

It works for me, thank you for the patch!

Tested-by: Dave Young <dyoung@redhat.com>

> 
> Thanks,
> Tom
> 
> > Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> > ---
> >  arch/x86/kernel/process.c |   25 +++++++++++++++----------
> >  1 file changed, 15 insertions(+), 10 deletions(-)
> > 
> > diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
> > index 63711fe..03408b9 100644
> > --- a/arch/x86/kernel/process.c
> > +++ b/arch/x86/kernel/process.c
> > @@ -379,19 +379,24 @@ void stop_this_cpu(void *dummy)
> >  	disable_local_APIC();
> >  	mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
> >  
> > +	/*
> > +	 * Use wbinvd on processors that support SME. This provides support
> > +	 * for performing a successful kexec when going from SME inactive
> > +	 * to SME active (or vice-versa). The cache must be cleared so that
> > +	 * if there are entries with the same physical address, both with and
> > +	 * without the encryption bit, they don't race each other when flushed
> > +	 * and potentially end up with the wrong entry being committed to
> > +	 * memory.
> > +	 */
> > +	if (boot_cpu_has(X86_FEATURE_SME))
> > +		native_wbinvd();
> >  	for (;;) {
> >  		/*
> > -		 * Use wbinvd followed by hlt to stop the processor. This
> > -		 * provides support for kexec on a processor that supports
> > -		 * SME. With kexec, going from SME inactive to SME active
> > -		 * requires clearing cache entries so that addresses without
> > -		 * the encryption bit set don't corrupt the same physical
> > -		 * address that has the encryption bit set when caches are
> > -		 * flushed. To achieve this a wbinvd is performed followed by
> > -		 * a hlt. Even if the processor is not in the kexec/SME
> > -		 * scenario this only adds a wbinvd to a halting processor.
> > +		 * Use native_halt() so that memory contents don't change
> > +		 * (stack usage and variables) after possibly issuing the
> > +		 * native_wbinvd() above.
> >  		 */
> > -		asm volatile("wbinvd; hlt" : : : "memory");
> > +		native_halt();
> >  	}
> >  }
> >  
> > 

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

* [tip:x86/urgent] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()
  2018-01-17 23:41 [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu() Tom Lendacky
  2018-01-17 23:47 ` Tom Lendacky
@ 2018-01-18 10:54 ` tip-bot for Tom Lendacky
  1 sibling, 0 replies; 4+ messages in thread
From: tip-bot for Tom Lendacky @ 2018-01-18 10:54 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: torvalds, tony.luck, jgross, dan.j.williams, boris.ostrovsky,
	tglx, linux-kernel, hpa, arjan, rui.zhang, dyoung, bhe, bp,
	yu.c.chen, mingo, thomas.lendacky

Commit-ID:  f23d74f6c66c3697e032550eeef3f640391a3a7d
Gitweb:     https://git.kernel.org/tip/f23d74f6c66c3697e032550eeef3f640391a3a7d
Author:     Tom Lendacky <thomas.lendacky@amd.com>
AuthorDate: Wed, 17 Jan 2018 17:41:41 -0600
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 18 Jan 2018 11:48:59 +0100

x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()

Some issues have been reported with the for loop in stop_this_cpu() that
issues the 'wbinvd; hlt' sequence.  Reverting this sequence to halt()
has been shown to resolve the issue.

However, the wbinvd is needed when running with SME.  The reason for the
wbinvd is to prevent cache flush races between encrypted and non-encrypted
entries that have the same physical address.  This can occur when
kexec'ing from memory encryption active to inactive or vice-versa.  The
important thing is to not have outside of kernel text memory references
(such as stack usage), so the usage of the native_*() functions is needed
since these expand as inline asm sequences.  So instead of reverting the
change, rework the sequence.

Move the wbinvd instruction outside of the for loop as native_wbinvd()
and make its execution conditional on X86_FEATURE_SME.  In the for loop,
change the asm 'wbinvd; hlt' sequence back to a halt sequence but use
the native_halt() call.

Fixes: bba4ed011a52 ("x86/mm, kexec: Allow kexec to be used with SME")
Reported-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Dave Young <dyoung@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Yu Chen <yu.c.chen@intel.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: kexec@lists.infradead.org
Cc: ebiederm@redhat.com
Cc: Borislav Petkov <bp@alien8.de>
Cc: Rui Zhang <rui.zhang@intel.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20180117234141.21184.44067.stgit@tlendack-t1.amdoffice.net

---
 arch/x86/kernel/process.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 832a6ac..cb368c2 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -380,19 +380,24 @@ void stop_this_cpu(void *dummy)
 	disable_local_APIC();
 	mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
 
+	/*
+	 * Use wbinvd on processors that support SME. This provides support
+	 * for performing a successful kexec when going from SME inactive
+	 * to SME active (or vice-versa). The cache must be cleared so that
+	 * if there are entries with the same physical address, both with and
+	 * without the encryption bit, they don't race each other when flushed
+	 * and potentially end up with the wrong entry being committed to
+	 * memory.
+	 */
+	if (boot_cpu_has(X86_FEATURE_SME))
+		native_wbinvd();
 	for (;;) {
 		/*
-		 * Use wbinvd followed by hlt to stop the processor. This
-		 * provides support for kexec on a processor that supports
-		 * SME. With kexec, going from SME inactive to SME active
-		 * requires clearing cache entries so that addresses without
-		 * the encryption bit set don't corrupt the same physical
-		 * address that has the encryption bit set when caches are
-		 * flushed. To achieve this a wbinvd is performed followed by
-		 * a hlt. Even if the processor is not in the kexec/SME
-		 * scenario this only adds a wbinvd to a halting processor.
+		 * Use native_halt() so that memory contents don't change
+		 * (stack usage and variables) after possibly issuing the
+		 * native_wbinvd() above.
 		 */
-		asm volatile("wbinvd; hlt" : : : "memory");
+		native_halt();
 	}
 }
 

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

end of thread, other threads:[~2018-01-18 10:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-17 23:41 [PATCH] x86/mm: Rework wbinvd, hlt operation in stop_this_cpu() Tom Lendacky
2018-01-17 23:47 ` Tom Lendacky
2018-01-18  1:27   ` Dave Young
2018-01-18 10:54 ` [tip:x86/urgent] " tip-bot for Tom Lendacky

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).