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