1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
5 #include "rte_power_intrinsics.h"
7 static bool wait_supported;
10 __get_umwait_val(const volatile void *p, const uint8_t sz)
14 return *(const volatile uint8_t *)p;
15 case sizeof(uint16_t):
16 return *(const volatile uint16_t *)p;
17 case sizeof(uint32_t):
18 return *(const volatile uint32_t *)p;
19 case sizeof(uint64_t):
20 return *(const volatile uint64_t *)p;
22 /* shouldn't happen */
29 __check_val_size(const uint8_t sz)
32 case sizeof(uint8_t): /* fall-through */
33 case sizeof(uint16_t): /* fall-through */
34 case sizeof(uint32_t): /* fall-through */
35 case sizeof(uint64_t): /* fall-through */
44 * This function uses UMONITOR/UMWAIT instructions and will enter C0.2 state.
45 * For more information about usage of these instructions, please refer to
46 * Intel(R) 64 and IA-32 Architectures Software Developer's Manual.
49 rte_power_monitor(const struct rte_power_monitor_cond *pmc,
50 const uint64_t tsc_timestamp)
52 const uint32_t tsc_l = (uint32_t)tsc_timestamp;
53 const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
55 /* prevent user from running this instruction if it's not supported */
62 if (__check_val_size(pmc->data_sz) < 0)
66 * we're using raw byte codes for now as only the newest compiler
67 * versions support this instruction natively.
70 /* set address for UMONITOR */
71 asm volatile(".byte 0xf3, 0x0f, 0xae, 0xf7;"
76 const uint64_t cur_value = __get_umwait_val(
77 pmc->addr, pmc->data_sz);
78 const uint64_t masked = cur_value & pmc->mask;
80 /* if the masked value is already matching, abort */
81 if (masked == pmc->val)
85 asm volatile(".byte 0xf2, 0x0f, 0xae, 0xf7;"
87 : "D"(0), /* enter C0.2 */
88 "a"(tsc_l), "d"(tsc_h));
94 * This function uses TPAUSE instruction and will enter C0.2 state. For more
95 * information about usage of this instruction, please refer to Intel(R) 64 and
96 * IA-32 Architectures Software Developer's Manual.
99 rte_power_pause(const uint64_t tsc_timestamp)
101 const uint32_t tsc_l = (uint32_t)tsc_timestamp;
102 const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);
104 /* prevent user from running this instruction if it's not supported */
109 asm volatile(".byte 0x66, 0x0f, 0xae, 0xf7;"
110 : /* ignore rflags */
111 : "D"(0), /* enter C0.2 */
112 "a"(tsc_l), "d"(tsc_h));
117 RTE_INIT(rte_power_intrinsics_init) {
118 struct rte_cpu_intrinsics i;
120 rte_cpu_get_intrinsics_support(&i);
122 if (i.power_monitor && i.power_pause)