power: add per-core turbo boost API
authorDavid Hunt <david.hunt@intel.com>
Wed, 13 Sep 2017 10:44:16 +0000 (11:44 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Fri, 22 Sep 2017 14:35:12 +0000 (16:35 +0200)
Adds a new set of APIs to allow per-core turbo
enable-disable.

Signed-off-by: David Hunt <david.hunt@intel.com>
doc/guides/prog_guide/power_man.rst
lib/librte_power/channel_commands.h
lib/librte_power/rte_power.c
lib/librte_power/rte_power.h
lib/librte_power/rte_power_acpi_cpufreq.c
lib/librte_power/rte_power_acpi_cpufreq.h
lib/librte_power/rte_power_kvm_vm.c
lib/librte_power/rte_power_kvm_vm.h

index 114d0b1..c5d62a3 100644 (file)
@@ -89,6 +89,14 @@ Core state can be altered by speculative sleeps whenever the specified lcore has
 In the DPDK, if no packet is received after polling,
 speculative sleeps can be triggered according the strategies defined by the user space application.
 
+Per-core Turbo Boost
+--------------------
+
+Individual cores can be allowed to enter a Turbo Boost state on a per-core
+basis. This is achieved by enabling Turbo Boost Technology in the BIOS, then
+looping through the relevant cores and enabling/disabling Turbo Boost on each
+core.
+
 API Overview of the Power Library
 ---------------------------------
 
@@ -108,6 +116,10 @@ The main methods exported by power library are for CPU frequency scaling and inc
 
 *   **Freq set**: Prompt the kernel to set the frequency for the specific lcore.
 
+*   **Enable turbo**: Prompt the kernel to enable Turbo Boost for the specific lcore.
+
+*   **Disable turbo**: Prompt the kernel to disable Turbo Boost for the specific lcore.
+
 User Cases
 ----------
 
index 383897b..484085b 100644 (file)
@@ -52,6 +52,8 @@ extern "C" {
 #define CPU_POWER_SCALE_DOWN    2
 #define CPU_POWER_SCALE_MAX     3
 #define CPU_POWER_SCALE_MIN     4
+#define CPU_POWER_ENABLE_TURBO  5
+#define CPU_POWER_DISABLE_TURBO 6
 
 struct channel_packet {
        uint64_t resource_id; /**< core_num, device */
index 998ed1c..b327a86 100644 (file)
@@ -50,6 +50,9 @@ rte_power_freq_change_t rte_power_freq_up = NULL;
 rte_power_freq_change_t rte_power_freq_down = NULL;
 rte_power_freq_change_t rte_power_freq_max = NULL;
 rte_power_freq_change_t rte_power_freq_min = NULL;
+rte_power_freq_change_t rte_power_turbo_status;
+rte_power_freq_change_t rte_power_freq_enable_turbo;
+rte_power_freq_change_t rte_power_freq_disable_turbo;
 
 int
 rte_power_set_env(enum power_management_env env)
@@ -65,6 +68,9 @@ rte_power_set_env(enum power_management_env env)
                rte_power_freq_down = rte_power_acpi_cpufreq_freq_down;
                rte_power_freq_min = rte_power_acpi_cpufreq_freq_min;
                rte_power_freq_max = rte_power_acpi_cpufreq_freq_max;
+               rte_power_turbo_status = rte_power_acpi_turbo_status;
+               rte_power_freq_enable_turbo = rte_power_acpi_enable_turbo;
+               rte_power_freq_disable_turbo = rte_power_acpi_disable_turbo;
        } else if (env == PM_ENV_KVM_VM) {
                rte_power_freqs = rte_power_kvm_vm_freqs;
                rte_power_get_freq = rte_power_kvm_vm_get_freq;
@@ -73,6 +79,9 @@ rte_power_set_env(enum power_management_env env)
                rte_power_freq_down = rte_power_kvm_vm_freq_down;
                rte_power_freq_min = rte_power_kvm_vm_freq_min;
                rte_power_freq_max = rte_power_kvm_vm_freq_max;
+               rte_power_turbo_status = rte_power_kvm_vm_turbo_status;
+               rte_power_freq_enable_turbo = rte_power_kvm_vm_enable_turbo;
+               rte_power_freq_disable_turbo = rte_power_kvm_vm_disable_turbo;
        } else {
                RTE_LOG(ERR, POWER, "Invalid Power Management Environment(%d) set\n",
                                env);
index 67e0ec0..b17b7a5 100644 (file)
@@ -236,6 +236,47 @@ extern rte_power_freq_change_t rte_power_freq_max;
  */
 extern rte_power_freq_change_t rte_power_freq_min;
 
+/**
+ * Query the Turbo Boost status of a specific lcore.
+ * Review each environments specific documentation for usage..
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 1 Turbo Boost is enabled for this lcore.
+ *  - 0 Turbo Boost is disabled for this lcore.
+ *  - Negative on error.
+ */
+extern rte_power_freq_change_t rte_power_turbo_status;
+
+/**
+ * Enable Turbo Boost for this lcore.
+ * Review each environments specific documentation for usage..
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 0 on success.
+ *  - Negative on error.
+ */
+extern rte_power_freq_change_t rte_power_freq_enable_turbo;
+
+/**
+ * Disable Turbo Boost for this lcore.
+ * Review each environments specific documentation for usage..
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 0 on success.
+ *  - Negative on error.
+ */
+extern rte_power_freq_change_t rte_power_freq_disable_turbo;
+
+
 #ifdef __cplusplus
 }
 #endif
index a56c9b5..01ac5ac 100644 (file)
 #define POWER_SYSFILE_SETSPEED   \
                "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_setspeed"
 
+/*
+ * MSR related
+ */
+#define PLATFORM_INFO     0x0CE
+#define TURBO_RATIO_LIMIT 0x1AD
+#define IA32_PERF_CTL     0x199
+#define CORE_TURBO_DISABLE_BIT ((uint64_t)1<<32)
+
 enum power_state {
        POWER_IDLE = 0,
        POWER_ONGOING,
@@ -105,6 +113,8 @@ struct rte_power_info {
        char governor_ori[32];               /**< Original governor name */
        uint32_t curr_idx;                   /**< Freq index in freqs array */
        volatile uint32_t state;             /**< Power in use state */
+       uint16_t turbo_available;            /**< Turbo Boost available */
+       uint16_t turbo_enable;               /**< Turbo Boost enable/disable */
 } __rte_cache_aligned;
 
 static struct rte_power_info lcore_power_info[RTE_MAX_LCORE];
@@ -244,6 +254,18 @@ power_get_available_freqs(struct rte_power_info *pi)
                                POWER_CONVERT_TO_DECIMAL);
        }
 
+       if ((pi->freqs[0]-1000) == pi->freqs[1]) {
+               pi->turbo_available = 1;
+               pi->turbo_enable = 1;
+               POWER_DEBUG_TRACE("Lcore %u Can do Turbo Boost\n",
+                               pi->lcore_id);
+       } else {
+               pi->turbo_available = 0;
+               pi->turbo_enable = 0;
+               POWER_DEBUG_TRACE("Turbo Boost not available on Lcore %u\n",
+                               pi->lcore_id);
+       }
+
        ret = 0;
        POWER_DEBUG_TRACE("%d frequencie(s) of lcore %u are available\n",
                        count, pi->lcore_id);
@@ -525,7 +547,17 @@ rte_power_acpi_cpufreq_freq_max(unsigned lcore_id)
        }
 
        /* Frequencies in the array are from high to low. */
-       return set_freq_internal(&lcore_power_info[lcore_id], 0);
+       if (lcore_power_info[lcore_id].turbo_available) {
+               if (lcore_power_info[lcore_id].turbo_enable)
+                       /* Set to Turbo */
+                       return set_freq_internal(
+                                       &lcore_power_info[lcore_id], 0);
+               else
+                       /* Set to max non-turbo */
+                       return set_freq_internal(
+                                       &lcore_power_info[lcore_id], 1);
+       } else
+               return set_freq_internal(&lcore_power_info[lcore_id], 0);
 }
 
 int
@@ -543,3 +575,80 @@ rte_power_acpi_cpufreq_freq_min(unsigned lcore_id)
        /* Frequencies in the array are from high to low. */
        return set_freq_internal(pi, pi->nb_freqs - 1);
 }
+
+
+int
+rte_power_acpi_turbo_status(unsigned int lcore_id)
+{
+       struct rte_power_info *pi;
+
+       if (lcore_id >= RTE_MAX_LCORE) {
+               RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
+               return -1;
+       }
+
+       pi = &lcore_power_info[lcore_id];
+
+       return pi->turbo_enable;
+}
+
+
+int
+rte_power_acpi_enable_turbo(unsigned int lcore_id)
+{
+       struct rte_power_info *pi;
+
+       if (lcore_id >= RTE_MAX_LCORE) {
+               RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
+               return -1;
+       }
+
+       pi = &lcore_power_info[lcore_id];
+
+       if (pi->turbo_available)
+               pi->turbo_enable = 1;
+       else {
+               pi->turbo_enable = 0;
+               RTE_LOG(ERR, POWER,
+                       "Failed to enable turbo on lcore %u\n",
+                       lcore_id);
+                       return -1;
+       }
+
+       /* Max may have changed, so call to max function */
+       if (rte_power_acpi_cpufreq_freq_max(lcore_id) < 0) {
+               RTE_LOG(ERR, POWER,
+                       "Failed to set frequency of lcore %u to max\n",
+                       lcore_id);
+                       return -1;
+       }
+
+       return 0;
+}
+
+int
+rte_power_acpi_disable_turbo(unsigned int lcore_id)
+{
+       struct rte_power_info *pi;
+
+       if (lcore_id >= RTE_MAX_LCORE) {
+               RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
+               return -1;
+       }
+
+       pi = &lcore_power_info[lcore_id];
+
+        pi->turbo_enable = 0;
+
+       if ((pi->turbo_available) && (pi->curr_idx <= 1)) {
+               /* Try to set freq to max by default coming out of turbo */
+               if (rte_power_acpi_cpufreq_freq_max(lcore_id) < 0) {
+                       RTE_LOG(ERR, POWER,
+                               "Failed to set frequency of lcore %u to max\n",
+                               lcore_id);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
index 68578e9..eee0ca0 100644 (file)
@@ -185,6 +185,46 @@ int rte_power_acpi_cpufreq_freq_max(unsigned lcore_id);
  */
 int rte_power_acpi_cpufreq_freq_min(unsigned lcore_id);
 
+/**
+ * Get the turbo status of a specific lcore.
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 1 Turbo Boost is enabled on this lcore.
+ *  - 0 Turbo Boost is disabled on this lcore.
+ *  - Negative on error.
+ */
+int rte_power_acpi_turbo_status(unsigned int lcore_id);
+
+/**
+ * Enable Turbo Boost on a specific lcore.
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 0 Turbo Boost is enabled successfully on this lcore.
+ *  - Negative on error.
+ */
+int rte_power_acpi_enable_turbo(unsigned int lcore_id);
+
+/**
+ * Disable Turbo Boost on a specific lcore.
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 0 Turbo Boost disabled successfully on this lcore.
+ *  - Negative on error.
+ */
+int rte_power_acpi_disable_turbo(unsigned int lcore_id);
+
 #ifdef __cplusplus
 }
 #endif
index a1badf3..9906062 100644 (file)
@@ -134,3 +134,22 @@ rte_power_kvm_vm_freq_min(unsigned lcore_id)
 {
        return send_msg(lcore_id, CPU_POWER_SCALE_MIN);
 }
+
+int
+rte_power_kvm_vm_turbo_status(__attribute__((unused)) unsigned int lcore_id)
+{
+       RTE_LOG(ERR, POWER, "rte_power_turbo_status is not implemented for Virtual Machine Power Management\n");
+       return -ENOTSUP;
+}
+
+int
+rte_power_kvm_vm_enable_turbo(unsigned int lcore_id)
+{
+       return send_msg(lcore_id, CPU_POWER_ENABLE_TURBO);
+}
+
+int
+rte_power_kvm_vm_disable_turbo(unsigned int lcore_id)
+{
+       return send_msg(lcore_id, CPU_POWER_DISABLE_TURBO);
+}
index dcbc878..9af41d6 100644 (file)
@@ -172,8 +172,41 @@ int rte_power_kvm_vm_freq_max(unsigned lcore_id);
  */
 int rte_power_kvm_vm_freq_min(unsigned lcore_id);
 
+/**
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  -ENOTSUP
+ */
+int rte_power_kvm_vm_turbo_status(unsigned int lcore_id);
+
+/**
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 1 on success.
+ *  - Negative on error.
+ */
+int rte_power_kvm_vm_enable_turbo(unsigned int lcore_id);
+
+/**
+ * It should be protected outside of this function for threadsafe.
+ *
+ * @param lcore_id
+ *  lcore id.
+ *
+ * @return
+ *  - 1 on success.
+ *  - Negative on error.
+ */
+int rte_power_kvm_vm_disable_turbo(unsigned int lcore_id);
 #ifdef __cplusplus
 }
 #endif
-
 #endif