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