xref: /dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c (revision b462f2737eb08b07b84da4204fbd1c9b9ba00b2d)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3f5e5c334SAlan Carew  */
4f5e5c334SAlan Carew 
5f5e5c334SAlan Carew 
6f5e5c334SAlan Carew #include <stdint.h>
7f5e5c334SAlan Carew #include <string.h>
8f5e5c334SAlan Carew #include <stdio.h>
9f5e5c334SAlan Carew #include <termios.h>
10f5e5c334SAlan Carew 
11f5e5c334SAlan Carew #include <cmdline_rdline.h>
12f5e5c334SAlan Carew #include <cmdline_parse.h>
13f5e5c334SAlan Carew #include <cmdline_parse_string.h>
14f5e5c334SAlan Carew #include <cmdline_parse_num.h>
15f5e5c334SAlan Carew #include <cmdline_socket.h>
16f5e5c334SAlan Carew #include <cmdline.h>
17f5e5c334SAlan Carew #include <rte_log.h>
18f5e5c334SAlan Carew #include <rte_lcore.h>
1988a81aa4SRory Sexton #include <rte_ethdev.h>
20f5e5c334SAlan Carew 
21f30a1bbdSSivaprasad Tummala #include <rte_power_cpufreq.h>
22*b462f273SDavid Marchand #include <rte_power_guest_channel.h>
23f5e5c334SAlan Carew 
24f5e5c334SAlan Carew #include "vm_power_cli_guest.h"
25f5e5c334SAlan Carew 
26f5e5c334SAlan Carew 
27f5e5c334SAlan Carew #define CHANNEL_PATH "/dev/virtio-ports/virtio.serial.port.poweragent"
28f5e5c334SAlan Carew 
29f5e5c334SAlan Carew 
30a21f995bSMarcin Hajkowski #define RTE_LOGTYPE_GUEST_CLI RTE_LOGTYPE_USER1
31f5e5c334SAlan Carew 
32f5e5c334SAlan Carew struct cmd_quit_result {
33f5e5c334SAlan Carew 	cmdline_fixed_string_t quit;
34f5e5c334SAlan Carew };
35f5e5c334SAlan Carew 
3659287933SDavid Hunt union PFID {
376d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
3859287933SDavid Hunt 	uint64_t pfid;
3959287933SDavid Hunt };
4059287933SDavid Hunt 
41bd5b6720SBruce Richardson static struct rte_power_channel_packet policy;
4259287933SDavid Hunt 
43bd5b6720SBruce Richardson struct rte_power_channel_packet *
4459287933SDavid Hunt get_policy(void)
4559287933SDavid Hunt {
4659287933SDavid Hunt 	return &policy;
4759287933SDavid Hunt }
4859287933SDavid Hunt 
4959287933SDavid Hunt int
5059287933SDavid Hunt set_policy_mac(int port, int idx)
5159287933SDavid Hunt {
52bd5b6720SBruce Richardson 	struct rte_power_channel_packet *policy;
5359287933SDavid Hunt 	union PFID pfid;
5470febdcfSIgor Romanov 	int ret;
5559287933SDavid Hunt 
5659287933SDavid Hunt 	/* Use port MAC address as the vfid */
5770febdcfSIgor Romanov 	ret = rte_eth_macaddr_get(port, &pfid.addr);
588532effdSFerruh Yigit 	if (ret != 0) {
5970febdcfSIgor Romanov 		printf("Failed to get device (port %u) MAC address: %s\n",
608532effdSFerruh Yigit 				port, rte_strerror(-ret));
618532effdSFerruh Yigit 		return ret;
6270febdcfSIgor Romanov 	}
6359287933SDavid Hunt 
6459287933SDavid Hunt 	printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":"
6559287933SDavid Hunt 			"%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n",
66a7db3afcSAman Deep Singh 			port, RTE_ETHER_ADDR_BYTES(&pfid.addr));
6759287933SDavid Hunt 	policy = get_policy();
6859287933SDavid Hunt 	policy->vfid[idx] = pfid.pfid;
6959287933SDavid Hunt 	return 0;
7059287933SDavid Hunt }
7159287933SDavid Hunt 
7270febdcfSIgor Romanov int
73bd5b6720SBruce Richardson set_policy_defaults(struct rte_power_channel_packet *pkt)
7459287933SDavid Hunt {
7570febdcfSIgor Romanov 	int ret;
7670febdcfSIgor Romanov 
7770febdcfSIgor Romanov 	ret = set_policy_mac(0, 0);
7870febdcfSIgor Romanov 	if (ret != 0)
790f2f911dSDavid Hunt 		pkt->nb_mac_to_monitor = 0;
800f2f911dSDavid Hunt 	else
8159287933SDavid Hunt 		pkt->nb_mac_to_monitor = 1;
8259287933SDavid Hunt 
8359287933SDavid Hunt 	pkt->t_boost_status.tbEnabled = false;
8459287933SDavid Hunt 
8559287933SDavid Hunt 	pkt->vcpu_to_control[0] = 0;
8659287933SDavid Hunt 	pkt->vcpu_to_control[1] = 1;
8759287933SDavid Hunt 	pkt->num_vcpu = 2;
8859287933SDavid Hunt 	/* Dummy Population. */
8959287933SDavid Hunt 	pkt->traffic_policy.min_packet_thresh = 96000;
9059287933SDavid Hunt 	pkt->traffic_policy.avg_max_packet_thresh = 1800000;
9159287933SDavid Hunt 	pkt->traffic_policy.max_max_packet_thresh = 2000000;
9259287933SDavid Hunt 
9359287933SDavid Hunt 	pkt->timer_policy.busy_hours[0] = 3;
9459287933SDavid Hunt 	pkt->timer_policy.busy_hours[1] = 4;
9559287933SDavid Hunt 	pkt->timer_policy.busy_hours[2] = 5;
9659287933SDavid Hunt 	pkt->timer_policy.quiet_hours[0] = 11;
9759287933SDavid Hunt 	pkt->timer_policy.quiet_hours[1] = 12;
9859287933SDavid Hunt 	pkt->timer_policy.quiet_hours[2] = 13;
9959287933SDavid Hunt 
10059287933SDavid Hunt 	pkt->timer_policy.hours_to_use_traffic_profile[0] = 8;
10159287933SDavid Hunt 	pkt->timer_policy.hours_to_use_traffic_profile[1] = 10;
10259287933SDavid Hunt 
10338d232b9SBruce Richardson 	pkt->core_type = RTE_POWER_CORE_TYPE_VIRTUAL;
10438d232b9SBruce Richardson 	pkt->workload = RTE_POWER_WL_LOW;
10538d232b9SBruce Richardson 	pkt->policy_to_use = RTE_POWER_POLICY_TIME;
10638d232b9SBruce Richardson 	pkt->command = RTE_POWER_PKT_POLICY;
1070e8f4749SMarcin Hajkowski 	strlcpy(pkt->vm_name, "ubuntu2", sizeof(pkt->vm_name));
1088532effdSFerruh Yigit 
1098532effdSFerruh Yigit 	return 0;
11059287933SDavid Hunt }
11159287933SDavid Hunt 
1120e8f4749SMarcin Hajkowski static void cmd_quit_parsed(__rte_unused void *parsed_result,
1130e8f4749SMarcin Hajkowski 		__rte_unused struct cmdline *cl,
1140e8f4749SMarcin Hajkowski 		__rte_unused void *data)
115f5e5c334SAlan Carew {
116f5e5c334SAlan Carew 	unsigned lcore_id;
117f5e5c334SAlan Carew 
118f5e5c334SAlan Carew 	RTE_LCORE_FOREACH(lcore_id) {
119f5e5c334SAlan Carew 		rte_power_exit(lcore_id);
120f5e5c334SAlan Carew 	}
121f5e5c334SAlan Carew 	cmdline_quit(cl);
122f5e5c334SAlan Carew }
123f5e5c334SAlan Carew 
124f5e5c334SAlan Carew cmdline_parse_token_string_t cmd_quit_quit =
125f5e5c334SAlan Carew 	TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
126f5e5c334SAlan Carew 
127f5e5c334SAlan Carew cmdline_parse_inst_t cmd_quit = {
128f5e5c334SAlan Carew 	.f = cmd_quit_parsed,  /* function to call */
129f5e5c334SAlan Carew 	.data = NULL,      /* 2nd arg of func */
130f5e5c334SAlan Carew 	.help_str = "close the application",
131f5e5c334SAlan Carew 	.tokens = {        /* token list, NULL terminated */
132f5e5c334SAlan Carew 		(void *)&cmd_quit_quit,
133f5e5c334SAlan Carew 		NULL,
134f5e5c334SAlan Carew 	},
135f5e5c334SAlan Carew };
136f5e5c334SAlan Carew 
137f5e5c334SAlan Carew /* *** VM operations *** */
138f5e5c334SAlan Carew 
1390e8f4749SMarcin Hajkowski struct cmd_freq_list_result {
1400e8f4749SMarcin Hajkowski 	cmdline_fixed_string_t query_freq;
1410e8f4749SMarcin Hajkowski 	cmdline_fixed_string_t cpu_num;
1420e8f4749SMarcin Hajkowski };
1430e8f4749SMarcin Hajkowski 
1440e8f4749SMarcin Hajkowski static int
145bd5b6720SBruce Richardson query_data(struct rte_power_channel_packet *pkt, unsigned int lcore_id)
1460e8f4749SMarcin Hajkowski {
1470e8f4749SMarcin Hajkowski 	int ret;
1480e8f4749SMarcin Hajkowski 	ret = rte_power_guest_channel_send_msg(pkt, lcore_id);
1490e8f4749SMarcin Hajkowski 	if (ret < 0) {
1500e8f4749SMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Error sending message.\n");
1510e8f4749SMarcin Hajkowski 		return -1;
1520e8f4749SMarcin Hajkowski 	}
1530e8f4749SMarcin Hajkowski 	return 0;
1540e8f4749SMarcin Hajkowski }
1550e8f4749SMarcin Hajkowski 
1560e8f4749SMarcin Hajkowski static int
157bd5b6720SBruce Richardson receive_freq_list(struct rte_power_channel_packet_freq_list *pkt_freq_list,
1580e8f4749SMarcin Hajkowski 		unsigned int lcore_id)
1590e8f4749SMarcin Hajkowski {
1600e8f4749SMarcin Hajkowski 	int ret;
1610e8f4749SMarcin Hajkowski 
1620e8f4749SMarcin Hajkowski 	ret = rte_power_guest_channel_receive_msg(pkt_freq_list,
163bd5b6720SBruce Richardson 			sizeof(*pkt_freq_list),
1640e8f4749SMarcin Hajkowski 			lcore_id);
1650e8f4749SMarcin Hajkowski 	if (ret < 0) {
1660e8f4749SMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
1670e8f4749SMarcin Hajkowski 		return -1;
1680e8f4749SMarcin Hajkowski 	}
16938d232b9SBruce Richardson 	if (pkt_freq_list->command != RTE_POWER_FREQ_LIST) {
1700e8f4749SMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
1710e8f4749SMarcin Hajkowski 		return -1;
1720e8f4749SMarcin Hajkowski 	}
1730e8f4749SMarcin Hajkowski 	return 0;
1740e8f4749SMarcin Hajkowski }
1750e8f4749SMarcin Hajkowski 
1760e8f4749SMarcin Hajkowski static void
1770e8f4749SMarcin Hajkowski cmd_query_freq_list_parsed(void *parsed_result,
1780e8f4749SMarcin Hajkowski 		__rte_unused struct cmdline *cl,
1790e8f4749SMarcin Hajkowski 		__rte_unused void *data)
1800e8f4749SMarcin Hajkowski {
1810e8f4749SMarcin Hajkowski 	struct cmd_freq_list_result *res = parsed_result;
1820e8f4749SMarcin Hajkowski 	unsigned int lcore_id;
183bd5b6720SBruce Richardson 	struct rte_power_channel_packet_freq_list pkt_freq_list;
184bd5b6720SBruce Richardson 	struct rte_power_channel_packet pkt;
1850e8f4749SMarcin Hajkowski 	bool query_list = false;
1860e8f4749SMarcin Hajkowski 	int ret;
1870e8f4749SMarcin Hajkowski 	char *ep;
1880e8f4749SMarcin Hajkowski 
189bd5b6720SBruce Richardson 	memset(&pkt, 0, sizeof(pkt));
190bd5b6720SBruce Richardson 	memset(&pkt_freq_list, 0, sizeof(pkt_freq_list));
1910e8f4749SMarcin Hajkowski 
1920e8f4749SMarcin Hajkowski 	if (!strcmp(res->cpu_num, "all")) {
1930e8f4749SMarcin Hajkowski 
1940e8f4749SMarcin Hajkowski 		/* Get first enabled lcore. */
1950e8f4749SMarcin Hajkowski 		lcore_id = rte_get_next_lcore(-1,
1960e8f4749SMarcin Hajkowski 				0,
1970e8f4749SMarcin Hajkowski 				0);
1980e8f4749SMarcin Hajkowski 		if (lcore_id == RTE_MAX_LCORE) {
1990e8f4749SMarcin Hajkowski 			cmdline_printf(cl, "Enabled core not found.\n");
2000e8f4749SMarcin Hajkowski 			return;
2010e8f4749SMarcin Hajkowski 		}
2020e8f4749SMarcin Hajkowski 
20338d232b9SBruce Richardson 		pkt.command = RTE_POWER_QUERY_FREQ_LIST;
2040e8f4749SMarcin Hajkowski 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
2050e8f4749SMarcin Hajkowski 		query_list = true;
2060e8f4749SMarcin Hajkowski 	} else {
2070e8f4749SMarcin Hajkowski 		errno = 0;
2080e8f4749SMarcin Hajkowski 		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
20938d232b9SBruce Richardson 		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
2100e8f4749SMarcin Hajkowski 			ep == res->cpu_num) {
2110e8f4749SMarcin Hajkowski 			cmdline_printf(cl, "Invalid parameter provided.\n");
2120e8f4749SMarcin Hajkowski 			return;
2130e8f4749SMarcin Hajkowski 		}
21438d232b9SBruce Richardson 		pkt.command = RTE_POWER_QUERY_FREQ;
2150e8f4749SMarcin Hajkowski 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
2160e8f4749SMarcin Hajkowski 		pkt.resource_id = lcore_id;
2170e8f4749SMarcin Hajkowski 	}
2180e8f4749SMarcin Hajkowski 
21907525d1aSMarcin Hajkowski 	ret = query_data(&pkt, lcore_id);
2200e8f4749SMarcin Hajkowski 	if (ret < 0) {
2210e8f4749SMarcin Hajkowski 		cmdline_printf(cl, "Error during sending frequency list query.\n");
2220e8f4749SMarcin Hajkowski 		return;
2230e8f4749SMarcin Hajkowski 	}
2240e8f4749SMarcin Hajkowski 
2250e8f4749SMarcin Hajkowski 	ret = receive_freq_list(&pkt_freq_list, lcore_id);
2260e8f4749SMarcin Hajkowski 	if (ret < 0) {
2270e8f4749SMarcin Hajkowski 		cmdline_printf(cl, "Error during frequency list reception.\n");
2280e8f4749SMarcin Hajkowski 		return;
2290e8f4749SMarcin Hajkowski 	}
2300e8f4749SMarcin Hajkowski 	if (query_list) {
2310e8f4749SMarcin Hajkowski 		unsigned int i;
2320e8f4749SMarcin Hajkowski 		for (i = 0; i < pkt_freq_list.num_vcpu; ++i)
2330e8f4749SMarcin Hajkowski 			cmdline_printf(cl, "Frequency of [%d] vcore is %d.\n",
2340e8f4749SMarcin Hajkowski 					i,
2350e8f4749SMarcin Hajkowski 					pkt_freq_list.freq_list[i]);
2360e8f4749SMarcin Hajkowski 	} else {
2370e8f4749SMarcin Hajkowski 		cmdline_printf(cl, "Frequency of [%d] vcore is %d.\n",
2380e8f4749SMarcin Hajkowski 				lcore_id,
2390e8f4749SMarcin Hajkowski 				pkt_freq_list.freq_list[lcore_id]);
2400e8f4749SMarcin Hajkowski 	}
2410e8f4749SMarcin Hajkowski }
2420e8f4749SMarcin Hajkowski 
2430e8f4749SMarcin Hajkowski cmdline_parse_token_string_t cmd_query_freq_token =
2440e8f4749SMarcin Hajkowski 	TOKEN_STRING_INITIALIZER(struct cmd_freq_list_result, query_freq, "query_cpu_freq");
2450e8f4749SMarcin Hajkowski cmdline_parse_token_string_t cmd_query_freq_cpu_num_token =
2460e8f4749SMarcin Hajkowski 	TOKEN_STRING_INITIALIZER(struct cmd_freq_list_result, cpu_num, NULL);
2470e8f4749SMarcin Hajkowski 
2480e8f4749SMarcin Hajkowski cmdline_parse_inst_t cmd_query_freq_list = {
2490e8f4749SMarcin Hajkowski 	.f = cmd_query_freq_list_parsed,  /* function to call */
2500e8f4749SMarcin Hajkowski 	.data = NULL,      /* 2nd arg of func */
2510e8f4749SMarcin Hajkowski 	.help_str = "query_cpu_freq <core_num>|all, request"
2520e8f4749SMarcin Hajkowski 				" information regarding virtual core frequencies."
2530e8f4749SMarcin Hajkowski 				" The keyword 'all' will query list of all vcores for the VM",
2540e8f4749SMarcin Hajkowski 	.tokens = {        /* token list, NULL terminated */
2550e8f4749SMarcin Hajkowski 		(void *)&cmd_query_freq_token,
2560e8f4749SMarcin Hajkowski 		(void *)&cmd_query_freq_cpu_num_token,
2570e8f4749SMarcin Hajkowski 		NULL,
2580e8f4749SMarcin Hajkowski 	},
259f5e5c334SAlan Carew };
260f5e5c334SAlan Carew 
26107525d1aSMarcin Hajkowski struct cmd_query_caps_result {
26207525d1aSMarcin Hajkowski 	cmdline_fixed_string_t query_caps;
26307525d1aSMarcin Hajkowski 	cmdline_fixed_string_t cpu_num;
26407525d1aSMarcin Hajkowski };
26507525d1aSMarcin Hajkowski 
26607525d1aSMarcin Hajkowski static int
267bd5b6720SBruce Richardson receive_capabilities(struct rte_power_channel_packet_caps_list *pkt_caps_list,
26807525d1aSMarcin Hajkowski 		unsigned int lcore_id)
26907525d1aSMarcin Hajkowski {
27007525d1aSMarcin Hajkowski 	int ret;
27107525d1aSMarcin Hajkowski 
27207525d1aSMarcin Hajkowski 	ret = rte_power_guest_channel_receive_msg(pkt_caps_list,
273bd5b6720SBruce Richardson 		sizeof(*pkt_caps_list),
27407525d1aSMarcin Hajkowski 		lcore_id);
27507525d1aSMarcin Hajkowski 	if (ret < 0) {
27607525d1aSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
27707525d1aSMarcin Hajkowski 		return -1;
27807525d1aSMarcin Hajkowski 	}
27938d232b9SBruce Richardson 	if (pkt_caps_list->command != RTE_POWER_CAPS_LIST) {
28007525d1aSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
28107525d1aSMarcin Hajkowski 		return -1;
28207525d1aSMarcin Hajkowski 	}
28307525d1aSMarcin Hajkowski 	return 0;
28407525d1aSMarcin Hajkowski }
28507525d1aSMarcin Hajkowski 
28607525d1aSMarcin Hajkowski static void
28707525d1aSMarcin Hajkowski cmd_query_caps_list_parsed(void *parsed_result,
28807525d1aSMarcin Hajkowski 		__rte_unused struct cmdline *cl,
28907525d1aSMarcin Hajkowski 		__rte_unused void *data)
29007525d1aSMarcin Hajkowski {
29107525d1aSMarcin Hajkowski 	struct cmd_query_caps_result *res = parsed_result;
29207525d1aSMarcin Hajkowski 	unsigned int lcore_id;
293bd5b6720SBruce Richardson 	struct rte_power_channel_packet_caps_list pkt_caps_list;
294bd5b6720SBruce Richardson 	struct rte_power_channel_packet pkt;
29507525d1aSMarcin Hajkowski 	bool query_list = false;
29607525d1aSMarcin Hajkowski 	int ret;
29707525d1aSMarcin Hajkowski 	char *ep;
29807525d1aSMarcin Hajkowski 
299bd5b6720SBruce Richardson 	memset(&pkt, 0, sizeof(pkt));
300bd5b6720SBruce Richardson 	memset(&pkt_caps_list, 0, sizeof(pkt_caps_list));
30107525d1aSMarcin Hajkowski 
30207525d1aSMarcin Hajkowski 	if (!strcmp(res->cpu_num, "all")) {
30307525d1aSMarcin Hajkowski 
30407525d1aSMarcin Hajkowski 		/* Get first enabled lcore. */
30507525d1aSMarcin Hajkowski 		lcore_id = rte_get_next_lcore(-1,
30607525d1aSMarcin Hajkowski 				0,
30707525d1aSMarcin Hajkowski 				0);
30807525d1aSMarcin Hajkowski 		if (lcore_id == RTE_MAX_LCORE) {
30907525d1aSMarcin Hajkowski 			cmdline_printf(cl, "Enabled core not found.\n");
31007525d1aSMarcin Hajkowski 			return;
31107525d1aSMarcin Hajkowski 		}
31207525d1aSMarcin Hajkowski 
31338d232b9SBruce Richardson 		pkt.command = RTE_POWER_QUERY_CAPS_LIST;
31407525d1aSMarcin Hajkowski 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
31507525d1aSMarcin Hajkowski 		query_list = true;
31607525d1aSMarcin Hajkowski 	} else {
31707525d1aSMarcin Hajkowski 		errno = 0;
31807525d1aSMarcin Hajkowski 		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
31938d232b9SBruce Richardson 		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
32007525d1aSMarcin Hajkowski 			ep == res->cpu_num) {
32107525d1aSMarcin Hajkowski 			cmdline_printf(cl, "Invalid parameter provided.\n");
32207525d1aSMarcin Hajkowski 			return;
32307525d1aSMarcin Hajkowski 		}
32438d232b9SBruce Richardson 		pkt.command = RTE_POWER_QUERY_CAPS;
32507525d1aSMarcin Hajkowski 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
32607525d1aSMarcin Hajkowski 		pkt.resource_id = lcore_id;
32707525d1aSMarcin Hajkowski 	}
32807525d1aSMarcin Hajkowski 
32907525d1aSMarcin Hajkowski 	ret = query_data(&pkt, lcore_id);
33007525d1aSMarcin Hajkowski 	if (ret < 0) {
33107525d1aSMarcin Hajkowski 		cmdline_printf(cl, "Error during sending capabilities query.\n");
33207525d1aSMarcin Hajkowski 		return;
33307525d1aSMarcin Hajkowski 	}
33407525d1aSMarcin Hajkowski 
33507525d1aSMarcin Hajkowski 	ret = receive_capabilities(&pkt_caps_list, lcore_id);
33607525d1aSMarcin Hajkowski 	if (ret < 0) {
33707525d1aSMarcin Hajkowski 		cmdline_printf(cl, "Error during capabilities reception.\n");
33807525d1aSMarcin Hajkowski 		return;
33907525d1aSMarcin Hajkowski 	}
34007525d1aSMarcin Hajkowski 	if (query_list) {
34107525d1aSMarcin Hajkowski 		unsigned int i;
34207525d1aSMarcin Hajkowski 		for (i = 0; i < pkt_caps_list.num_vcpu; ++i)
34307525d1aSMarcin Hajkowski 			cmdline_printf(cl, "Capabilities of [%d] vcore are:"
344984d99ccSFerruh Yigit 					" turbo possibility: %" PRId64 ", "
345984d99ccSFerruh Yigit 					"is priority core: %" PRId64 ".\n",
34607525d1aSMarcin Hajkowski 					i,
34707525d1aSMarcin Hajkowski 					pkt_caps_list.turbo[i],
34807525d1aSMarcin Hajkowski 					pkt_caps_list.priority[i]);
34907525d1aSMarcin Hajkowski 	} else {
35007525d1aSMarcin Hajkowski 		cmdline_printf(cl, "Capabilities of [%d] vcore are:"
351984d99ccSFerruh Yigit 				" turbo possibility: %" PRId64 ", "
352984d99ccSFerruh Yigit 				"is priority core: %" PRId64 ".\n",
35307525d1aSMarcin Hajkowski 				lcore_id,
35407525d1aSMarcin Hajkowski 				pkt_caps_list.turbo[lcore_id],
35507525d1aSMarcin Hajkowski 				pkt_caps_list.priority[lcore_id]);
35607525d1aSMarcin Hajkowski 	}
35707525d1aSMarcin Hajkowski }
35807525d1aSMarcin Hajkowski 
35907525d1aSMarcin Hajkowski cmdline_parse_token_string_t cmd_query_caps_token =
36007525d1aSMarcin Hajkowski 	TOKEN_STRING_INITIALIZER(struct cmd_query_caps_result, query_caps, "query_cpu_caps");
36107525d1aSMarcin Hajkowski cmdline_parse_token_string_t cmd_query_caps_cpu_num_token =
36207525d1aSMarcin Hajkowski 	TOKEN_STRING_INITIALIZER(struct cmd_query_caps_result, cpu_num, NULL);
36307525d1aSMarcin Hajkowski 
36407525d1aSMarcin Hajkowski cmdline_parse_inst_t cmd_query_caps_list = {
36507525d1aSMarcin Hajkowski 	.f = cmd_query_caps_list_parsed,  /* function to call */
36607525d1aSMarcin Hajkowski 	.data = NULL,      /* 2nd arg of func */
36707525d1aSMarcin Hajkowski 	.help_str = "query_cpu_caps <core_num>|all, request"
36807525d1aSMarcin Hajkowski 				" information regarding virtual core capabilities."
36907525d1aSMarcin Hajkowski 				" The keyword 'all' will query list of all vcores for the VM",
37007525d1aSMarcin Hajkowski 	.tokens = {        /* token list, NULL terminated */
37107525d1aSMarcin Hajkowski 		(void *)&cmd_query_caps_token,
37207525d1aSMarcin Hajkowski 		(void *)&cmd_query_caps_cpu_num_token,
37307525d1aSMarcin Hajkowski 		NULL,
37407525d1aSMarcin Hajkowski 	},
37507525d1aSMarcin Hajkowski };
37607525d1aSMarcin Hajkowski 
377a21f995bSMarcin Hajkowski static int
378a21f995bSMarcin Hajkowski check_response_cmd(unsigned int lcore_id, int *result)
379a21f995bSMarcin Hajkowski {
380bd5b6720SBruce Richardson 	struct rte_power_channel_packet pkt;
381a21f995bSMarcin Hajkowski 	int ret;
382a21f995bSMarcin Hajkowski 
38304a8cb8eSMarcin Hajkowski 	ret = rte_power_guest_channel_receive_msg(&pkt, sizeof pkt, lcore_id);
384a21f995bSMarcin Hajkowski 	if (ret < 0)
385a21f995bSMarcin Hajkowski 		return -1;
386a21f995bSMarcin Hajkowski 
387a21f995bSMarcin Hajkowski 	switch (pkt.command) {
38838d232b9SBruce Richardson 	case(RTE_POWER_CMD_ACK):
389a21f995bSMarcin Hajkowski 		*result = 1;
390a21f995bSMarcin Hajkowski 		break;
39138d232b9SBruce Richardson 	case(RTE_POWER_CMD_NACK):
392a21f995bSMarcin Hajkowski 		*result = 0;
393a21f995bSMarcin Hajkowski 		break;
394a21f995bSMarcin Hajkowski 	default:
395a21f995bSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI,
396a21f995bSMarcin Hajkowski 				"Received invalid response from host, expecting ACK/NACK.\n");
397a21f995bSMarcin Hajkowski 		return -1;
398a21f995bSMarcin Hajkowski 	}
399a21f995bSMarcin Hajkowski 
400a21f995bSMarcin Hajkowski 	return 0;
401a21f995bSMarcin Hajkowski }
402a21f995bSMarcin Hajkowski 
4030e8f4749SMarcin Hajkowski struct cmd_set_cpu_freq_result {
4040e8f4749SMarcin Hajkowski 	cmdline_fixed_string_t set_cpu_freq;
4054b978938SSivaprasad Tummala 	uint32_t lcore_id;
4060e8f4749SMarcin Hajkowski 	cmdline_fixed_string_t cmd;
4070e8f4749SMarcin Hajkowski };
4080e8f4749SMarcin Hajkowski 
409f5e5c334SAlan Carew static void
410f5e5c334SAlan Carew cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
4110e8f4749SMarcin Hajkowski 	       __rte_unused void *data)
412f5e5c334SAlan Carew {
413f5e5c334SAlan Carew 	int ret = -1;
414f5e5c334SAlan Carew 	struct cmd_set_cpu_freq_result *res = parsed_result;
415f5e5c334SAlan Carew 
416f5e5c334SAlan Carew 	if (!strcmp(res->cmd, "up"))
417f5e5c334SAlan Carew 		ret = rte_power_freq_up(res->lcore_id);
418f5e5c334SAlan Carew 	else if (!strcmp(res->cmd, "down"))
419f5e5c334SAlan Carew 		ret = rte_power_freq_down(res->lcore_id);
420f5e5c334SAlan Carew 	else if (!strcmp(res->cmd, "min"))
421f5e5c334SAlan Carew 		ret = rte_power_freq_min(res->lcore_id);
422f5e5c334SAlan Carew 	else if (!strcmp(res->cmd, "max"))
423f5e5c334SAlan Carew 		ret = rte_power_freq_max(res->lcore_id);
424d191f085SDavid Hunt 	else if (!strcmp(res->cmd, "enable_turbo"))
425d191f085SDavid Hunt 		ret = rte_power_freq_enable_turbo(res->lcore_id);
426d191f085SDavid Hunt 	else if (!strcmp(res->cmd, "disable_turbo"))
427d191f085SDavid Hunt 		ret = rte_power_freq_disable_turbo(res->lcore_id);
428a21f995bSMarcin Hajkowski 
429a21f995bSMarcin Hajkowski 	if (ret != 1) {
430f5e5c334SAlan Carew 		cmdline_printf(cl, "Error sending message: %s\n", strerror(ret));
431a21f995bSMarcin Hajkowski 		return;
432a21f995bSMarcin Hajkowski 	}
433a21f995bSMarcin Hajkowski 	int result;
434a21f995bSMarcin Hajkowski 	ret = check_response_cmd(res->lcore_id, &result);
435a21f995bSMarcin Hajkowski 	if (ret < 0) {
436a21f995bSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "No confirmation for sent message received\n");
437a21f995bSMarcin Hajkowski 	} else {
438a21f995bSMarcin Hajkowski 		cmdline_printf(cl, "%s received for message sent to host.\n",
439a21f995bSMarcin Hajkowski 				result == 1 ? "ACK" : "NACK");
440a21f995bSMarcin Hajkowski 	}
441f5e5c334SAlan Carew }
442f5e5c334SAlan Carew 
443f5e5c334SAlan Carew cmdline_parse_token_string_t cmd_set_cpu_freq =
444f5e5c334SAlan Carew 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
445f5e5c334SAlan Carew 			set_cpu_freq, "set_cpu_freq");
44699dc0144SBruce Richardson cmdline_parse_token_num_t cmd_set_cpu_freq_core_num =
447f5e5c334SAlan Carew 	TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result,
4484b978938SSivaprasad Tummala 			lcore_id, RTE_UINT32);
449f5e5c334SAlan Carew cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd =
450f5e5c334SAlan Carew 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
451d191f085SDavid Hunt 			cmd, "up#down#min#max#enable_turbo#disable_turbo");
452f5e5c334SAlan Carew 
453f5e5c334SAlan Carew cmdline_parse_inst_t cmd_set_cpu_freq_set = {
454f5e5c334SAlan Carew 	.f = cmd_set_cpu_freq_parsed,
455f5e5c334SAlan Carew 	.data = NULL,
4564c897d23SDavid Hunt 	.help_str = "set_cpu_freq <core_num> "
4574c897d23SDavid Hunt 			"<up|down|min|max|enable_turbo|disable_turbo>, "
4584c897d23SDavid Hunt 			"adjust the frequency for the specified core.",
459f5e5c334SAlan Carew 	.tokens = {
460f5e5c334SAlan Carew 		(void *)&cmd_set_cpu_freq,
461f5e5c334SAlan Carew 		(void *)&cmd_set_cpu_freq_core_num,
462f5e5c334SAlan Carew 		(void *)&cmd_set_cpu_freq_cmd_cmd,
463f5e5c334SAlan Carew 		NULL,
464f5e5c334SAlan Carew 	},
465f5e5c334SAlan Carew };
466f5e5c334SAlan Carew 
46788a81aa4SRory Sexton struct cmd_send_policy_result {
46888a81aa4SRory Sexton 	cmdline_fixed_string_t send_policy;
46988a81aa4SRory Sexton 	cmdline_fixed_string_t cmd;
47088a81aa4SRory Sexton };
47188a81aa4SRory Sexton 
47288a81aa4SRory Sexton static inline int
473bd5b6720SBruce Richardson send_policy(struct rte_power_channel_packet *pkt, struct cmdline *cl)
47488a81aa4SRory Sexton {
47588a81aa4SRory Sexton 	int ret;
47688a81aa4SRory Sexton 
47759287933SDavid Hunt 	ret = rte_power_guest_channel_send_msg(pkt, 1);
478a21f995bSMarcin Hajkowski 	if (ret < 0) {
479a21f995bSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "Error sending message: %s\n",
48088a81aa4SRory Sexton 				ret > 0 ? strerror(ret) : "channel not connected");
48188a81aa4SRory Sexton 		return -1;
48288a81aa4SRory Sexton 	}
48388a81aa4SRory Sexton 
484a21f995bSMarcin Hajkowski 	int result;
485a21f995bSMarcin Hajkowski 	ret = check_response_cmd(1, &result);
486a21f995bSMarcin Hajkowski 	if (ret < 0) {
487a21f995bSMarcin Hajkowski 		RTE_LOG(ERR, GUEST_CLI, "No confirmation for sent policy received\n");
488a21f995bSMarcin Hajkowski 	} else {
489a21f995bSMarcin Hajkowski 		cmdline_printf(cl, "%s for sent policy received.\n",
490a21f995bSMarcin Hajkowski 				result == 1 ? "ACK" : "NACK");
491a21f995bSMarcin Hajkowski 	}
492a21f995bSMarcin Hajkowski 	return 1;
493a21f995bSMarcin Hajkowski }
494a21f995bSMarcin Hajkowski 
49588a81aa4SRory Sexton static void
49688a81aa4SRory Sexton cmd_send_policy_parsed(void *parsed_result, struct cmdline *cl,
4970e8f4749SMarcin Hajkowski 		__rte_unused void *data)
49888a81aa4SRory Sexton {
49988a81aa4SRory Sexton 	int ret = -1;
50088a81aa4SRory Sexton 	struct cmd_send_policy_result *res = parsed_result;
50188a81aa4SRory Sexton 
50288a81aa4SRory Sexton 	if (!strcmp(res->cmd, "now")) {
50388a81aa4SRory Sexton 		printf("Sending Policy down now!\n");
504a21f995bSMarcin Hajkowski 		ret = send_policy(&policy, cl);
50588a81aa4SRory Sexton 	}
50688a81aa4SRory Sexton 	if (ret != 1)
50788a81aa4SRory Sexton 		cmdline_printf(cl, "Error sending message: %s\n",
50888a81aa4SRory Sexton 				strerror(ret));
50988a81aa4SRory Sexton }
51088a81aa4SRory Sexton 
51188a81aa4SRory Sexton cmdline_parse_token_string_t cmd_send_policy =
51288a81aa4SRory Sexton 	TOKEN_STRING_INITIALIZER(struct cmd_send_policy_result,
51388a81aa4SRory Sexton 			send_policy, "send_policy");
51488a81aa4SRory Sexton cmdline_parse_token_string_t cmd_send_policy_cmd_cmd =
51588a81aa4SRory Sexton 	TOKEN_STRING_INITIALIZER(struct cmd_send_policy_result,
51688a81aa4SRory Sexton 			cmd, "now");
51788a81aa4SRory Sexton 
51888a81aa4SRory Sexton cmdline_parse_inst_t cmd_send_policy_set = {
51988a81aa4SRory Sexton 	.f = cmd_send_policy_parsed,
52088a81aa4SRory Sexton 	.data = NULL,
52188a81aa4SRory Sexton 	.help_str = "send_policy now",
52288a81aa4SRory Sexton 	.tokens = {
52388a81aa4SRory Sexton 		(void *)&cmd_send_policy,
52488a81aa4SRory Sexton 		(void *)&cmd_send_policy_cmd_cmd,
52588a81aa4SRory Sexton 		NULL,
52688a81aa4SRory Sexton 	},
52788a81aa4SRory Sexton };
52888a81aa4SRory Sexton 
529f5e5c334SAlan Carew cmdline_parse_ctx_t main_ctx[] = {
530f5e5c334SAlan Carew 		(cmdline_parse_inst_t *)&cmd_quit,
53188a81aa4SRory Sexton 		(cmdline_parse_inst_t *)&cmd_send_policy_set,
532f5e5c334SAlan Carew 		(cmdline_parse_inst_t *)&cmd_set_cpu_freq_set,
5330e8f4749SMarcin Hajkowski 		(cmdline_parse_inst_t *)&cmd_query_freq_list,
53407525d1aSMarcin Hajkowski 		(cmdline_parse_inst_t *)&cmd_query_caps_list,
535f5e5c334SAlan Carew 		NULL,
536f5e5c334SAlan Carew };
537f5e5c334SAlan Carew 
538f5e5c334SAlan Carew void
5390e8f4749SMarcin Hajkowski run_cli(__rte_unused void *arg)
540f5e5c334SAlan Carew {
541f5e5c334SAlan Carew 	struct cmdline *cl;
542f5e5c334SAlan Carew 
543f5e5c334SAlan Carew 	cl = cmdline_stdin_new(main_ctx, "vmpower(guest)> ");
544f5e5c334SAlan Carew 	if (cl == NULL)
545f5e5c334SAlan Carew 		return;
546f5e5c334SAlan Carew 
547f5e5c334SAlan Carew 	cmdline_interact(cl);
548f5e5c334SAlan Carew 	cmdline_stdin_exit(cl);
549f5e5c334SAlan Carew }
550