1/* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 5#ifndef _RTE_POWER_INTRINSIC_H_ 6#define _RTE_POWER_INTRINSIC_H_ 7 8#include <inttypes.h> 9 10#include <rte_compat.h> 11#include <rte_spinlock.h> 12 13/** 14 * @file 15 * Advanced power management operations. 16 * 17 * This file define APIs for advanced power management, 18 * which are architecture-dependent. 19 */ 20 21/** Size of the opaque data in monitor condition */ 22#define RTE_POWER_MONITOR_OPAQUE_SZ 4 23 24/** 25 * Callback definition for monitoring conditions. Callbacks with this signature 26 * will be used by `rte_power_monitor()` to check if the entering of power 27 * optimized state should be aborted. 28 * 29 * @param val 30 * The value read from memory. 31 * @param opaque 32 * Callback-specific data. 33 * 34 * @return 35 * 0 if entering of power optimized state should proceed 36 * -1 if entering of power optimized state should be aborted 37 */ 38typedef int (*rte_power_monitor_clb_t)(const uint64_t val, 39 const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ]); 40 41struct rte_power_monitor_cond { 42 volatile void *addr; /**< Address to monitor for changes */ 43 uint8_t size; /**< Data size (in bytes) that will be read from the 44 * monitored memory location (`addr`). Can be 1, 2, 45 * 4, or 8. Supplying any other value will result in 46 * an error. 47 */ 48 rte_power_monitor_clb_t fn; /**< Callback to be used to check if 49 * entering power optimized state should 50 * be aborted. 51 */ 52 uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ]; 53 /**< Callback-specific data */ 54}; 55 56/** 57 * @warning 58 * @b EXPERIMENTAL: this API may change without prior notice. 59 * 60 * Monitor specific address for changes. This will cause the CPU to enter an 61 * architecture-defined optimized power state until either the specified 62 * memory address is written to, a certain TSC timestamp is reached, or other 63 * reasons cause the CPU to wake up. 64 * 65 * Additionally, an expected value (`pmc->val`), mask (`pmc->mask`), and data 66 * size (`pmc->size`) are provided in the `pmc` power monitoring condition. If 67 * the mask is non-zero, the current value pointed to by the `pmc->addr` pointer 68 * will be read and compared against the expected value, and if they match, the 69 * entering of optimized power state will be aborted. This is intended to 70 * prevent the CPU from entering optimized power state and waiting on a write 71 * that has already happened by the time this API is called. 72 * 73 * @warning It is responsibility of the user to check if this function is 74 * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. 75 * 76 * @param pmc 77 * The monitoring condition structure. 78 * @param tsc_timestamp 79 * Maximum TSC timestamp to wait for. Note that the wait behavior is 80 * architecture-dependent. 81 * 82 * @return 83 * 0 on success 84 * -EINVAL on invalid parameters 85 * -ENOTSUP if unsupported 86 */ 87__rte_experimental 88int rte_power_monitor(const struct rte_power_monitor_cond *pmc, 89 const uint64_t tsc_timestamp); 90 91/** 92 * @warning 93 * @b EXPERIMENTAL: this API may change without prior notice. 94 * 95 * Wake up a specific lcore that is in a power optimized state and is monitoring 96 * an address. 97 * 98 * @note It is safe to call this function if the lcore in question is not 99 * sleeping. The function will have no effect. 100 * 101 * @note This function will *not* wake up a core that is in a power optimized 102 * state due to calling `rte_power_pause`. 103 * 104 * @param lcore_id 105 * Lcore ID of a sleeping thread. 106 */ 107__rte_experimental 108int rte_power_monitor_wakeup(const unsigned int lcore_id); 109 110/** 111 * @warning 112 * @b EXPERIMENTAL: this API may change without prior notice. 113 * 114 * Enter an architecture-defined optimized power state until a certain TSC 115 * timestamp is reached. 116 * 117 * @warning It is responsibility of the user to check if this function is 118 * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. 119 * 120 * @param tsc_timestamp 121 * Maximum TSC timestamp to wait for. Note that the wait behavior is 122 * architecture-dependent. 123 * 124 * @return 125 * 0 on success 126 * -EINVAL on invalid parameters 127 * -ENOTSUP if unsupported 128 */ 129__rte_experimental 130int rte_power_pause(const uint64_t tsc_timestamp); 131 132/** 133 * @warning 134 * @b EXPERIMENTAL: this API may change without prior notice 135 * 136 * Monitor a set of addresses for changes. This will cause the CPU to enter an 137 * architecture-defined optimized power state until either one of the specified 138 * memory addresses is written to, a certain TSC timestamp is reached, or other 139 * reasons cause the CPU to wake up. 140 * 141 * Additionally, `expected` 64-bit values and 64-bit masks are provided. If 142 * mask is non-zero, the current value pointed to by the `p` pointer will be 143 * checked against the expected value, and if they do not match, the entering of 144 * optimized power state may be aborted. 145 * 146 * @warning It is responsibility of the user to check if this function is 147 * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. 148 * Failing to do so may result in an illegal CPU instruction error. 149 * 150 * @param pmc 151 * An array of monitoring condition structures. 152 * @param num 153 * Length of the `pmc` array. 154 * @param tsc_timestamp 155 * Maximum TSC timestamp to wait for. Note that the wait behavior is 156 * architecture-dependent. 157 * 158 * @return 159 * 0 on success 160 * -EINVAL on invalid parameters 161 * -ENOTSUP if unsupported 162 */ 163__rte_experimental 164int rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[], 165 const uint32_t num, const uint64_t tsc_timestamp); 166 167#endif /* _RTE_POWER_INTRINSIC_H_ */ 168