Imported Upstream version 16.04
[deb_dpdk.git] / examples / vm_power_manager / vm_power_cli.c
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         if (ret < 0) {
524                 cmdline_printf(cl, "Error scaling core_mask(0x%"PRIx64") '%s' , not "
525                                 "all cores specified have been scaled\n",
526                                 res->core_mask, res->cmd);
527         };
528 }
529
530 cmdline_parse_token_string_t cmd_set_cpu_freq_mask =
531         TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
532                         set_cpu_freq_mask, "set_cpu_freq_mask");
533 cmdline_parse_token_num_t cmd_set_cpu_freq_mask_core_mask =
534         TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
535                         core_mask, UINT64);
536 cmdline_parse_token_string_t cmd_set_cpu_freq_mask_result =
537         TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result,
538                         cmd, "up#down#min#max");
539
540 cmdline_parse_inst_t cmd_set_cpu_freq_mask_set = {
541         .f = cmd_set_cpu_freq_mask_parsed,
542         .data = NULL,
543         .help_str = "set_cpu_freq <core_mask> <up|down|min|max>, Set the current "
544                         "frequency for the cores specified in <core_mask> by scaling "
545                         "each up/down/min/max.",
546         .tokens = {
547                 (void *)&cmd_set_cpu_freq_mask,
548                 (void *)&cmd_set_cpu_freq_mask_core_mask,
549                 (void *)&cmd_set_cpu_freq_mask_result,
550                 NULL,
551         },
552 };
553
554
555
556 struct cmd_show_cpu_freq_result {
557         cmdline_fixed_string_t show_cpu_freq;
558         uint8_t core_num;
559 };
560
561 static void
562 cmd_show_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
563                        __attribute__((unused)) void *data)
564 {
565         struct cmd_show_cpu_freq_result *res = parsed_result;
566         uint32_t curr_freq = power_manager_get_current_frequency(res->core_num);
567
568         if (curr_freq == 0) {
569                 cmdline_printf(cl, "Unable to get frequency for core %u\n",
570                                 res->core_num);
571                 return;
572         }
573         cmdline_printf(cl, "Core %u frequency: %"PRId32"\n", res->core_num,
574                         curr_freq);
575 }
576
577 cmdline_parse_token_string_t cmd_show_cpu_freq =
578         TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_result,
579                         show_cpu_freq, "show_cpu_freq");
580
581 cmdline_parse_token_num_t cmd_show_cpu_freq_core_num =
582         TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_result,
583                         core_num, UINT8);
584
585 cmdline_parse_inst_t cmd_show_cpu_freq_set = {
586         .f = cmd_show_cpu_freq_parsed,
587         .data = NULL,
588         .help_str = "Get the current frequency for the specified core",
589         .tokens = {
590                 (void *)&cmd_show_cpu_freq,
591                 (void *)&cmd_show_cpu_freq_core_num,
592                 NULL,
593         },
594 };
595
596 struct cmd_set_cpu_freq_result {
597         cmdline_fixed_string_t set_cpu_freq;
598         uint8_t core_num;
599         cmdline_fixed_string_t cmd;
600 };
601
602 static void
603 cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
604                        __attribute__((unused)) void *data)
605 {
606         int ret = -1;
607         struct cmd_set_cpu_freq_result *res = parsed_result;
608
609         if (!strcmp(res->cmd , "up"))
610                 ret = power_manager_scale_core_up(res->core_num);
611         else if (!strcmp(res->cmd , "down"))
612                 ret = power_manager_scale_core_down(res->core_num);
613         else if (!strcmp(res->cmd , "min"))
614                 ret = power_manager_scale_core_min(res->core_num);
615         else if (!strcmp(res->cmd , "max"))
616                 ret = power_manager_scale_core_max(res->core_num);
617         if (ret < 0) {
618                 cmdline_printf(cl, "Error scaling core(%u) '%s'\n", res->core_num,
619                                 res->cmd);
620         }
621 }
622
623 cmdline_parse_token_string_t cmd_set_cpu_freq =
624         TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
625                         set_cpu_freq, "set_cpu_freq");
626 cmdline_parse_token_num_t cmd_set_cpu_freq_core_num =
627         TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result,
628                         core_num, UINT8);
629 cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd =
630         TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
631                         cmd, "up#down#min#max");
632
633 cmdline_parse_inst_t cmd_set_cpu_freq_set = {
634         .f = cmd_set_cpu_freq_parsed,
635         .data = NULL,
636         .help_str = "set_cpu_freq <core_num> <up|down|min|max>, Set the current "
637                         "frequency for the specified core by scaling up/down/min/max",
638         .tokens = {
639                 (void *)&cmd_set_cpu_freq,
640                 (void *)&cmd_set_cpu_freq_core_num,
641                 (void *)&cmd_set_cpu_freq_cmd_cmd,
642                 NULL,
643         },
644 };
645
646 cmdline_parse_ctx_t main_ctx[] = {
647                 (cmdline_parse_inst_t *)&cmd_quit,
648                 (cmdline_parse_inst_t *)&cmd_vm_op_set,
649                 (cmdline_parse_inst_t *)&cmd_channels_op_set,
650                 (cmdline_parse_inst_t *)&cmd_channels_status_op_set,
651                 (cmdline_parse_inst_t *)&cmd_show_vm_set,
652                 (cmdline_parse_inst_t *)&cmd_show_cpu_freq_mask_set,
653                 (cmdline_parse_inst_t *)&cmd_set_cpu_freq_mask_set,
654                 (cmdline_parse_inst_t *)&cmd_show_cpu_freq_set,
655                 (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set,
656                 (cmdline_parse_inst_t *)&cmd_set_pcpu_mask_set,
657                 (cmdline_parse_inst_t *)&cmd_set_pcpu_set,
658                 NULL,
659 };
660
661 void
662 run_cli(__attribute__((unused)) void *arg)
663 {
664         struct cmdline *cl;
665
666         cl = cmdline_stdin_new(main_ctx, "vmpower> ");
667         if (cl == NULL)
668                 return;
669
670         cmdline_interact(cl);
671         cmdline_stdin_exit(cl);
672 }