diff options
Diffstat (limited to 'arch/x86/include/asm/mwait.h')
| -rw-r--r-- | arch/x86/include/asm/mwait.h | 46 | 
1 files changed, 45 insertions, 1 deletions
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index bcdff997668..1da25a5f96f 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -1,10 +1,13 @@  #ifndef _ASM_X86_MWAIT_H  #define _ASM_X86_MWAIT_H +#include <linux/sched.h> +  #define MWAIT_SUBSTATE_MASK		0xf  #define MWAIT_CSTATE_MASK		0xf  #define MWAIT_SUBSTATE_SIZE		4 -#define MWAIT_MAX_NUM_CSTATES		8 +#define MWAIT_HINT2CSTATE(hint)		(((hint) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) +#define MWAIT_HINT2SUBSTATE(hint)	((hint) & MWAIT_CSTATE_MASK)  #define CPUID_MWAIT_LEAF		5  #define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1 @@ -12,4 +15,45 @@  #define MWAIT_ECX_INTERRUPT_BREAK	0x1 +static inline void __monitor(const void *eax, unsigned long ecx, +			     unsigned long edx) +{ +	/* "monitor %eax, %ecx, %edx;" */ +	asm volatile(".byte 0x0f, 0x01, 0xc8;" +		     :: "a" (eax), "c" (ecx), "d"(edx)); +} + +static inline void __mwait(unsigned long eax, unsigned long ecx) +{ +	/* "mwait %eax, %ecx;" */ +	asm volatile(".byte 0x0f, 0x01, 0xc9;" +		     :: "a" (eax), "c" (ecx)); +} + +/* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. + * We execute MONITOR against need_resched and enter optimized wait state + * through MWAIT. Whenever someone changes need_resched, we would be woken + * up from MWAIT (without an IPI). + * + * New with Core Duo processors, MWAIT can take some hints based on CPU + * capability. + */ +static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) +{ +	if (!current_set_polling_and_test()) { +		if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) { +			mb(); +			clflush((void *)¤t_thread_info()->flags); +			mb(); +		} + +		__monitor((void *)¤t_thread_info()->flags, 0, 0); +		if (!need_resched()) +			__mwait(eax, ecx); +	} +	current_clr_polling(); +} +  #endif /* _ASM_X86_MWAIT_H */  | 
