Linux Audio

Check our new training course

Loading...
v4.6
 
  1#ifndef _ASM_X86_MWAIT_H
  2#define _ASM_X86_MWAIT_H
  3
  4#include <linux/sched.h>
 
  5
  6#include <asm/cpufeature.h>
 
  7
  8#define MWAIT_SUBSTATE_MASK		0xf
  9#define MWAIT_CSTATE_MASK		0xf
 10#define MWAIT_SUBSTATE_SIZE		4
 11#define MWAIT_HINT2CSTATE(hint)		(((hint) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK)
 12#define MWAIT_HINT2SUBSTATE(hint)	((hint) & MWAIT_CSTATE_MASK)
 
 13
 14#define CPUID_MWAIT_LEAF		5
 15#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
 16#define CPUID5_ECX_INTERRUPT_BREAK	0x2
 17
 18#define MWAIT_ECX_INTERRUPT_BREAK	0x1
 19#define MWAITX_ECX_TIMER_ENABLE		BIT(1)
 20#define MWAITX_MAX_LOOPS		((u32)-1)
 21#define MWAITX_DISABLE_CSTATES		0xf
 
 
 22
 23static inline void __monitor(const void *eax, unsigned long ecx,
 24			     unsigned long edx)
 25{
 26	/* "monitor %eax, %ecx, %edx;" */
 27	asm volatile(".byte 0x0f, 0x01, 0xc8;"
 28		     :: "a" (eax), "c" (ecx), "d"(edx));
 29}
 30
 31static inline void __monitorx(const void *eax, unsigned long ecx,
 32			      unsigned long edx)
 33{
 34	/* "monitorx %eax, %ecx, %edx;" */
 35	asm volatile(".byte 0x0f, 0x01, 0xfa;"
 36		     :: "a" (eax), "c" (ecx), "d"(edx));
 37}
 38
 39static inline void __mwait(unsigned long eax, unsigned long ecx)
 40{
 
 
 41	/* "mwait %eax, %ecx;" */
 42	asm volatile(".byte 0x0f, 0x01, 0xc9;"
 43		     :: "a" (eax), "c" (ecx));
 44}
 45
 46/*
 47 * MWAITX allows for a timer expiration to get the core out a wait state in
 48 * addition to the default MWAIT exit condition of a store appearing at a
 49 * monitored virtual address.
 50 *
 51 * Registers:
 52 *
 53 * MWAITX ECX[1]: enable timer if set
 54 * MWAITX EBX[31:0]: max wait time expressed in SW P0 clocks. The software P0
 55 * frequency is the same as the TSC frequency.
 56 *
 57 * Below is a comparison between MWAIT and MWAITX on AMD processors:
 58 *
 59 *                 MWAIT                           MWAITX
 60 * opcode          0f 01 c9           |            0f 01 fb
 61 * ECX[0]                  value of RFLAGS.IF seen by instruction
 62 * ECX[1]          unused/#GP if set  |            enable timer if set
 63 * ECX[31:2]                     unused/#GP if set
 64 * EAX                           unused (reserve for hint)
 65 * EBX[31:0]       unused             |            max wait time (P0 clocks)
 66 *
 67 *                 MONITOR                         MONITORX
 68 * opcode          0f 01 c8           |            0f 01 fa
 69 * EAX                     (logical) address to monitor
 70 * ECX                     #GP if not zero
 71 */
 72static inline void __mwaitx(unsigned long eax, unsigned long ebx,
 73			    unsigned long ecx)
 74{
 
 
 75	/* "mwaitx %eax, %ebx, %ecx;" */
 76	asm volatile(".byte 0x0f, 0x01, 0xfb;"
 77		     :: "a" (eax), "b" (ebx), "c" (ecx));
 78}
 79
 80static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
 
 
 
 
 
 
 
 
 
 81{
 82	trace_hardirqs_on();
 83	/* "mwait %eax, %ecx;" */
 84	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
 85		     :: "a" (eax), "c" (ecx));
 86}
 87
 88/*
 89 * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
 90 * which can obviate IPI to trigger checking of need_resched.
 91 * We execute MONITOR against need_resched and enter optimized wait state
 92 * through MWAIT. Whenever someone changes need_resched, we would be woken
 93 * up from MWAIT (without an IPI).
 94 *
 95 * New with Core Duo processors, MWAIT can take some hints based on CPU
 96 * capability.
 97 */
 98static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
 99{
100	if (!current_set_polling_and_test()) {
101		if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
102			mb();
103			clflush((void *)&current_thread_info()->flags);
104			mb();
105		}
106
107		__monitor((void *)&current_thread_info()->flags, 0, 0);
108		if (!need_resched())
109			__mwait(eax, ecx);
 
 
 
 
 
 
 
110	}
111	current_clr_polling();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112}
113
114#endif /* _ASM_X86_MWAIT_H */
v6.8
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _ASM_X86_MWAIT_H
  3#define _ASM_X86_MWAIT_H
  4
  5#include <linux/sched.h>
  6#include <linux/sched/idle.h>
  7
  8#include <asm/cpufeature.h>
  9#include <asm/nospec-branch.h>
 10
 11#define MWAIT_SUBSTATE_MASK		0xf
 12#define MWAIT_CSTATE_MASK		0xf
 13#define MWAIT_SUBSTATE_SIZE		4
 14#define MWAIT_HINT2CSTATE(hint)		(((hint) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK)
 15#define MWAIT_HINT2SUBSTATE(hint)	((hint) & MWAIT_CSTATE_MASK)
 16#define MWAIT_C1_SUBSTATE_MASK  0xf0
 17
 18#define CPUID_MWAIT_LEAF		5
 19#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
 20#define CPUID5_ECX_INTERRUPT_BREAK	0x2
 21
 22#define MWAIT_ECX_INTERRUPT_BREAK	0x1
 23#define MWAITX_ECX_TIMER_ENABLE		BIT(1)
 24#define MWAITX_MAX_WAIT_CYCLES		UINT_MAX
 25#define MWAITX_DISABLE_CSTATES		0xf0
 26#define TPAUSE_C01_STATE		1
 27#define TPAUSE_C02_STATE		0
 28
 29static __always_inline void __monitor(const void *eax, unsigned long ecx,
 30			     unsigned long edx)
 31{
 32	/* "monitor %eax, %ecx, %edx;" */
 33	asm volatile(".byte 0x0f, 0x01, 0xc8;"
 34		     :: "a" (eax), "c" (ecx), "d"(edx));
 35}
 36
 37static __always_inline void __monitorx(const void *eax, unsigned long ecx,
 38			      unsigned long edx)
 39{
 40	/* "monitorx %eax, %ecx, %edx;" */
 41	asm volatile(".byte 0x0f, 0x01, 0xfa;"
 42		     :: "a" (eax), "c" (ecx), "d"(edx));
 43}
 44
 45static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
 46{
 47	mds_idle_clear_cpu_buffers();
 48
 49	/* "mwait %eax, %ecx;" */
 50	asm volatile(".byte 0x0f, 0x01, 0xc9;"
 51		     :: "a" (eax), "c" (ecx));
 52}
 53
 54/*
 55 * MWAITX allows for a timer expiration to get the core out a wait state in
 56 * addition to the default MWAIT exit condition of a store appearing at a
 57 * monitored virtual address.
 58 *
 59 * Registers:
 60 *
 61 * MWAITX ECX[1]: enable timer if set
 62 * MWAITX EBX[31:0]: max wait time expressed in SW P0 clocks. The software P0
 63 * frequency is the same as the TSC frequency.
 64 *
 65 * Below is a comparison between MWAIT and MWAITX on AMD processors:
 66 *
 67 *                 MWAIT                           MWAITX
 68 * opcode          0f 01 c9           |            0f 01 fb
 69 * ECX[0]                  value of RFLAGS.IF seen by instruction
 70 * ECX[1]          unused/#GP if set  |            enable timer if set
 71 * ECX[31:2]                     unused/#GP if set
 72 * EAX                           unused (reserve for hint)
 73 * EBX[31:0]       unused             |            max wait time (P0 clocks)
 74 *
 75 *                 MONITOR                         MONITORX
 76 * opcode          0f 01 c8           |            0f 01 fa
 77 * EAX                     (logical) address to monitor
 78 * ECX                     #GP if not zero
 79 */
 80static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
 81				     unsigned long ecx)
 82{
 83	/* No MDS buffer clear as this is AMD/HYGON only */
 84
 85	/* "mwaitx %eax, %ebx, %ecx;" */
 86	asm volatile(".byte 0x0f, 0x01, 0xfb;"
 87		     :: "a" (eax), "b" (ebx), "c" (ecx));
 88}
 89
 90/*
 91 * Re-enable interrupts right upon calling mwait in such a way that
 92 * no interrupt can fire _before_ the execution of mwait, ie: no
 93 * instruction must be placed between "sti" and "mwait".
 94 *
 95 * This is necessary because if an interrupt queues a timer before
 96 * executing mwait, it would otherwise go unnoticed and the next tick
 97 * would not be reprogrammed accordingly before mwait ever wakes up.
 98 */
 99static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
100{
101	mds_idle_clear_cpu_buffers();
102	/* "mwait %eax, %ecx;" */
103	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
104		     :: "a" (eax), "c" (ecx));
105}
106
107/*
108 * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
109 * which can obviate IPI to trigger checking of need_resched.
110 * We execute MONITOR against need_resched and enter optimized wait state
111 * through MWAIT. Whenever someone changes need_resched, we would be woken
112 * up from MWAIT (without an IPI).
113 *
114 * New with Core Duo processors, MWAIT can take some hints based on CPU
115 * capability.
116 */
117static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
118{
119	if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
120		if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
121			mb();
122			clflush((void *)&current_thread_info()->flags);
123			mb();
124		}
125
126		__monitor((void *)&current_thread_info()->flags, 0, 0);
127
128		if (!need_resched()) {
129			if (ecx & 1) {
130				__mwait(eax, ecx);
131			} else {
132				__sti_mwait(eax, ecx);
133				raw_local_irq_disable();
134			}
135		}
136	}
137	current_clr_polling();
138}
139
140/*
141 * Caller can specify whether to enter C0.1 (low latency, less
142 * power saving) or C0.2 state (saves more power, but longer wakeup
143 * latency). This may be overridden by the IA32_UMWAIT_CONTROL MSR
144 * which can force requests for C0.2 to be downgraded to C0.1.
145 */
146static inline void __tpause(u32 ecx, u32 edx, u32 eax)
147{
148	/* "tpause %ecx, %edx, %eax;" */
149	#ifdef CONFIG_AS_TPAUSE
150	asm volatile("tpause %%ecx\n"
151		     :
152		     : "c"(ecx), "d"(edx), "a"(eax));
153	#else
154	asm volatile(".byte 0x66, 0x0f, 0xae, 0xf1\t\n"
155		     :
156		     : "c"(ecx), "d"(edx), "a"(eax));
157	#endif
158}
159
160#endif /* _ASM_X86_MWAIT_H */