regex/mlx5: fix type of setup constants
[dpdk.git] / lib / librte_eal / x86 / include / rte_power_intrinsics.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
3  */
4
5 #ifndef _RTE_POWER_INTRINSIC_X86_H_
6 #define _RTE_POWER_INTRINSIC_X86_H_
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 #include <rte_common.h>
13
14 #include "generic/rte_power_intrinsics.h"
15
16 static inline uint64_t
17 __rte_power_get_umwait_val(const volatile void *p, const uint8_t sz)
18 {
19         switch (sz) {
20         case sizeof(uint8_t):
21                 return *(const volatile uint8_t *)p;
22         case sizeof(uint16_t):
23                 return *(const volatile uint16_t *)p;
24         case sizeof(uint32_t):
25                 return *(const volatile uint32_t *)p;
26         case sizeof(uint64_t):
27                 return *(const volatile uint64_t *)p;
28         default:
29                 /* this is an intrinsic, so we can't have any error handling */
30                 RTE_ASSERT(0);
31                 return 0;
32         }
33 }
34
35 /**
36  * This function uses UMONITOR/UMWAIT instructions and will enter C0.2 state.
37  * For more information about usage of these instructions, please refer to
38  * Intel(R) 64 and IA-32 Architectures Software Developer's Manual.
39  */
40 static inline void
41 rte_power_monitor(const volatile void *p, const uint64_t expected_value,
42                 const uint64_t value_mask, const uint64_t tsc_timestamp,
43                 const uint8_t data_sz)
44 {
45         const uint32_t tsc_l = (uint32_t)tsc_timestamp;
46         const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
47         /*
48          * we're using raw byte codes for now as only the newest compiler
49          * versions support this instruction natively.
50          */
51
52         /* set address for UMONITOR */
53         asm volatile(".byte 0xf3, 0x0f, 0xae, 0xf7;"
54                         :
55                         : "D"(p));
56
57         if (value_mask) {
58                 const uint64_t cur_value = __rte_power_get_umwait_val(p, data_sz);
59                 const uint64_t masked = cur_value & value_mask;
60
61                 /* if the masked value is already matching, abort */
62                 if (masked == expected_value)
63                         return;
64         }
65         /* execute UMWAIT */
66         asm volatile(".byte 0xf2, 0x0f, 0xae, 0xf7;"
67                         : /* ignore rflags */
68                         : "D"(0), /* enter C0.2 */
69                           "a"(tsc_l), "d"(tsc_h));
70 }
71
72 /**
73  * This function uses UMONITOR/UMWAIT instructions and will enter C0.2 state.
74  * For more information about usage of these instructions, please refer to
75  * Intel(R) 64 and IA-32 Architectures Software Developer's Manual.
76  */
77 static inline void
78 rte_power_monitor_sync(const volatile void *p, const uint64_t expected_value,
79                 const uint64_t value_mask, const uint64_t tsc_timestamp,
80                 const uint8_t data_sz, rte_spinlock_t *lck)
81 {
82         const uint32_t tsc_l = (uint32_t)tsc_timestamp;
83         const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
84         /*
85          * we're using raw byte codes for now as only the newest compiler
86          * versions support this instruction natively.
87          */
88
89         /* set address for UMONITOR */
90         asm volatile(".byte 0xf3, 0x0f, 0xae, 0xf7;"
91                         :
92                         : "D"(p));
93
94         if (value_mask) {
95                 const uint64_t cur_value = __rte_power_get_umwait_val(p, data_sz);
96                 const uint64_t masked = cur_value & value_mask;
97
98                 /* if the masked value is already matching, abort */
99                 if (masked == expected_value)
100                         return;
101         }
102         rte_spinlock_unlock(lck);
103
104         /* execute UMWAIT */
105         asm volatile(".byte 0xf2, 0x0f, 0xae, 0xf7;"
106                         : /* ignore rflags */
107                         : "D"(0), /* enter C0.2 */
108                           "a"(tsc_l), "d"(tsc_h));
109
110         rte_spinlock_lock(lck);
111 }
112
113 /**
114  * This function uses TPAUSE instruction  and will enter C0.2 state. For more
115  * information about usage of this instruction, please refer to Intel(R) 64 and
116  * IA-32 Architectures Software Developer's Manual.
117  */
118 static inline void
119 rte_power_pause(const uint64_t tsc_timestamp)
120 {
121         const uint32_t tsc_l = (uint32_t)tsc_timestamp;
122         const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
123
124         /* execute TPAUSE */
125         asm volatile(".byte 0x66, 0x0f, 0xae, 0xf7;"
126                 : /* ignore rflags */
127                 : "D"(0), /* enter C0.2 */
128                   "a"(tsc_l), "d"(tsc_h));
129 }
130
131 #ifdef __cplusplus
132 }
133 #endif
134
135 #endif /* _RTE_POWER_INTRINSIC_X86_H_ */