1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
5 #include "rte_power_intrinsics.h"
8 __get_umwait_val(const volatile void *p, const uint8_t sz)
12 return *(const volatile uint8_t *)p;
13 case sizeof(uint16_t):
14 return *(const volatile uint16_t *)p;
15 case sizeof(uint32_t):
16 return *(const volatile uint32_t *)p;
17 case sizeof(uint64_t):
18 return *(const volatile uint64_t *)p;
20 /* this is an intrinsic, so we can't have any error handling */
27 * This function uses UMONITOR/UMWAIT instructions and will enter C0.2 state.
28 * For more information about usage of these instructions, please refer to
29 * Intel(R) 64 and IA-32 Architectures Software Developer's Manual.
32 rte_power_monitor(const volatile void *p, const uint64_t expected_value,
33 const uint64_t value_mask, const uint64_t tsc_timestamp,
34 const uint8_t data_sz)
36 const uint32_t tsc_l = (uint32_t)tsc_timestamp;
37 const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
39 * we're using raw byte codes for now as only the newest compiler
40 * versions support this instruction natively.
43 /* set address for UMONITOR */
44 asm volatile(".byte 0xf3, 0x0f, 0xae, 0xf7;"
49 const uint64_t cur_value = __get_umwait_val(p, data_sz);
50 const uint64_t masked = cur_value & value_mask;
52 /* if the masked value is already matching, abort */
53 if (masked == expected_value)
57 asm volatile(".byte 0xf2, 0x0f, 0xae, 0xf7;"
59 : "D"(0), /* enter C0.2 */
60 "a"(tsc_l), "d"(tsc_h));
64 * This function uses UMONITOR/UMWAIT instructions and will enter C0.2 state.
65 * For more information about usage of these instructions, please refer to
66 * Intel(R) 64 and IA-32 Architectures Software Developer's Manual.
69 rte_power_monitor_sync(const volatile void *p, const uint64_t expected_value,
70 const uint64_t value_mask, const uint64_t tsc_timestamp,
71 const uint8_t data_sz, rte_spinlock_t *lck)
73 const uint32_t tsc_l = (uint32_t)tsc_timestamp;
74 const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
76 * we're using raw byte codes for now as only the newest compiler
77 * versions support this instruction natively.
80 /* set address for UMONITOR */
81 asm volatile(".byte 0xf3, 0x0f, 0xae, 0xf7;"
86 const uint64_t cur_value = __get_umwait_val(p, data_sz);
87 const uint64_t masked = cur_value & value_mask;
89 /* if the masked value is already matching, abort */
90 if (masked == expected_value)
93 rte_spinlock_unlock(lck);
96 asm volatile(".byte 0xf2, 0x0f, 0xae, 0xf7;"
98 : "D"(0), /* enter C0.2 */
99 "a"(tsc_l), "d"(tsc_h));
101 rte_spinlock_lock(lck);
105 * This function uses TPAUSE instruction and will enter C0.2 state. For more
106 * information about usage of this instruction, please refer to Intel(R) 64 and
107 * IA-32 Architectures Software Developer's Manual.
110 rte_power_pause(const uint64_t tsc_timestamp)
112 const uint32_t tsc_l = (uint32_t)tsc_timestamp;
113 const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
116 asm volatile(".byte 0x66, 0x0f, 0xae, 0xf7;"
117 : /* ignore rflags */
118 : "D"(0), /* enter C0.2 */
119 "a"(tsc_l), "d"(tsc_h));