1f88e7c17SRadu Nicolau /* SPDX-License-Identifier: BSD-3-Clause 2f88e7c17SRadu Nicolau * Copyright(c) 2010-2018 Intel Corporation 3f88e7c17SRadu Nicolau */ 4f88e7c17SRadu Nicolau 572b452c5SDmitry Kozlyuk #include <ctype.h> 6f88e7c17SRadu Nicolau #include <stdio.h> 772b452c5SDmitry Kozlyuk #include <stdlib.h> 8f88e7c17SRadu Nicolau #include <string.h> 9f88e7c17SRadu Nicolau 10f88e7c17SRadu Nicolau #include <rte_common.h> 11f88e7c17SRadu Nicolau #include <rte_memory.h> 12f88e7c17SRadu Nicolau #include <rte_lcore.h> 13*f30a1bbdSSivaprasad Tummala #include <rte_power_cpufreq.h> 14f88e7c17SRadu Nicolau #include <rte_string_fns.h> 15f88e7c17SRadu Nicolau 16f88e7c17SRadu Nicolau #include "perf_core.h" 17f88e7c17SRadu Nicolau #include "main.h" 18f88e7c17SRadu Nicolau 19f88e7c17SRadu Nicolau 20f88e7c17SRadu Nicolau static uint16_t hp_lcores[RTE_MAX_LCORE]; 21f88e7c17SRadu Nicolau static uint16_t nb_hp_lcores; 22f88e7c17SRadu Nicolau 237e06c0deSTyler Retzlaff struct __rte_cache_aligned perf_lcore_params { 24f88e7c17SRadu Nicolau uint16_t port_id; 25b23c5bd7SSivaprasad Tummala uint16_t queue_id; 26f88e7c17SRadu Nicolau uint8_t high_perf; 274b978938SSivaprasad Tummala uint32_t lcore_idx; 287e06c0deSTyler Retzlaff }; 29f88e7c17SRadu Nicolau 30f88e7c17SRadu Nicolau static struct perf_lcore_params prf_lc_prms[MAX_LCORE_PARAMS]; 31f88e7c17SRadu Nicolau static uint16_t nb_prf_lc_prms; 32f88e7c17SRadu Nicolau 33eb8d9bbfSAnatoly Burakov static int 34eb8d9bbfSAnatoly Burakov is_hp_core(unsigned int lcore) 35eb8d9bbfSAnatoly Burakov { 36eb8d9bbfSAnatoly Burakov struct rte_power_core_capabilities caps; 37eb8d9bbfSAnatoly Burakov int ret; 38eb8d9bbfSAnatoly Burakov 39eb8d9bbfSAnatoly Burakov /* do we have power management enabled? */ 40eb8d9bbfSAnatoly Burakov if (rte_power_get_env() == PM_ENV_NOT_SET) { 41eb8d9bbfSAnatoly Burakov /* there's no power management, so just mark it as high perf */ 42eb8d9bbfSAnatoly Burakov return 1; 43eb8d9bbfSAnatoly Burakov } 44eb8d9bbfSAnatoly Burakov ret = rte_power_get_capabilities(lcore, &caps); 45eb8d9bbfSAnatoly Burakov return ret == 0 && caps.turbo; 46eb8d9bbfSAnatoly Burakov } 47eb8d9bbfSAnatoly Burakov 48f88e7c17SRadu Nicolau int 49f88e7c17SRadu Nicolau update_lcore_params(void) 50f88e7c17SRadu Nicolau { 51f88e7c17SRadu Nicolau uint8_t non_perf_lcores[RTE_MAX_LCORE]; 52f88e7c17SRadu Nicolau uint16_t nb_non_perf_lcores = 0; 53eb8d9bbfSAnatoly Burakov int i, j; 54f88e7c17SRadu Nicolau 55f88e7c17SRadu Nicolau /* if perf-config option was not used do nothing */ 56f88e7c17SRadu Nicolau if (nb_prf_lc_prms == 0) 57f88e7c17SRadu Nicolau return 0; 58f88e7c17SRadu Nicolau 59f88e7c17SRadu Nicolau /* if high-perf-cores option was not used query every available core */ 60f88e7c17SRadu Nicolau if (nb_hp_lcores == 0) { 61f88e7c17SRadu Nicolau for (i = 0; i < RTE_MAX_LCORE; i++) { 62eb8d9bbfSAnatoly Burakov if (rte_lcore_is_enabled(i) && is_hp_core(i)) { 63f88e7c17SRadu Nicolau hp_lcores[nb_hp_lcores] = i; 64f88e7c17SRadu Nicolau nb_hp_lcores++; 65f88e7c17SRadu Nicolau } 66f88e7c17SRadu Nicolau } 67f88e7c17SRadu Nicolau } 68f88e7c17SRadu Nicolau 69f88e7c17SRadu Nicolau /* create a list on non high performance cores*/ 70f88e7c17SRadu Nicolau for (i = 0; i < RTE_MAX_LCORE; i++) { 71f88e7c17SRadu Nicolau if (rte_lcore_is_enabled(i)) { 72f88e7c17SRadu Nicolau int hp = 0; 73f88e7c17SRadu Nicolau for (j = 0; j < nb_hp_lcores; j++) { 74f88e7c17SRadu Nicolau if (hp_lcores[j] == i) { 75f88e7c17SRadu Nicolau hp = 1; 76f88e7c17SRadu Nicolau break; 77f88e7c17SRadu Nicolau } 78f88e7c17SRadu Nicolau } 79f88e7c17SRadu Nicolau if (!hp) 80f88e7c17SRadu Nicolau non_perf_lcores[nb_non_perf_lcores++] = i; 81f88e7c17SRadu Nicolau } 82f88e7c17SRadu Nicolau } 83f88e7c17SRadu Nicolau 84f88e7c17SRadu Nicolau /* update the lcore config */ 85f88e7c17SRadu Nicolau for (i = 0; i < nb_prf_lc_prms; i++) { 86f88e7c17SRadu Nicolau int lcore = -1; 87f88e7c17SRadu Nicolau if (prf_lc_prms[i].high_perf) { 88f88e7c17SRadu Nicolau if (prf_lc_prms[i].lcore_idx < nb_hp_lcores) 89f88e7c17SRadu Nicolau lcore = hp_lcores[prf_lc_prms[i].lcore_idx]; 90f88e7c17SRadu Nicolau } else { 91f88e7c17SRadu Nicolau if (prf_lc_prms[i].lcore_idx < nb_non_perf_lcores) 92f88e7c17SRadu Nicolau lcore = 93f88e7c17SRadu Nicolau non_perf_lcores[prf_lc_prms[i].lcore_idx]; 94f88e7c17SRadu Nicolau } 95f88e7c17SRadu Nicolau 96f88e7c17SRadu Nicolau if (lcore < 0) { 97f88e7c17SRadu Nicolau printf("Performance cores configuration error\n"); 98f88e7c17SRadu Nicolau return -1; 99f88e7c17SRadu Nicolau } 100f88e7c17SRadu Nicolau 101f88e7c17SRadu Nicolau lcore_params_array[i].lcore_id = lcore; 102f88e7c17SRadu Nicolau lcore_params_array[i].queue_id = prf_lc_prms[i].queue_id; 103f88e7c17SRadu Nicolau lcore_params_array[i].port_id = prf_lc_prms[i].port_id; 104f88e7c17SRadu Nicolau } 105f88e7c17SRadu Nicolau 106f88e7c17SRadu Nicolau lcore_params = lcore_params_array; 107f88e7c17SRadu Nicolau nb_lcore_params = nb_prf_lc_prms; 108f88e7c17SRadu Nicolau 109f88e7c17SRadu Nicolau printf("Updated performance core configuration\n"); 110f88e7c17SRadu Nicolau for (i = 0; i < nb_prf_lc_prms; i++) 111f88e7c17SRadu Nicolau printf("\t(%d,%d,%d)\n", lcore_params[i].port_id, 112f88e7c17SRadu Nicolau lcore_params[i].queue_id, 113f88e7c17SRadu Nicolau lcore_params[i].lcore_id); 114f88e7c17SRadu Nicolau 115f88e7c17SRadu Nicolau return 0; 116f88e7c17SRadu Nicolau } 117f88e7c17SRadu Nicolau 118f88e7c17SRadu Nicolau int 119f88e7c17SRadu Nicolau parse_perf_config(const char *q_arg) 120f88e7c17SRadu Nicolau { 121f88e7c17SRadu Nicolau char s[256]; 122f88e7c17SRadu Nicolau const char *p, *p0 = q_arg; 123f88e7c17SRadu Nicolau char *end; 124f88e7c17SRadu Nicolau enum fieldnames { 125f88e7c17SRadu Nicolau FLD_PORT = 0, 126f88e7c17SRadu Nicolau FLD_QUEUE, 127f88e7c17SRadu Nicolau FLD_LCORE_HP, 128f88e7c17SRadu Nicolau FLD_LCORE_IDX, 129f88e7c17SRadu Nicolau _NUM_FLD 130f88e7c17SRadu Nicolau }; 131f88e7c17SRadu Nicolau unsigned long int_fld[_NUM_FLD]; 132f88e7c17SRadu Nicolau char *str_fld[_NUM_FLD]; 133f88e7c17SRadu Nicolau int i; 134f88e7c17SRadu Nicolau unsigned int size; 1354b978938SSivaprasad Tummala unsigned int max_fld[_NUM_FLD] = { 136548de909SSivaprasad Tummala RTE_MAX_ETHPORTS, 1374b978938SSivaprasad Tummala RTE_MAX_QUEUES_PER_PORT, 1384b978938SSivaprasad Tummala 255, 1394b978938SSivaprasad Tummala RTE_MAX_LCORE 1404b978938SSivaprasad Tummala }; 141f88e7c17SRadu Nicolau 142f88e7c17SRadu Nicolau nb_prf_lc_prms = 0; 143f88e7c17SRadu Nicolau 144f88e7c17SRadu Nicolau while ((p = strchr(p0, '(')) != NULL) { 145f88e7c17SRadu Nicolau ++p; 146f88e7c17SRadu Nicolau p0 = strchr(p, ')'); 147f88e7c17SRadu Nicolau if (p0 == NULL) 148f88e7c17SRadu Nicolau return -1; 149f88e7c17SRadu Nicolau 150f88e7c17SRadu Nicolau size = p0 - p; 151f88e7c17SRadu Nicolau if (size >= sizeof(s)) 152f88e7c17SRadu Nicolau return -1; 153f88e7c17SRadu Nicolau 154f88e7c17SRadu Nicolau snprintf(s, sizeof(s), "%.*s", size, p); 155f88e7c17SRadu Nicolau if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 156f88e7c17SRadu Nicolau _NUM_FLD) 157f88e7c17SRadu Nicolau return -1; 158f88e7c17SRadu Nicolau for (i = 0; i < _NUM_FLD; i++) { 159f88e7c17SRadu Nicolau errno = 0; 160f88e7c17SRadu Nicolau int_fld[i] = strtoul(str_fld[i], &end, 0); 161b23c5bd7SSivaprasad Tummala if (errno != 0 || end == str_fld[i] || int_fld[i] > max_fld[i]) 162b23c5bd7SSivaprasad Tummala 163f88e7c17SRadu Nicolau return -1; 164f88e7c17SRadu Nicolau } 165f88e7c17SRadu Nicolau if (nb_prf_lc_prms >= MAX_LCORE_PARAMS) { 166f88e7c17SRadu Nicolau printf("exceeded max number of lcore params: %hu\n", 167f88e7c17SRadu Nicolau nb_prf_lc_prms); 168f88e7c17SRadu Nicolau return -1; 169f88e7c17SRadu Nicolau } 170f88e7c17SRadu Nicolau prf_lc_prms[nb_prf_lc_prms].port_id = 171548de909SSivaprasad Tummala (uint16_t)int_fld[FLD_PORT]; 172f88e7c17SRadu Nicolau prf_lc_prms[nb_prf_lc_prms].queue_id = 173b23c5bd7SSivaprasad Tummala (uint16_t)int_fld[FLD_QUEUE]; 174f88e7c17SRadu Nicolau prf_lc_prms[nb_prf_lc_prms].high_perf = 175f88e7c17SRadu Nicolau !!(uint8_t)int_fld[FLD_LCORE_HP]; 176f88e7c17SRadu Nicolau prf_lc_prms[nb_prf_lc_prms].lcore_idx = 1774b978938SSivaprasad Tummala (uint32_t)int_fld[FLD_LCORE_IDX]; 178f88e7c17SRadu Nicolau ++nb_prf_lc_prms; 179f88e7c17SRadu Nicolau } 180f88e7c17SRadu Nicolau 181f88e7c17SRadu Nicolau return 0; 182f88e7c17SRadu Nicolau } 183f88e7c17SRadu Nicolau 184f88e7c17SRadu Nicolau int 185f88e7c17SRadu Nicolau parse_perf_core_list(const char *corelist) 186f88e7c17SRadu Nicolau { 187f88e7c17SRadu Nicolau int i, idx = 0; 188f88e7c17SRadu Nicolau unsigned int count = 0; 189f88e7c17SRadu Nicolau char *end = NULL; 190f88e7c17SRadu Nicolau int min, max; 191f88e7c17SRadu Nicolau 192f88e7c17SRadu Nicolau if (corelist == NULL) { 193f88e7c17SRadu Nicolau printf("invalid core list\n"); 194f88e7c17SRadu Nicolau return -1; 195f88e7c17SRadu Nicolau } 196f88e7c17SRadu Nicolau 197f88e7c17SRadu Nicolau 198f88e7c17SRadu Nicolau /* Remove all blank characters ahead and after */ 199f88e7c17SRadu Nicolau while (isblank(*corelist)) 200f88e7c17SRadu Nicolau corelist++; 201f88e7c17SRadu Nicolau i = strlen(corelist); 202f88e7c17SRadu Nicolau while ((i > 0) && isblank(corelist[i - 1])) 203f88e7c17SRadu Nicolau i--; 204f88e7c17SRadu Nicolau 205f88e7c17SRadu Nicolau /* Get list of cores */ 206f88e7c17SRadu Nicolau min = RTE_MAX_LCORE; 207f88e7c17SRadu Nicolau do { 208f88e7c17SRadu Nicolau while (isblank(*corelist)) 209f88e7c17SRadu Nicolau corelist++; 210f88e7c17SRadu Nicolau if (*corelist == '\0') 211f88e7c17SRadu Nicolau return -1; 212f88e7c17SRadu Nicolau errno = 0; 213f88e7c17SRadu Nicolau idx = strtoul(corelist, &end, 10); 214f88e7c17SRadu Nicolau if (errno || end == NULL) 215f88e7c17SRadu Nicolau return -1; 216f88e7c17SRadu Nicolau while (isblank(*end)) 217f88e7c17SRadu Nicolau end++; 218f88e7c17SRadu Nicolau if (*end == '-') { 219f88e7c17SRadu Nicolau min = idx; 220f88e7c17SRadu Nicolau } else if ((*end == ',') || (*end == '\0')) { 221f88e7c17SRadu Nicolau max = idx; 222f88e7c17SRadu Nicolau if (min == RTE_MAX_LCORE) 223f88e7c17SRadu Nicolau min = idx; 224f88e7c17SRadu Nicolau for (idx = min; idx <= max; idx++) { 225f88e7c17SRadu Nicolau hp_lcores[count] = idx; 226f88e7c17SRadu Nicolau count++; 227f88e7c17SRadu Nicolau } 228f88e7c17SRadu Nicolau min = RTE_MAX_LCORE; 229f88e7c17SRadu Nicolau } else { 230f88e7c17SRadu Nicolau printf("invalid core list\n"); 231f88e7c17SRadu Nicolau return -1; 232f88e7c17SRadu Nicolau } 233f88e7c17SRadu Nicolau corelist = end + 1; 234f88e7c17SRadu Nicolau } while (*end != '\0'); 235f88e7c17SRadu Nicolau 236f88e7c17SRadu Nicolau if (count == 0) { 237f88e7c17SRadu Nicolau printf("invalid core list\n"); 238f88e7c17SRadu Nicolau return -1; 239f88e7c17SRadu Nicolau } 240f88e7c17SRadu Nicolau 241f88e7c17SRadu Nicolau nb_hp_lcores = count; 242f88e7c17SRadu Nicolau 243f88e7c17SRadu Nicolau printf("Configured %d high performance cores\n", nb_hp_lcores); 244f88e7c17SRadu Nicolau for (i = 0; i < nb_hp_lcores; i++) 245f88e7c17SRadu Nicolau printf("\tHigh performance core %d %d\n", 246f88e7c17SRadu Nicolau i, hp_lcores[i]); 247f88e7c17SRadu Nicolau 248f88e7c17SRadu Nicolau return 0; 249f88e7c17SRadu Nicolau } 250