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