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