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