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