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