1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
13 #include <cmdline_rdline.h>
14 #include <cmdline_parse.h>
15 #include <cmdline_parse_string.h>
16 #include <cmdline_parse_num.h>
17 #include <cmdline_socket.h>
20 #include "vm_power_cli.h"
21 #include "channel_manager.h"
22 #include "channel_monitor.h"
23 #include "power_manager.h"
24 #include "channel_commands.h"
26 struct cmd_quit_result {
27 cmdline_fixed_string_t quit;
30 static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
32 __attribute__((unused)) void *data)
34 channel_monitor_exit();
35 channel_manager_exit();
40 cmdline_parse_token_string_t cmd_quit_quit =
41 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
43 cmdline_parse_inst_t cmd_quit = {
44 .f = cmd_quit_parsed, /* function to call */
45 .data = NULL, /* 2nd arg of func */
46 .help_str = "close the application",
47 .tokens = { /* token list, NULL terminated */
48 (void *)&cmd_quit_quit,
53 /* *** VM operations *** */
54 struct cmd_show_vm_result {
55 cmdline_fixed_string_t show_vm;
56 cmdline_fixed_string_t vm_name;
60 cmd_show_vm_parsed(void *parsed_result, struct cmdline *cl,
61 __attribute__((unused)) void *data)
63 struct cmd_show_vm_result *res = parsed_result;
67 if (get_info_vm(res->vm_name, &info) != 0)
69 cmdline_printf(cl, "VM: '%s', status = ", info.name);
70 if (info.status == CHANNEL_MGR_VM_ACTIVE)
71 cmdline_printf(cl, "ACTIVE\n");
73 cmdline_printf(cl, "INACTIVE\n");
74 cmdline_printf(cl, "Channels %u\n", info.num_channels);
75 for (i = 0; i < info.num_channels; i++) {
76 cmdline_printf(cl, " [%u]: %s, status = ", i,
77 info.channels[i].channel_path);
78 switch (info.channels[i].status) {
79 case CHANNEL_MGR_CHANNEL_CONNECTED:
80 cmdline_printf(cl, "CONNECTED\n");
82 case CHANNEL_MGR_CHANNEL_DISCONNECTED:
83 cmdline_printf(cl, "DISCONNECTED\n");
85 case CHANNEL_MGR_CHANNEL_DISABLED:
86 cmdline_printf(cl, "DISABLED\n");
88 case CHANNEL_MGR_CHANNEL_PROCESSING:
89 cmdline_printf(cl, "PROCESSING\n");
92 cmdline_printf(cl, "UNKNOWN\n");
96 cmdline_printf(cl, "Virtual CPU(s): %u\n", info.num_vcpus);
97 for (i = 0; i < info.num_vcpus; i++) {
98 cmdline_printf(cl, " [%u]: Physical CPU %d\n", i,
105 cmdline_parse_token_string_t cmd_vm_show =
106 TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result,
108 cmdline_parse_token_string_t cmd_show_vm_name =
109 TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result,
112 cmdline_parse_inst_t cmd_show_vm_set = {
113 .f = cmd_show_vm_parsed,
115 .help_str = "show_vm <vm_name>, prints the information on the "
116 "specified VM(s), the information lists the number of vCPUS, the "
117 "pinning to pCPU(s) as a bit mask, along with any communication "
118 "channels associated with each VM",
120 (void *)&cmd_vm_show,
121 (void *)&cmd_show_vm_name,
126 /* *** vCPU to pCPU mapping operations *** */
129 struct cmd_set_pcpu_result {
130 cmdline_fixed_string_t set_pcpu;
131 cmdline_fixed_string_t vm_name;
137 cmd_set_pcpu_parsed(void *parsed_result, struct cmdline *cl,
138 __attribute__((unused)) void *data)
140 struct cmd_set_pcpu_result *res = parsed_result;
142 if (set_pcpu(res->vm_name, res->vcpu, res->core) == 0)
143 cmdline_printf(cl, "Pinned vCPU(%"PRId8") to pCPU core "
144 "%"PRId8")\n", res->vcpu, res->core);
146 cmdline_printf(cl, "Unable to pin vCPU(%"PRId8") to pCPU core "
147 "%"PRId8")\n", res->vcpu, res->core);
150 cmdline_parse_token_string_t cmd_set_pcpu =
151 TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result,
152 set_pcpu, "set_pcpu");
153 cmdline_parse_token_string_t cmd_set_pcpu_vm_name =
154 TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result,
156 cmdline_parse_token_num_t set_pcpu_vcpu =
157 TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result,
159 cmdline_parse_token_num_t set_pcpu_core =
160 TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result,
164 cmdline_parse_inst_t cmd_set_pcpu_set = {
165 .f = cmd_set_pcpu_parsed,
167 .help_str = "set_pcpu <vm_name> <vcpu> <pcpu>, Set the binding "
168 "of Virtual CPU on VM to the Physical CPU.",
170 (void *)&cmd_set_pcpu,
171 (void *)&cmd_set_pcpu_vm_name,
172 (void *)&set_pcpu_vcpu,
173 (void *)&set_pcpu_core,
178 struct cmd_vm_op_result {
179 cmdline_fixed_string_t op_vm;
180 cmdline_fixed_string_t vm_name;
184 cmd_vm_op_parsed(void *parsed_result, struct cmdline *cl,
185 __attribute__((unused)) void *data)
187 struct cmd_vm_op_result *res = parsed_result;
189 if (!strcmp(res->op_vm, "add_vm")) {
190 if (add_vm(res->vm_name) < 0)
191 cmdline_printf(cl, "Unable to add VM '%s'\n", res->vm_name);
192 } else if (remove_vm(res->vm_name) < 0)
193 cmdline_printf(cl, "Unable to remove VM '%s'\n", res->vm_name);
196 cmdline_parse_token_string_t cmd_vm_op =
197 TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result,
198 op_vm, "add_vm#rm_vm");
199 cmdline_parse_token_string_t cmd_vm_name =
200 TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result,
203 cmdline_parse_inst_t cmd_vm_op_set = {
204 .f = cmd_vm_op_parsed,
206 .help_str = "add_vm|rm_vm <name>, add a VM for "
207 "subsequent operations with the CLI or remove a previously added "
208 "VM from the VM Power Manager",
211 (void *)&cmd_vm_name,
216 /* *** VM channel operations *** */
217 struct cmd_channels_op_result {
218 cmdline_fixed_string_t op;
219 cmdline_fixed_string_t vm_name;
220 cmdline_fixed_string_t channel_list;
223 cmd_channels_op_parsed(void *parsed_result, struct cmdline *cl,
224 __attribute__((unused)) void *data)
226 unsigned num_channels = 0, channel_num, i;
228 unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS];
229 char *token, *remaining, *tail_ptr;
230 struct cmd_channels_op_result *res = parsed_result;
232 if (!strcmp(res->channel_list, "all")) {
233 channels_added = add_all_channels(res->vm_name);
234 cmdline_printf(cl, "Added %d channels for VM '%s'\n",
235 channels_added, res->vm_name);
239 remaining = res->channel_list;
241 if (remaining == NULL || remaining[0] == '\0')
244 token = strsep(&remaining, ",");
248 channel_num = (unsigned)strtol(token, &tail_ptr, 10);
249 if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0'))
252 if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) {
253 cmdline_printf(cl, "Channel number '%u' exceeds the maximum number "
254 "of allowable channels(%u) for VM '%s'\n", channel_num,
255 CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name);
258 channel_list[num_channels++] = channel_num;
260 for (i = 0; i < num_channels; i++)
261 cmdline_printf(cl, "[%u]: Adding channel %u\n", i, channel_list[i]);
263 channels_added = add_channels(res->vm_name, channel_list,
265 cmdline_printf(cl, "Enabled %d channels for '%s'\n", channels_added,
269 cmdline_parse_token_string_t cmd_channels_op =
270 TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
272 cmdline_parse_token_string_t cmd_channels_vm_name =
273 TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
275 cmdline_parse_token_string_t cmd_channels_list =
276 TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
279 cmdline_parse_inst_t cmd_channels_op_set = {
280 .f = cmd_channels_op_parsed,
282 .help_str = "add_channels <vm_name> <list>|all, add "
283 "communication channels for the specified VM, the "
284 "virtio channels must be enabled in the VM "
285 "configuration(qemu/libvirt) and the associated VM must be active. "
286 "<list> is a comma-separated list of channel numbers to add, using "
287 "the keyword 'all' will attempt to add all channels for the VM",
289 (void *)&cmd_channels_op,
290 (void *)&cmd_channels_vm_name,
291 (void *)&cmd_channels_list,
296 struct cmd_channels_status_op_result {
297 cmdline_fixed_string_t op;
298 cmdline_fixed_string_t vm_name;
299 cmdline_fixed_string_t channel_list;
300 cmdline_fixed_string_t status;
304 cmd_channels_status_op_parsed(void *parsed_result, struct cmdline *cl,
305 __attribute__((unused)) void *data)
307 unsigned num_channels = 0, channel_num;
309 unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS];
310 char *token, *remaining, *tail_ptr;
311 struct cmd_channels_status_op_result *res = parsed_result;
312 enum channel_status status;
314 if (!strcmp(res->status, "enabled"))
315 status = CHANNEL_MGR_CHANNEL_CONNECTED;
317 status = CHANNEL_MGR_CHANNEL_DISABLED;
319 if (!strcmp(res->channel_list, "all")) {
320 changed = set_channel_status_all(res->vm_name, status);
321 cmdline_printf(cl, "Updated status of %d channels "
322 "for VM '%s'\n", changed, res->vm_name);
325 remaining = res->channel_list;
327 if (remaining == NULL || remaining[0] == '\0')
329 token = strsep(&remaining, ",");
333 channel_num = (unsigned)strtol(token, &tail_ptr, 10);
334 if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0'))
337 if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) {
338 cmdline_printf(cl, "%u exceeds the maximum number of allowable "
339 "channels(%u) for VM '%s'\n", channel_num,
340 CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name);
343 channel_list[num_channels++] = channel_num;
345 changed = set_channel_status(res->vm_name, channel_list, num_channels,
347 cmdline_printf(cl, "Updated status of %d channels "
348 "for VM '%s'\n", changed, res->vm_name);
351 cmdline_parse_token_string_t cmd_channels_status_op =
352 TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
353 op, "set_channel_status");
354 cmdline_parse_token_string_t cmd_channels_status_vm_name =
355 TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
357 cmdline_parse_token_string_t cmd_channels_status_list =
358 TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
360 cmdline_parse_token_string_t cmd_channels_status =
361 TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
362 status, "enabled#disabled");
364 cmdline_parse_inst_t cmd_channels_status_op_set = {
365 .f = cmd_channels_status_op_parsed,
367 .help_str = "set_channel_status <vm_name> <list>|all enabled|disabled, "
368 " enable or disable the communication channels in "
369 "list(comma-separated) for the specified VM, alternatively "
370 "list can be replaced with keyword 'all'. "
371 "Disabled channels will still receive packets on the host, "
372 "however the commands they specify will be ignored. "
373 "Set status to 'enabled' to begin processing requests again.",
375 (void *)&cmd_channels_status_op,
376 (void *)&cmd_channels_status_vm_name,
377 (void *)&cmd_channels_status_list,
378 (void *)&cmd_channels_status,
383 /* *** CPU Frequency operations *** */
384 struct cmd_show_cpu_freq_result {
385 cmdline_fixed_string_t show_cpu_freq;
390 cmd_show_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
391 __attribute__((unused)) void *data)
393 struct cmd_show_cpu_freq_result *res = parsed_result;
394 uint32_t curr_freq = power_manager_get_current_frequency(res->core_num);
396 if (curr_freq == 0) {
397 cmdline_printf(cl, "Unable to get frequency for core %u\n",
401 cmdline_printf(cl, "Core %u frequency: %"PRId32"\n", res->core_num,
405 cmdline_parse_token_string_t cmd_show_cpu_freq =
406 TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_result,
407 show_cpu_freq, "show_cpu_freq");
409 cmdline_parse_token_num_t cmd_show_cpu_freq_core_num =
410 TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_result,
413 cmdline_parse_inst_t cmd_show_cpu_freq_set = {
414 .f = cmd_show_cpu_freq_parsed,
416 .help_str = "Get the current frequency for the specified core",
418 (void *)&cmd_show_cpu_freq,
419 (void *)&cmd_show_cpu_freq_core_num,
424 struct cmd_set_cpu_freq_result {
425 cmdline_fixed_string_t set_cpu_freq;
427 cmdline_fixed_string_t cmd;
431 cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
432 __attribute__((unused)) void *data)
435 struct cmd_set_cpu_freq_result *res = parsed_result;
437 if (!strcmp(res->cmd , "up"))
438 ret = power_manager_scale_core_up(res->core_num);
439 else if (!strcmp(res->cmd , "down"))
440 ret = power_manager_scale_core_down(res->core_num);
441 else if (!strcmp(res->cmd , "min"))
442 ret = power_manager_scale_core_min(res->core_num);
443 else if (!strcmp(res->cmd , "max"))
444 ret = power_manager_scale_core_max(res->core_num);
445 else if (!strcmp(res->cmd, "enable_turbo"))
446 ret = power_manager_enable_turbo_core(res->core_num);
447 else if (!strcmp(res->cmd, "disable_turbo"))
448 ret = power_manager_disable_turbo_core(res->core_num);
450 cmdline_printf(cl, "Error scaling core(%u) '%s'\n", res->core_num,
455 cmdline_parse_token_string_t cmd_set_cpu_freq =
456 TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
457 set_cpu_freq, "set_cpu_freq");
458 cmdline_parse_token_num_t cmd_set_cpu_freq_core_num =
459 TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result,
461 cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd =
462 TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
463 cmd, "up#down#min#max#enable_turbo#disable_turbo");
465 cmdline_parse_inst_t cmd_set_cpu_freq_set = {
466 .f = cmd_set_cpu_freq_parsed,
468 .help_str = "set_cpu_freq <core_num> <up|down|min|max|enable_turbo|disable_turbo>, adjust the current "
469 "frequency for the specified core",
471 (void *)&cmd_set_cpu_freq,
472 (void *)&cmd_set_cpu_freq_core_num,
473 (void *)&cmd_set_cpu_freq_cmd_cmd,
478 cmdline_parse_ctx_t main_ctx[] = {
479 (cmdline_parse_inst_t *)&cmd_quit,
480 (cmdline_parse_inst_t *)&cmd_vm_op_set,
481 (cmdline_parse_inst_t *)&cmd_channels_op_set,
482 (cmdline_parse_inst_t *)&cmd_channels_status_op_set,
483 (cmdline_parse_inst_t *)&cmd_show_vm_set,
484 (cmdline_parse_inst_t *)&cmd_show_cpu_freq_set,
485 (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set,
486 (cmdline_parse_inst_t *)&cmd_set_pcpu_set,
491 run_cli(__attribute__((unused)) void *arg)
495 cl = cmdline_stdin_new(main_ctx, "vmpower> ");
499 cmdline_interact(cl);
500 cmdline_stdin_exit(cl);