From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753324AbbFKR2t (ORCPT ); Thu, 11 Jun 2015 13:28:49 -0400 Received: from cantor2.suse.de ([195.135.220.15]:39921 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752608AbbFKR2s (ORCPT ); Thu, 11 Jun 2015 13:28:48 -0400 Date: Thu, 11 Jun 2015 19:28:37 +0200 From: Borislav Petkov To: Huang Rui Cc: Andy Lutomirski , Thomas Gleixner , Peter Zijlstra , Ingo Molnar , "Rafael J. Wysocki" , Len Brown , John Stultz , =?utf-8?B?RnLDqWTDqXJpYw==?= Weisbecker , linux-kernel@vger.kernel.org, x86@kernel.org, Fengguang Wu , Aaron Lu , Suravee Suthikulanit , Tony Li Subject: Re: [PATCH v4 2/2] x86, mwaitt: introduce mwaix delay with a configurable timer Message-ID: <20150611172837.GF30391@pd.tnic> References: <1434033662-2291-1-git-send-email-ray.huang@amd.com> <1434033662-2291-3-git-send-email-ray.huang@amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <1434033662-2291-3-git-send-email-ray.huang@amd.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jun 11, 2015 at 10:41:02PM +0800, Huang Rui wrote: > MWAITX can enable a timer and a corresponding timer value specified in SW > P0 clocks. The SW P0 frequency is the same with TSC. The timer provides an > upper bound on how long the instruction waits before exiting. > > The implementation of delay function in kernel can lerverage the timer of > MWAITX. This patch provides a new method (delay_mwaitx) to measure delay > time. > > Suggested-by: Andy Lutomirski > Suggested-by: Borislav Petkov > Suggested-by: Peter Zijlstra > Signed-off-by: Huang Rui > --- > arch/x86/include/asm/mwait.h | 11 +++++++++++ > arch/x86/lib/delay.c | 41 ++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 51 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h > index 1fbc89d..9c8cccd 100644 > --- a/arch/x86/include/asm/mwait.h > +++ b/arch/x86/include/asm/mwait.h > @@ -14,6 +14,8 @@ > #define CPUID5_ECX_INTERRUPT_BREAK 0x2 > > #define MWAIT_ECX_INTERRUPT_BREAK 0x1 > +#define MWAITX_ECX_TIMER_ENABLE BIT(1) > +#define MWAITX_MAX_LOOPS ((u32)-1) > > static inline void __monitor(const void *eax, unsigned long ecx, > unsigned long edx) > @@ -104,4 +106,13 @@ static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) > current_clr_polling(); > } > > +static inline void mwaitx(unsigned long eax, unsigned long loops, > + bool enable) > +{ > + if (enable) > + __mwaitx(eax, loops, MWAITX_ECX_TIMER_ENABLE); > + else > + __mwaitx(eax, 0, 0); > +} > + > #endif /* _ASM_X86_MWAIT_H */ > diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c > index 39d6a3d..9daf94a 100644 > --- a/arch/x86/lib/delay.c > +++ b/arch/x86/lib/delay.c > @@ -20,6 +20,7 @@ > #include > #include > #include > +#include > > #ifdef CONFIG_SMP > # include > @@ -87,6 +88,41 @@ static void delay_tsc(unsigned long __loops) > } > > /* > + * On AMD platforms mwaitx has a configurable 32-bit timer, that counts > + * with TSC frequency. And the input value is the loop of the counter, it > + * will exit with the timer expired. > + */ > +static void delay_mwaitx(unsigned long __loops) > +{ > + u32 end, start, delay, addr, loops = __loops; > + > + rdtsc_barrier(); > + rdtscl(start); > + > + for (;;) { > + delay = min(MWAITX_MAX_LOOPS, loops); > + > + __monitorx(&addr, 0, 0); > + /* > + * AMD, like Intel, supports the EAX hint and EAX=0xf > + * means, do not enter any deep C-state and we use it > + * here in delay() to minimize wakeup latency. > + */ > + mwaitx(0xf, delay, true); > + > + rdtsc_barrier(); > + rdtscl(end); > + > + if (loops <= end - start) > + break; > + > + loops -= end - start; > + > + start = end; > + } > +} > + > +/* > * Since we calibrate only once at boot, this > * function should be set once at boot and not changed > */ > @@ -108,7 +144,10 @@ int read_current_timer(unsigned long *timer_val) > > void __delay(unsigned long loops) > { > - delay_fn(loops); > + if (!static_cpu_has_safe(X86_FEATURE_MWAITT)) Actually, as Thomas suggested, you don't need that static_cpu_has_safe() thing either. You can change use_tsc_delay() to do this: void use_tsc_delay(void) { if (delay_fn == delay_loop) delay_fn = delay_tsc; } and then add: void use_mwaitx_delay(void) { delay_fn = delay_mwaitx; } and in cpu/amd.c:init_amd() do: if (static_cpu_has_safe(X86_FEATURE_MWAITT)) use_mwaitx_delay(); Something like that, at least. tglx might have a better idea though. -- Regards/Gruss, Boris. ECO tip #101: Trim your mails when you reply. --