Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1437854 > unrolled thread
| Started by | Jacob Pan <jacob.jun.pan@linux.intel.com> |
|---|---|
| First post | 2016-07-06 19:10 +0200 |
| Last post | 2016-07-08 21:20 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH] x86: add workaround monitor bug Jacob Pan <jacob.jun.pan@linux.intel.com> - 2016-07-06 19:10 +0200
Re: [PATCH] x86: add workaround monitor bug Ingo Molnar <mingo@kernel.org> - 2016-07-08 11:00 +0200
Re: [PATCH] x86: add workaround monitor bug Peter Zijlstra <peterz@infradead.org> - 2016-07-08 13:50 +0200
Re: [PATCH] x86: add workaround monitor bug Ingo Molnar <mingo@kernel.org> - 2016-07-08 14:10 +0200
Re: [PATCH] x86: add workaround monitor bug Jacob Pan <jacob.jun.pan@linux.intel.com> - 2016-07-08 21:20 +0200
| From | Jacob Pan <jacob.jun.pan@linux.intel.com> |
|---|---|
| Date | 2016-07-06 19:10 +0200 |
| Subject | [PATCH] x86: add workaround monitor bug |
| Message-ID | <rRYuK-3wy-33@gated-at.bofh.it> |
From: Peter Zijlstra <peterz@infradead.org>
Monitored cached line may not wake up from mwait on certain
Goldmont based CPUs. This patch will avoid calling
current_set_polling_and_test() and thereby not set the TIF_ flag.
The result is that we'll always send IPIs for wakeups.
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/mwait.h | 2 +-
arch/x86/kernel/cpu/intel.c | 5 +++++
arch/x86/kernel/process.c | 2 +-
4 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 78dbd28..197a3f4 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -304,6 +304,7 @@
#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
#define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */
#define X86_BUG_SWAPGS_FENCE X86_BUG(10) /* SWAPGS without input dep on GS */
+#define X86_BUG_MONITOR X86_BUG(11) /* IPI required to wake up remote cpu */
#ifdef CONFIG_X86_32
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
index 0deeb2d..f37f2d8 100644
--- a/arch/x86/include/asm/mwait.h
+++ b/arch/x86/include/asm/mwait.h
@@ -97,7 +97,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
*/
static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
{
- if (!current_set_polling_and_test()) {
+ if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
mb();
clflush((void *)¤t_thread_info()->flags);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 6e2ffbe..77c6b3e 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -13,6 +13,7 @@
#include <asm/msr.h>
#include <asm/bugs.h>
#include <asm/cpu.h>
+#include <asm/intel-family.h>
#ifdef CONFIG_X86_64
#include <linux/topology.h>
@@ -509,6 +510,10 @@ static void init_intel(struct cpuinfo_x86 *c)
(c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
+ if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_MWAIT) &&
+ ((c->x86_model == INTEL_FAM6_ATOM_GOLDMONT)))
+ set_cpu_bug(c, X86_BUG_MONITOR);
+
#ifdef CONFIG_X86_64
if (c->x86 == 15)
c->x86_cache_alignment = c->x86_clflush_size * 2;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 96becbb..59f68f1 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -404,7 +404,7 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
if (c->x86_vendor != X86_VENDOR_INTEL)
return 0;
- if (!cpu_has(c, X86_FEATURE_MWAIT))
+ if (!cpu_has(c, X86_FEATURE_MWAIT) || static_cpu_has_bug(X86_BUG_MONITOR))
return 0;
return 1;
--
1.9.1
[toc] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-07-08 11:00 +0200 |
| Message-ID | <rSzND-2nt-3@gated-at.bofh.it> |
| In reply to | #1437854 |
* Jacob Pan <jacob.jun.pan@linux.intel.com> wrote:
> From: Peter Zijlstra <peterz@infradead.org>
>
> Monitored cached line may not wake up from mwait on certain
> Goldmont based CPUs. This patch will avoid calling
> current_set_polling_and_test() and thereby not set the TIF_ flag.
> The result is that we'll always send IPIs for wakeups.
>
> Signed-off-by: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> ---
> arch/x86/include/asm/cpufeatures.h | 1 +
> arch/x86/include/asm/mwait.h | 2 +-
> arch/x86/kernel/cpu/intel.c | 5 +++++
> arch/x86/kernel/process.c | 2 +-
> 4 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index 78dbd28..197a3f4 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/arch/x86/include/asm/cpufeatures.h
> @@ -304,6 +304,7 @@
> #define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
> #define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */
> #define X86_BUG_SWAPGS_FENCE X86_BUG(10) /* SWAPGS without input dep on GS */
> +#define X86_BUG_MONITOR X86_BUG(11) /* IPI required to wake up remote cpu */
>
>
> #ifdef CONFIG_X86_32
> diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
> index 0deeb2d..f37f2d8 100644
> --- a/arch/x86/include/asm/mwait.h
> +++ b/arch/x86/include/asm/mwait.h
> @@ -97,7 +97,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
> */
> static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
> {
> - if (!current_set_polling_and_test()) {
> + if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
Hm, this might be suboptimal: if MONITOR/MWAIT is implemented by setting the
exclusive flag for the monitored memory address and then snooping for cache
invalidation requests for that cache line, then not modifying the ->flags value
with TIF_POLLING_NRFLAG makes MWAIT not wake up - only the IPI would wake it up.
I think a better approach would be to still optimistically modify the ->flags
value _AND_ to also send an IPI, to make sure the wakeup is not lost. This means
that the woken CPU will wake up much faster (no IPI latency).
(The system will still bear the ovehread of sending and receiving the IPI, but
that cost is unavoidable if there's no other workaround for this erratum.)
Thanks,
Ingo
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-07-08 13:50 +0200 |
| Message-ID | <rSCs9-4e3-27@gated-at.bofh.it> |
| In reply to | #1439180 |
On Fri, Jul 08, 2016 at 10:55:15AM +0200, Ingo Molnar wrote:
> > static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
> > {
> > - if (!current_set_polling_and_test()) {
> > + if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
>
> Hm, this might be suboptimal: if MONITOR/MWAIT is implemented by setting the
> exclusive flag for the monitored memory address and then snooping for cache
> invalidation requests for that cache line, then not modifying the ->flags value
> with TIF_POLLING_NRFLAG makes MWAIT not wake up - only the IPI would wake it up.
Confused.. POLLING_NRFLAGS is not used to wake up ever. It is only used
to determine if we want to send IPIs or not.
And since we _must_ send an IPI in this case, because the monitor is
busted, we cannot set this.
> I think a better approach would be to still optimistically modify the ->flags
> value _AND_ to also send an IPI, to make sure the wakeup is not lost. This means
> that the woken CPU will wake up much faster (no IPI latency).
This is exactly what is done. See resched_curr()'s use of
set_nr_and_not_polling(). That does:
if (!(fetch_or(&flags, NEED_RESCHED) & POLLING_NRFLAG))
smp_send_reschedule(cpu);
So we unconditionally set NEED_RESCHED, if, when we set that, POLLING
was set, we skip the IPI.
So again, since monitor is busted, simply setting NEED_RESCHED will not
wake us, we must send the IPI, this is achieved by not setting
POLLING_NRFLAG.
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-07-08 14:10 +0200 |
| Message-ID | <rSCLx-4Br-107@gated-at.bofh.it> |
| In reply to | #1439343 |
* Peter Zijlstra <peterz@infradead.org> wrote:
> On Fri, Jul 08, 2016 at 10:55:15AM +0200, Ingo Molnar wrote:
>
> > > static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
> > > {
> > > - if (!current_set_polling_and_test()) {
> > > + if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
> >
> > Hm, this might be suboptimal: if MONITOR/MWAIT is implemented by setting the
> > exclusive flag for the monitored memory address and then snooping for cache
> > invalidation requests for that cache line, then not modifying the ->flags value
> > with TIF_POLLING_NRFLAG makes MWAIT not wake up - only the IPI would wake it up.
>
> Confused.. POLLING_NRFLAGS is not used to wake up ever. It is only used
> to determine if we want to send IPIs or not.
I called the IPI the 'wakeup' - it's the 'CPU wakeup' :-)
> And since we _must_ send an IPI in this case, because the monitor is
> busted, we cannot set this.
>
> > I think a better approach would be to still optimistically modify the ->flags
> > value _AND_ to also send an IPI, to make sure the wakeup is not lost. This means
> > that the woken CPU will wake up much faster (no IPI latency).
>
> This is exactly what is done. See resched_curr()'s use of
> set_nr_and_not_polling(). That does:
>
> if (!(fetch_or(&flags, NEED_RESCHED) & POLLING_NRFLAG))
> smp_send_reschedule(cpu);
>
> So we unconditionally set NEED_RESCHED, if, when we set that, POLLING
> was set, we skip the IPI.
Ah, indeed, we set NEED_RESCHED in the same memory address that __monitor() is
watching so all is good.
> So again, since monitor is busted, simply setting NEED_RESCHED will not
> wake us, we must send the IPI, this is achieved by not setting
> POLLING_NRFLAG.
Yeah, so I got the impression that it might be broken in only certain
circumstances, or is it completely busted?
Thanks,
Ingo
[toc] | [prev] | [next] | [standalone]
| From | Jacob Pan <jacob.jun.pan@linux.intel.com> |
|---|---|
| Date | 2016-07-08 21:20 +0200 |
| Message-ID | <rSJtD-w3-7@gated-at.bofh.it> |
| In reply to | #1439384 |
On Fri, 8 Jul 2016 14:07:12 +0200
Ingo Molnar <mingo@kernel.org> wrote:
>
> * Peter Zijlstra <peterz@infradead.org> wrote:
>
> > On Fri, Jul 08, 2016 at 10:55:15AM +0200, Ingo Molnar wrote:
> >
> > > > static inline void mwait_idle_with_hints(unsigned long eax,
> > > > unsigned long ecx) {
> > > > - if (!current_set_polling_and_test()) {
> > > > + if (static_cpu_has_bug(X86_BUG_MONITOR)
> > > > || !current_set_polling_and_test()) {
> > >
> > > Hm, this might be suboptimal: if MONITOR/MWAIT is implemented by
> > > setting the exclusive flag for the monitored memory address and
> > > then snooping for cache invalidation requests for that cache
> > > line, then not modifying the ->flags value with
> > > TIF_POLLING_NRFLAG makes MWAIT not wake up - only the IPI would
> > > wake it up.
> >
> > Confused.. POLLING_NRFLAGS is not used to wake up ever. It is only
> > used to determine if we want to send IPIs or not.
>
> I called the IPI the 'wakeup' - it's the 'CPU wakeup' :-)
>
> > And since we _must_ send an IPI in this case, because the monitor is
> > busted, we cannot set this.
> >
> > > I think a better approach would be to still optimistically modify
> > > the ->flags value _AND_ to also send an IPI, to make sure the
> > > wakeup is not lost. This means that the woken CPU will wake up
> > > much faster (no IPI latency).
> >
> > This is exactly what is done. See resched_curr()'s use of
> > set_nr_and_not_polling(). That does:
> >
> > if (!(fetch_or(&flags, NEED_RESCHED) & POLLING_NRFLAG))
> > smp_send_reschedule(cpu);
> >
> > So we unconditionally set NEED_RESCHED, if, when we set that,
> > POLLING was set, we skip the IPI.
>
> Ah, indeed, we set NEED_RESCHED in the same memory address that
> __monitor() is watching so all is good.
>
> > So again, since monitor is busted, simply setting NEED_RESCHED will
> > not wake us, we must send the IPI, this is achieved by not setting
> > POLLING_NRFLAG.
>
> Yeah, so I got the impression that it might be broken in only certain
> circumstances, or is it completely busted?
>
That is right, monitor is only partially broken not completely busted. I
don't have the statistics but it is not rare to miss wakeup. The
typical symptom is random slowness and fails to boot, without this
patch.
So doing both can speed up wake up in some cases.
Jacob
> Thanks,
>
> Ingo
[Jacob Pan]
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web