LCOV - code coverage report
Current view: top level - arch/x86/include/asm - mwait.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 26 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 1 0.0 %
Branches: 0 16 0.0 %

           Branch data     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_LOOPS                ((u32)-1)
      24                 :            : #define MWAITX_DISABLE_CSTATES          0xf0
      25                 :            : 
      26                 :          0 : static inline void __monitor(const void *eax, unsigned long ecx,
      27                 :            :                              unsigned long edx)
      28                 :            : {
      29                 :            :         /* "monitor %eax, %ecx, %edx;" */
      30                 :          0 :         asm volatile(".byte 0x0f, 0x01, 0xc8;"
      31                 :            :                      :: "a" (eax), "c" (ecx), "d"(edx));
      32                 :            : }
      33                 :            : 
      34                 :          0 : static inline void __monitorx(const void *eax, unsigned long ecx,
      35                 :            :                               unsigned long edx)
      36                 :            : {
      37                 :            :         /* "monitorx %eax, %ecx, %edx;" */
      38                 :          0 :         asm volatile(".byte 0x0f, 0x01, 0xfa;"
      39                 :            :                      :: "a" (eax), "c" (ecx), "d"(edx));
      40                 :            : }
      41                 :            : 
      42                 :          0 : static inline void __mwait(unsigned long eax, unsigned long ecx)
      43                 :            : {
      44         [ #  # ]:          0 :         mds_idle_clear_cpu_buffers();
      45                 :            : 
      46                 :            :         /* "mwait %eax, %ecx;" */
      47                 :          0 :         asm volatile(".byte 0x0f, 0x01, 0xc9;"
      48                 :            :                      :: "a" (eax), "c" (ecx));
      49                 :          0 : }
      50                 :            : 
      51                 :            : /*
      52                 :            :  * MWAITX allows for a timer expiration to get the core out a wait state in
      53                 :            :  * addition to the default MWAIT exit condition of a store appearing at a
      54                 :            :  * monitored virtual address.
      55                 :            :  *
      56                 :            :  * Registers:
      57                 :            :  *
      58                 :            :  * MWAITX ECX[1]: enable timer if set
      59                 :            :  * MWAITX EBX[31:0]: max wait time expressed in SW P0 clocks. The software P0
      60                 :            :  * frequency is the same as the TSC frequency.
      61                 :            :  *
      62                 :            :  * Below is a comparison between MWAIT and MWAITX on AMD processors:
      63                 :            :  *
      64                 :            :  *                 MWAIT                           MWAITX
      65                 :            :  * opcode          0f 01 c9           |            0f 01 fb
      66                 :            :  * ECX[0]                  value of RFLAGS.IF seen by instruction
      67                 :            :  * ECX[1]          unused/#GP if set  |            enable timer if set
      68                 :            :  * ECX[31:2]                     unused/#GP if set
      69                 :            :  * EAX                           unused (reserve for hint)
      70                 :            :  * EBX[31:0]       unused             |            max wait time (P0 clocks)
      71                 :            :  *
      72                 :            :  *                 MONITOR                         MONITORX
      73                 :            :  * opcode          0f 01 c8           |            0f 01 fa
      74                 :            :  * EAX                     (logical) address to monitor
      75                 :            :  * ECX                     #GP if not zero
      76                 :            :  */
      77                 :          0 : static inline void __mwaitx(unsigned long eax, unsigned long ebx,
      78                 :            :                             unsigned long ecx)
      79                 :            : {
      80                 :            :         /* No MDS buffer clear as this is AMD/HYGON only */
      81                 :            : 
      82                 :            :         /* "mwaitx %eax, %ebx, %ecx;" */
      83                 :          0 :         asm volatile(".byte 0x0f, 0x01, 0xfb;"
      84                 :            :                      :: "a" (eax), "b" (ebx), "c" (ecx));
      85                 :            : }
      86                 :            : 
      87                 :          0 : static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
      88                 :            : {
      89                 :          0 :         trace_hardirqs_on();
      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                 :          0 : static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
     108                 :            : {
     109   [ #  #  #  #  :          0 :         if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
                      # ]
     110      [ #  #  # ]:          0 :                 if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
     111                 :          0 :                         mb();
     112                 :          0 :                         clflush((void *)&current_thread_info()->flags);
     113                 :          0 :                         mb();
     114                 :            :                 }
     115                 :            : 
     116                 :          0 :                 __monitor((void *)&current_thread_info()->flags, 0, 0);
     117         [ #  # ]:          0 :                 if (!need_resched())
     118         [ #  # ]:          0 :                         __mwait(eax, ecx);
     119                 :            :         }
     120                 :          0 :         current_clr_polling();
     121                 :          0 : }
     122                 :            : 
     123                 :            : #endif /* _ASM_X86_MWAIT_H */

Generated by: LCOV version 1.14