LCOV - code coverage report
Current view: top level - arch/x86/include/asm - mwait.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 15 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 0 -

          Line data    Source code
       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             : 
      17             : #define CPUID_MWAIT_LEAF                5
      18             : #define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
      19             : #define CPUID5_ECX_INTERRUPT_BREAK      0x2
      20             : 
      21             : #define MWAIT_ECX_INTERRUPT_BREAK       0x1
      22             : #define MWAITX_ECX_TIMER_ENABLE         BIT(1)
      23             : #define MWAITX_MAX_WAIT_CYCLES          UINT_MAX
      24             : #define MWAITX_DISABLE_CSTATES          0xf0
      25             : #define TPAUSE_C01_STATE                1
      26             : #define TPAUSE_C02_STATE                0
      27             : 
      28           0 : static inline void __monitor(const void *eax, unsigned long ecx,
      29             :                              unsigned long edx)
      30             : {
      31             :         /* "monitor %eax, %ecx, %edx;" */
      32           0 :         asm volatile(".byte 0x0f, 0x01, 0xc8;"
      33             :                      :: "a" (eax), "c" (ecx), "d"(edx));
      34             : }
      35             : 
      36           0 : static inline void __monitorx(const void *eax, unsigned long ecx,
      37             :                               unsigned long edx)
      38             : {
      39             :         /* "monitorx %eax, %ecx, %edx;" */
      40           0 :         asm volatile(".byte 0x0f, 0x01, 0xfa;"
      41             :                      :: "a" (eax), "c" (ecx), "d"(edx));
      42             : }
      43             : 
      44           0 : static inline void __mwait(unsigned long eax, unsigned long ecx)
      45             : {
      46           0 :         mds_idle_clear_cpu_buffers();
      47             : 
      48             :         /* "mwait %eax, %ecx;" */
      49           0 :         asm volatile(".byte 0x0f, 0x01, 0xc9;"
      50             :                      :: "a" (eax), "c" (ecx));
      51             : }
      52             : 
      53             : /*
      54             :  * MWAITX allows for a timer expiration to get the core out a wait state in
      55             :  * addition to the default MWAIT exit condition of a store appearing at a
      56             :  * monitored virtual address.
      57             :  *
      58             :  * Registers:
      59             :  *
      60             :  * MWAITX ECX[1]: enable timer if set
      61             :  * MWAITX EBX[31:0]: max wait time expressed in SW P0 clocks. The software P0
      62             :  * frequency is the same as the TSC frequency.
      63             :  *
      64             :  * Below is a comparison between MWAIT and MWAITX on AMD processors:
      65             :  *
      66             :  *                 MWAIT                           MWAITX
      67             :  * opcode          0f 01 c9           |            0f 01 fb
      68             :  * ECX[0]                  value of RFLAGS.IF seen by instruction
      69             :  * ECX[1]          unused/#GP if set  |            enable timer if set
      70             :  * ECX[31:2]                     unused/#GP if set
      71             :  * EAX                           unused (reserve for hint)
      72             :  * EBX[31:0]       unused             |            max wait time (P0 clocks)
      73             :  *
      74             :  *                 MONITOR                         MONITORX
      75             :  * opcode          0f 01 c8           |            0f 01 fa
      76             :  * EAX                     (logical) address to monitor
      77             :  * ECX                     #GP if not zero
      78             :  */
      79           0 : static inline void __mwaitx(unsigned long eax, unsigned long ebx,
      80             :                             unsigned long ecx)
      81             : {
      82             :         /* No MDS buffer clear as this is AMD/HYGON only */
      83             : 
      84             :         /* "mwaitx %eax, %ebx, %ecx;" */
      85           0 :         asm volatile(".byte 0x0f, 0x01, 0xfb;"
      86             :                      :: "a" (eax), "b" (ebx), "c" (ecx));
      87             : }
      88             : 
      89           0 : static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
      90             : {
      91           0 :         mds_idle_clear_cpu_buffers();
      92             :         /* "mwait %eax, %ecx;" */
      93           0 :         asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
      94             :                      :: "a" (eax), "c" (ecx));
      95           0 : }
      96             : 
      97             : /*
      98             :  * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
      99             :  * which can obviate IPI to trigger checking of need_resched.
     100             :  * We execute MONITOR against need_resched and enter optimized wait state
     101             :  * through MWAIT. Whenever someone changes need_resched, we would be woken
     102             :  * up from MWAIT (without an IPI).
     103             :  *
     104             :  * New with Core Duo processors, MWAIT can take some hints based on CPU
     105             :  * capability.
     106             :  */
     107             : static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
     108             : {
     109             :         if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
     110             :                 if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
     111             :                         mb();
     112             :                         clflush((void *)&current_thread_info()->flags);
     113             :                         mb();
     114             :                 }
     115             : 
     116             :                 __monitor((void *)&current_thread_info()->flags, 0, 0);
     117             :                 if (!need_resched())
     118             :                         __mwait(eax, ecx);
     119             :         }
     120             :         current_clr_polling();
     121             : }
     122             : 
     123             : /*
     124             :  * Caller can specify whether to enter C0.1 (low latency, less
     125             :  * power saving) or C0.2 state (saves more power, but longer wakeup
     126             :  * latency). This may be overridden by the IA32_UMWAIT_CONTROL MSR
     127             :  * which can force requests for C0.2 to be downgraded to C0.1.
     128             :  */
     129           0 : static inline void __tpause(u32 ecx, u32 edx, u32 eax)
     130             : {
     131             :         /* "tpause %ecx, %edx, %eax;" */
     132             :         #ifdef CONFIG_AS_TPAUSE
     133           0 :         asm volatile("tpause %%ecx\n"
     134             :                      :
     135             :                      : "c"(ecx), "d"(edx), "a"(eax));
     136             :         #else
     137             :         asm volatile(".byte 0x66, 0x0f, 0xae, 0xf1\t\n"
     138             :                      :
     139             :                      : "c"(ecx), "d"(edx), "a"(eax));
     140             :         #endif
     141             : }
     142             : 
     143             : #endif /* _ASM_X86_MWAIT_H */

Generated by: LCOV version 1.14