xref: /dpdk/examples/vm_power_manager/vm_power_cli.c (revision 3998e2a07220844d3f3c17f76a781ced3efe0de0)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <inttypes.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <termios.h>
11 #include <errno.h>
12 
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>
18 #include <cmdline.h>
19 
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"
25 
26 struct cmd_quit_result {
27 	cmdline_fixed_string_t quit;
28 };
29 
30 static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
31 		struct cmdline *cl,
32 		__attribute__((unused)) void *data)
33 {
34 	channel_monitor_exit();
35 	channel_manager_exit();
36 	power_manager_exit();
37 	cmdline_quit(cl);
38 }
39 
40 cmdline_parse_token_string_t cmd_quit_quit =
41 	TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
42 
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,
49 		NULL,
50 	},
51 };
52 
53 /* *** VM operations *** */
54 struct cmd_show_vm_result {
55 	cmdline_fixed_string_t show_vm;
56 	cmdline_fixed_string_t vm_name;
57 };
58 
59 static void
60 cmd_show_vm_parsed(void *parsed_result, struct cmdline *cl,
61 		__attribute__((unused)) void *data)
62 {
63 	struct cmd_show_vm_result *res = parsed_result;
64 	struct vm_info info;
65 	unsigned i;
66 
67 	if (get_info_vm(res->vm_name, &info) != 0)
68 		return;
69 	cmdline_printf(cl, "VM: '%s', status = ", info.name);
70 	if (info.status == CHANNEL_MGR_VM_ACTIVE)
71 		cmdline_printf(cl, "ACTIVE\n");
72 	else
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");
81 			break;
82 		case CHANNEL_MGR_CHANNEL_DISCONNECTED:
83 			cmdline_printf(cl, "DISCONNECTED\n");
84 			break;
85 		case CHANNEL_MGR_CHANNEL_DISABLED:
86 			cmdline_printf(cl, "DISABLED\n");
87 			break;
88 		case CHANNEL_MGR_CHANNEL_PROCESSING:
89 			cmdline_printf(cl, "PROCESSING\n");
90 			break;
91 		default:
92 			cmdline_printf(cl, "UNKNOWN\n");
93 			break;
94 		}
95 	}
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 Mask 0x%"PRIx64"\n", i,
99 				info.pcpu_mask[i]);
100 	}
101 }
102 
103 
104 
105 cmdline_parse_token_string_t cmd_vm_show =
106 	TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result,
107 				show_vm, "show_vm");
108 cmdline_parse_token_string_t cmd_show_vm_name =
109 	TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result,
110 			vm_name, NULL);
111 
112 cmdline_parse_inst_t cmd_show_vm_set = {
113 	.f = cmd_show_vm_parsed,
114 	.data = NULL,
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",
119 	.tokens = {
120 		(void *)&cmd_vm_show,
121 		(void *)&cmd_show_vm_name,
122 		NULL,
123 	},
124 };
125 
126 /* *** vCPU to pCPU mapping operations *** */
127 struct cmd_set_pcpu_mask_result {
128 	cmdline_fixed_string_t set_pcpu_mask;
129 	cmdline_fixed_string_t vm_name;
130 	uint8_t vcpu;
131 	uint64_t core_mask;
132 };
133 
134 static void
135 cmd_set_pcpu_mask_parsed(void *parsed_result, struct cmdline *cl,
136 		__attribute__((unused)) void *data)
137 {
138 	struct cmd_set_pcpu_mask_result *res = parsed_result;
139 
140 	if (set_pcpus_mask(res->vm_name, res->vcpu, res->core_mask) == 0)
141 		cmdline_printf(cl, "Pinned vCPU(%"PRId8") to pCPU core "
142 				"mask(0x%"PRIx64")\n", res->vcpu, res->core_mask);
143 	else
144 		cmdline_printf(cl, "Unable to pin vCPU(%"PRId8") to pCPU core "
145 				"mask(0x%"PRIx64")\n", res->vcpu, res->core_mask);
146 }
147 
148 cmdline_parse_token_string_t cmd_set_pcpu_mask =
149 		TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_mask_result,
150 				set_pcpu_mask, "set_pcpu_mask");
151 cmdline_parse_token_string_t cmd_set_pcpu_mask_vm_name =
152 		TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_mask_result,
153 				vm_name, NULL);
154 cmdline_parse_token_num_t set_pcpu_mask_vcpu =
155 		TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_mask_result,
156 				vcpu, UINT8);
157 cmdline_parse_token_num_t set_pcpu_mask_core_mask =
158 		TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_mask_result,
159 				core_mask, UINT64);
160 
161 
162 cmdline_parse_inst_t cmd_set_pcpu_mask_set = {
163 		.f = cmd_set_pcpu_mask_parsed,
164 		.data = NULL,
165 		.help_str = "set_pcpu_mask <vm_name> <vcpu> <pcpu>, Set the binding "
166 				"of Virtual CPU on VM to the Physical CPU mask.",
167 				.tokens = {
168 						(void *)&cmd_set_pcpu_mask,
169 						(void *)&cmd_set_pcpu_mask_vm_name,
170 						(void *)&set_pcpu_mask_vcpu,
171 						(void *)&set_pcpu_mask_core_mask,
172 						NULL,
173 		},
174 };
175 
176 struct cmd_set_pcpu_result {
177 	cmdline_fixed_string_t set_pcpu;
178 	cmdline_fixed_string_t vm_name;
179 	uint8_t vcpu;
180 	uint8_t core;
181 };
182 
183 static void
184 cmd_set_pcpu_parsed(void *parsed_result, struct cmdline *cl,
185 		__attribute__((unused)) void *data)
186 {
187 	struct cmd_set_pcpu_result *res = parsed_result;
188 
189 	if (set_pcpu(res->vm_name, res->vcpu, res->core) == 0)
190 		cmdline_printf(cl, "Pinned vCPU(%"PRId8") to pCPU core "
191 				"%"PRId8")\n", res->vcpu, res->core);
192 	else
193 		cmdline_printf(cl, "Unable to pin vCPU(%"PRId8") to pCPU core "
194 				"%"PRId8")\n", res->vcpu, res->core);
195 }
196 
197 cmdline_parse_token_string_t cmd_set_pcpu =
198 		TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result,
199 				set_pcpu, "set_pcpu");
200 cmdline_parse_token_string_t cmd_set_pcpu_vm_name =
201 		TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result,
202 				vm_name, NULL);
203 cmdline_parse_token_num_t set_pcpu_vcpu =
204 		TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result,
205 				vcpu, UINT8);
206 cmdline_parse_token_num_t set_pcpu_core =
207 		TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result,
208 				core, UINT64);
209 
210 
211 cmdline_parse_inst_t cmd_set_pcpu_set = {
212 		.f = cmd_set_pcpu_parsed,
213 		.data = NULL,
214 		.help_str = "set_pcpu <vm_name> <vcpu> <pcpu>, Set the binding "
215 				"of Virtual CPU on VM to the Physical CPU.",
216 				.tokens = {
217 						(void *)&cmd_set_pcpu,
218 						(void *)&cmd_set_pcpu_vm_name,
219 						(void *)&set_pcpu_vcpu,
220 						(void *)&set_pcpu_core,
221 						NULL,
222 		},
223 };
224 
225 struct cmd_vm_op_result {
226 	cmdline_fixed_string_t op_vm;
227 	cmdline_fixed_string_t vm_name;
228 };
229 
230 static void
231 cmd_vm_op_parsed(void *parsed_result, struct cmdline *cl,
232 		__attribute__((unused)) void *data)
233 {
234 	struct cmd_vm_op_result *res = parsed_result;
235 
236 	if (!strcmp(res->op_vm, "add_vm")) {
237 		if (add_vm(res->vm_name) < 0)
238 			cmdline_printf(cl, "Unable to add VM '%s'\n", res->vm_name);
239 	} else if (remove_vm(res->vm_name) < 0)
240 		cmdline_printf(cl, "Unable to remove VM '%s'\n", res->vm_name);
241 }
242 
243 cmdline_parse_token_string_t cmd_vm_op =
244 	TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result,
245 			op_vm, "add_vm#rm_vm");
246 cmdline_parse_token_string_t cmd_vm_name =
247 	TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result,
248 			vm_name, NULL);
249 
250 cmdline_parse_inst_t cmd_vm_op_set = {
251 	.f = cmd_vm_op_parsed,
252 	.data = NULL,
253 	.help_str = "add_vm|rm_vm <name>, add a VM for "
254 			"subsequent operations with the CLI or remove a previously added "
255 			"VM from the VM Power Manager",
256 	.tokens = {
257 		(void *)&cmd_vm_op,
258 		(void *)&cmd_vm_name,
259 	NULL,
260 	},
261 };
262 
263 /* *** VM channel operations *** */
264 struct cmd_channels_op_result {
265 	cmdline_fixed_string_t op;
266 	cmdline_fixed_string_t vm_name;
267 	cmdline_fixed_string_t channel_list;
268 };
269 static void
270 cmd_channels_op_parsed(void *parsed_result, struct cmdline *cl,
271 			__attribute__((unused)) void *data)
272 {
273 	unsigned num_channels = 0, channel_num, i;
274 	int channels_added;
275 	unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS];
276 	char *token, *remaining, *tail_ptr;
277 	struct cmd_channels_op_result *res = parsed_result;
278 
279 	if (!strcmp(res->channel_list, "all")) {
280 		channels_added = add_all_channels(res->vm_name);
281 		cmdline_printf(cl, "Added %d channels for VM '%s'\n",
282 				channels_added, res->vm_name);
283 		return;
284 	}
285 
286 	remaining = res->channel_list;
287 	while (1) {
288 		if (remaining == NULL || remaining[0] == '\0')
289 			break;
290 
291 		token = strsep(&remaining, ",");
292 		if (token == NULL)
293 			break;
294 		errno = 0;
295 		channel_num = (unsigned)strtol(token, &tail_ptr, 10);
296 		if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0'))
297 			break;
298 
299 		if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) {
300 			cmdline_printf(cl, "Channel number '%u' exceeds the maximum number "
301 					"of allowable channels(%u) for VM '%s'\n", channel_num,
302 					CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name);
303 			return;
304 		}
305 		channel_list[num_channels++] = channel_num;
306 	}
307 	for (i = 0; i < num_channels; i++)
308 		cmdline_printf(cl, "[%u]: Adding channel %u\n", i, channel_list[i]);
309 
310 	channels_added = add_channels(res->vm_name, channel_list,
311 			num_channels);
312 	cmdline_printf(cl, "Enabled %d channels for '%s'\n", channels_added,
313 			res->vm_name);
314 }
315 
316 cmdline_parse_token_string_t cmd_channels_op =
317 	TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
318 				op, "add_channels");
319 cmdline_parse_token_string_t cmd_channels_vm_name =
320 	TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
321 			vm_name, NULL);
322 cmdline_parse_token_string_t cmd_channels_list =
323 	TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result,
324 			channel_list, NULL);
325 
326 cmdline_parse_inst_t cmd_channels_op_set = {
327 	.f = cmd_channels_op_parsed,
328 	.data = NULL,
329 	.help_str = "add_channels <vm_name> <list>|all, add "
330 			"communication channels for the specified VM, the "
331 			"virtio channels must be enabled in the VM "
332 			"configuration(qemu/libvirt) and the associated VM must be active. "
333 			"<list> is a comma-separated list of channel numbers to add, using "
334 			"the keyword 'all' will attempt to add all channels for the VM",
335 	.tokens = {
336 		(void *)&cmd_channels_op,
337 		(void *)&cmd_channels_vm_name,
338 		(void *)&cmd_channels_list,
339 		NULL,
340 	},
341 };
342 
343 struct cmd_channels_status_op_result {
344 	cmdline_fixed_string_t op;
345 	cmdline_fixed_string_t vm_name;
346 	cmdline_fixed_string_t channel_list;
347 	cmdline_fixed_string_t status;
348 };
349 
350 static void
351 cmd_channels_status_op_parsed(void *parsed_result, struct cmdline *cl,
352 		       __attribute__((unused)) void *data)
353 {
354 	unsigned num_channels = 0, channel_num;
355 	int changed;
356 	unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS];
357 	char *token, *remaining, *tail_ptr;
358 	struct cmd_channels_status_op_result *res = parsed_result;
359 	enum channel_status status;
360 
361 	if (!strcmp(res->status, "enabled"))
362 		status = CHANNEL_MGR_CHANNEL_CONNECTED;
363 	else
364 		status = CHANNEL_MGR_CHANNEL_DISABLED;
365 
366 	if (!strcmp(res->channel_list, "all")) {
367 		changed = set_channel_status_all(res->vm_name, status);
368 		cmdline_printf(cl, "Updated status of %d channels "
369 				"for VM '%s'\n", changed, res->vm_name);
370 		return;
371 	}
372 	remaining = res->channel_list;
373 	while (1) {
374 		if (remaining == NULL || remaining[0] == '\0')
375 			break;
376 		token = strsep(&remaining, ",");
377 		if (token == NULL)
378 			break;
379 		errno = 0;
380 		channel_num = (unsigned)strtol(token, &tail_ptr, 10);
381 		if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0'))
382 			break;
383 
384 		if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) {
385 			cmdline_printf(cl, "%u exceeds the maximum number of allowable "
386 					"channels(%u) for VM '%s'\n", channel_num,
387 					CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name);
388 			return;
389 		}
390 		channel_list[num_channels++] = channel_num;
391 	}
392 	changed = set_channel_status(res->vm_name, channel_list, num_channels,
393 			status);
394 	cmdline_printf(cl, "Updated status of %d channels "
395 					"for VM '%s'\n", changed, res->vm_name);
396 }
397 
398 cmdline_parse_token_string_t cmd_channels_status_op =
399 	TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
400 				op, "set_channel_status");
401 cmdline_parse_token_string_t cmd_channels_status_vm_name =
402 	TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
403 			vm_name, NULL);
404 cmdline_parse_token_string_t cmd_channels_status_list =
405 	TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
406 			channel_list, NULL);
407 cmdline_parse_token_string_t cmd_channels_status =
408 	TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result,
409 			status, "enabled#disabled");
410 
411 cmdline_parse_inst_t cmd_channels_status_op_set = {
412 	.f = cmd_channels_status_op_parsed,
413 	.data = NULL,
414 	.help_str = "set_channel_status <vm_name> <list>|all enabled|disabled, "
415 			" enable or disable the communication channels in "
416 			"list(comma-separated) for the specified VM, alternatively "
417 			"list can be replaced with keyword 'all'. "
418 			"Disabled channels will still receive packets on the host, "
419 			"however the commands they specify will be ignored. "
420 			"Set status to 'enabled' to begin processing requests again.",
421 	.tokens = {
422 		(void *)&cmd_channels_status_op,
423 		(void *)&cmd_channels_status_vm_name,
424 		(void *)&cmd_channels_status_list,
425 		(void *)&cmd_channels_status,
426 		NULL,
427 	},
428 };
429 
430 /* *** CPU Frequency operations *** */
431 struct cmd_show_cpu_freq_mask_result {
432 	cmdline_fixed_string_t show_cpu_freq_mask;
433 	uint64_t core_mask;
434 };
435 
436 static void
437 cmd_show_cpu_freq_mask_parsed(void *parsed_result, struct cmdline *cl,
438 		       __attribute__((unused)) void *data)
439 {
440 	struct cmd_show_cpu_freq_mask_result *res = parsed_result;
441 	unsigned i;
442 	uint64_t mask = res->core_mask;
443 	uint32_t freq;
444 
445 	for (i = 0; mask; mask &= ~(1ULL << i++)) {
446 		if ((mask >> i) & 1) {
447 			freq = power_manager_get_current_frequency(i);
448 			if (freq > 0)
449 				cmdline_printf(cl, "Core %u: %"PRId32"\n", i, freq);
450 		}
451 	}
452 }
453 
454 cmdline_parse_token_string_t cmd_show_cpu_freq_mask =
455 	TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_mask_result,
456 			show_cpu_freq_mask, "show_cpu_freq_mask");
457 cmdline_parse_token_num_t cmd_show_cpu_freq_mask_core_mask =
458 	TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_mask_result,
459 			core_mask, UINT64);
460 
461 cmdline_parse_inst_t cmd_show_cpu_freq_mask_set = {
462 	.f = cmd_show_cpu_freq_mask_parsed,
463 	.data = NULL,
464 	.help_str = "show_cpu_freq_mask <mask>, Get the current frequency for each "
465 			"core specified in the mask",
466 	.tokens = {
467 		(void *)&cmd_show_cpu_freq_mask,
468 		(void *)&cmd_show_cpu_freq_mask_core_mask,
469 		NULL,
470 	},
471 };
472 
473 struct cmd_set_cpu_freq_mask_result {
474 	cmdline_fixed_string_t set_cpu_freq_mask;
475 	uint64_t core_mask;
476 	cmdline_fixed_string_t cmd;
477 };
478 
479 static void
480 cmd_set_cpu_freq_mask_parsed(void *parsed_result, struct cmdline *cl,
481 			__attribute__((unused)) void *data)
482 {
483 	struct cmd_set_cpu_freq_mask_result *res = parsed_result;
484 	int ret = -1;
485 
486 	if (!strcmp(res->cmd , "up"))
487 		ret = power_manager_scale_mask_up(res->core_mask);
488 	else if (!strcmp(res->cmd , "down"))
489 		ret = power_manager_scale_mask_down(res->core_mask);
490 	else if (!strcmp(res->cmd , "min"))
491 		ret = power_manager_scale_mask_min(res->core_mask);
492 	else if (!strcmp(res->cmd , "max"))
493 		ret = power_manager_scale_mask_max(res->core_mask);
494 	else if (!strcmp(res->cmd, "enable_turbo"))
495 		ret = power_manager_enable_turbo_mask(res->core_mask);
496 	else if (!strcmp(res->cmd, "disable_turbo"))
497 		ret = power_manager_disable_turbo_mask(res->core_mask);
498 	if (ret < 0) {
499 		cmdline_printf(cl, "Error scaling core_mask(0x%"PRIx64") '%s' , not "
500 				"all cores specified have been scaled\n",
501 				res->core_mask, res->cmd);
502 	};
503 }
504 
505 cmdline_parse_token_string_t cmd_set_cpu_freq_mask =
506 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
507 			set_cpu_freq_mask, "set_cpu_freq_mask");
508 cmdline_parse_token_num_t cmd_set_cpu_freq_mask_core_mask =
509 	TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
510 			core_mask, UINT64);
511 cmdline_parse_token_string_t cmd_set_cpu_freq_mask_result =
512 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
513 			cmd, "up#down#min#max#enable_turbo#disable_turbo");
514 
515 cmdline_parse_inst_t cmd_set_cpu_freq_mask_set = {
516 	.f = cmd_set_cpu_freq_mask_parsed,
517 	.data = NULL,
518 	.help_str = "set_cpu_freq <core_mask> <up|down|min|max|enable_turbo|disable_turbo>, adjust the current "
519 			"frequency for the cores specified in <core_mask>",
520 	.tokens = {
521 		(void *)&cmd_set_cpu_freq_mask,
522 		(void *)&cmd_set_cpu_freq_mask_core_mask,
523 		(void *)&cmd_set_cpu_freq_mask_result,
524 		NULL,
525 	},
526 };
527 
528 
529 
530 struct cmd_show_cpu_freq_result {
531 	cmdline_fixed_string_t show_cpu_freq;
532 	uint8_t core_num;
533 };
534 
535 static void
536 cmd_show_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
537 		       __attribute__((unused)) void *data)
538 {
539 	struct cmd_show_cpu_freq_result *res = parsed_result;
540 	uint32_t curr_freq = power_manager_get_current_frequency(res->core_num);
541 
542 	if (curr_freq == 0) {
543 		cmdline_printf(cl, "Unable to get frequency for core %u\n",
544 				res->core_num);
545 		return;
546 	}
547 	cmdline_printf(cl, "Core %u frequency: %"PRId32"\n", res->core_num,
548 			curr_freq);
549 }
550 
551 cmdline_parse_token_string_t cmd_show_cpu_freq =
552 	TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_result,
553 			show_cpu_freq, "show_cpu_freq");
554 
555 cmdline_parse_token_num_t cmd_show_cpu_freq_core_num =
556 	TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_result,
557 			core_num, UINT8);
558 
559 cmdline_parse_inst_t cmd_show_cpu_freq_set = {
560 	.f = cmd_show_cpu_freq_parsed,
561 	.data = NULL,
562 	.help_str = "Get the current frequency for the specified core",
563 	.tokens = {
564 		(void *)&cmd_show_cpu_freq,
565 		(void *)&cmd_show_cpu_freq_core_num,
566 		NULL,
567 	},
568 };
569 
570 struct cmd_set_cpu_freq_result {
571 	cmdline_fixed_string_t set_cpu_freq;
572 	uint8_t core_num;
573 	cmdline_fixed_string_t cmd;
574 };
575 
576 static void
577 cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
578 		       __attribute__((unused)) void *data)
579 {
580 	int ret = -1;
581 	struct cmd_set_cpu_freq_result *res = parsed_result;
582 
583 	if (!strcmp(res->cmd , "up"))
584 		ret = power_manager_scale_core_up(res->core_num);
585 	else if (!strcmp(res->cmd , "down"))
586 		ret = power_manager_scale_core_down(res->core_num);
587 	else if (!strcmp(res->cmd , "min"))
588 		ret = power_manager_scale_core_min(res->core_num);
589 	else if (!strcmp(res->cmd , "max"))
590 		ret = power_manager_scale_core_max(res->core_num);
591 	else if (!strcmp(res->cmd, "enable_turbo"))
592 		ret = power_manager_enable_turbo_core(res->core_num);
593 	else if (!strcmp(res->cmd, "disable_turbo"))
594 		ret = power_manager_disable_turbo_core(res->core_num);
595 	if (ret < 0) {
596 		cmdline_printf(cl, "Error scaling core(%u) '%s'\n", res->core_num,
597 				res->cmd);
598 	}
599 }
600 
601 cmdline_parse_token_string_t cmd_set_cpu_freq =
602 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
603 			set_cpu_freq, "set_cpu_freq");
604 cmdline_parse_token_num_t cmd_set_cpu_freq_core_num =
605 	TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result,
606 			core_num, UINT8);
607 cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd =
608 	TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
609 			cmd, "up#down#min#max#enable_turbo#disable_turbo");
610 
611 cmdline_parse_inst_t cmd_set_cpu_freq_set = {
612 	.f = cmd_set_cpu_freq_parsed,
613 	.data = NULL,
614 	.help_str = "set_cpu_freq <core_num> <up|down|min|max|enable_turbo|disable_turbo>, adjust the current "
615 			"frequency for the specified core",
616 	.tokens = {
617 		(void *)&cmd_set_cpu_freq,
618 		(void *)&cmd_set_cpu_freq_core_num,
619 		(void *)&cmd_set_cpu_freq_cmd_cmd,
620 		NULL,
621 	},
622 };
623 
624 cmdline_parse_ctx_t main_ctx[] = {
625 		(cmdline_parse_inst_t *)&cmd_quit,
626 		(cmdline_parse_inst_t *)&cmd_vm_op_set,
627 		(cmdline_parse_inst_t *)&cmd_channels_op_set,
628 		(cmdline_parse_inst_t *)&cmd_channels_status_op_set,
629 		(cmdline_parse_inst_t *)&cmd_show_vm_set,
630 		(cmdline_parse_inst_t *)&cmd_show_cpu_freq_mask_set,
631 		(cmdline_parse_inst_t *)&cmd_set_cpu_freq_mask_set,
632 		(cmdline_parse_inst_t *)&cmd_show_cpu_freq_set,
633 		(cmdline_parse_inst_t *)&cmd_set_cpu_freq_set,
634 		(cmdline_parse_inst_t *)&cmd_set_pcpu_mask_set,
635 		(cmdline_parse_inst_t *)&cmd_set_pcpu_set,
636 		NULL,
637 };
638 
639 void
640 run_cli(__attribute__((unused)) void *arg)
641 {
642 	struct cmdline *cl;
643 
644 	cl = cmdline_stdin_new(main_ctx, "vmpower> ");
645 	if (cl == NULL)
646 		return;
647 
648 	cmdline_interact(cl);
649 	cmdline_stdin_exit(cl);
650 }
651