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