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 } 673