xref: /dpdk/examples/l3fwd-power/perf_core.c (revision f30a1bbd63f494f5ba623582d7e9166c817794a4)
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