Subversion Repositories HelenOS

Rev

Rev 3742 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup genericconsole
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file    cmd.c
  35.  * @brief   Kernel console command wrappers.
  36.  *
  37.  * This file is meant to contain all wrapper functions for
  38.  * all kconsole commands. The point is in separating
  39.  * kconsole specific wrappers from kconsole-unaware functions
  40.  * from other subsystems.
  41.  */
  42.  
  43. #include <console/cmd.h>
  44. #include <console/console.h>
  45. #include <console/kconsole.h>
  46. #include <print.h>
  47. #include <panic.h>
  48. #include <arch/types.h>
  49. #include <adt/list.h>
  50. #include <arch.h>
  51. #include <config.h>
  52. #include <func.h>
  53. #include <macros.h>
  54. #include <debug.h>
  55. #include <symtab.h>
  56. #include <cpu.h>
  57. #include <mm/tlb.h>
  58. #include <mm/frame.h>
  59. #include <main/version.h>
  60. #include <mm/slab.h>
  61. #include <proc/scheduler.h>
  62. #include <proc/thread.h>
  63. #include <proc/task.h>
  64. #include <ipc/ipc.h>
  65. #include <ipc/irq.h>
  66.  
  67. #ifdef CONFIG_TEST
  68. #include <test.h>
  69. #endif
  70.  
  71. /* Data and methods for 'help' command. */
  72. static int cmd_help(cmd_arg_t *argv);
  73. static cmd_info_t help_info = {
  74.     .name = "help",
  75.     .description = "List of supported commands.",
  76.     .func = cmd_help,
  77.     .argc = 0
  78. };
  79.  
  80. static cmd_info_t exit_info = {
  81.     .name = "exit",
  82.     .description = "Exit kconsole.",
  83.     .argc = 0
  84. };
  85.  
  86. static int cmd_reboot(cmd_arg_t *argv);
  87. static cmd_info_t reboot_info = {
  88.     .name = "reboot",
  89.     .description = "Reboot.",
  90.     .func = cmd_reboot,
  91.     .argc = 0
  92. };
  93.  
  94. static int cmd_uptime(cmd_arg_t *argv);
  95. static cmd_info_t uptime_info = {
  96.     .name = "uptime",
  97.     .description = "Print uptime information.",
  98.     .func = cmd_uptime,
  99.     .argc = 0
  100. };
  101.  
  102. static int cmd_continue(cmd_arg_t *argv);
  103. static cmd_info_t continue_info = {
  104.     .name = "continue",
  105.     .description = "Return console back to userspace.",
  106.     .func = cmd_continue,
  107.     .argc = 0
  108. };
  109.  
  110. #ifdef CONFIG_TEST
  111. static int cmd_tests(cmd_arg_t *argv);
  112. static cmd_info_t tests_info = {
  113.     .name = "tests",
  114.     .description = "Print available kernel tests.",
  115.     .func = cmd_tests,
  116.     .argc = 0
  117. };
  118.  
  119. static char test_buf[MAX_CMDLINE + 1];
  120. static int cmd_test(cmd_arg_t *argv);
  121. static cmd_arg_t test_argv[] = {
  122.     {
  123.         .type = ARG_TYPE_STRING,
  124.         .buffer = test_buf,
  125.         .len = sizeof(test_buf)
  126.     }
  127. };
  128. static cmd_info_t test_info = {
  129.     .name = "test",
  130.     .description = "Run kernel test.",
  131.     .func = cmd_test,
  132.     .argc = 1,
  133.     .argv = test_argv
  134. };
  135.  
  136. static int cmd_bench(cmd_arg_t *argv);
  137. static cmd_arg_t bench_argv[] = {
  138.     {
  139.         .type = ARG_TYPE_STRING,
  140.         .buffer = test_buf,
  141.         .len = sizeof(test_buf)
  142.     },
  143.     {
  144.         .type = ARG_TYPE_INT,
  145.     }
  146. };
  147. static cmd_info_t bench_info = {
  148.     .name = "bench",
  149.     .description = "Run kernel test as benchmark.",
  150.     .func = cmd_bench,
  151.     .argc = 2,
  152.     .argv = bench_argv
  153. };
  154. #endif
  155.  
  156. /* Data and methods for 'description' command. */
  157. static int cmd_desc(cmd_arg_t *argv);
  158. static void desc_help(void);
  159. static char desc_buf[MAX_CMDLINE+1];
  160. static cmd_arg_t desc_argv = {
  161.     .type = ARG_TYPE_STRING,
  162.     .buffer = desc_buf,
  163.     .len = sizeof(desc_buf)
  164. };
  165. static cmd_info_t desc_info = {
  166.     .name = "describe",
  167.     .description = "Describe specified command.",
  168.     .help = desc_help,
  169.     .func = cmd_desc,
  170.     .argc = 1,
  171.     .argv = &desc_argv
  172. };
  173.  
  174. /* Data and methods for 'symaddr' command. */
  175. static int cmd_symaddr(cmd_arg_t *argv);
  176. static char symaddr_buf[MAX_CMDLINE+1];
  177. static cmd_arg_t symaddr_argv = {
  178.     .type = ARG_TYPE_STRING,
  179.     .buffer = symaddr_buf,
  180.     .len = sizeof(symaddr_buf)
  181. };
  182. static cmd_info_t symaddr_info = {
  183.     .name = "symaddr",
  184.     .description = "Return symbol address.",
  185.     .func = cmd_symaddr,
  186.     .argc = 1,
  187.     .argv = &symaddr_argv
  188. };
  189.  
  190. static char set_buf[MAX_CMDLINE+1];
  191. static int cmd_set4(cmd_arg_t *argv);
  192. static cmd_arg_t set4_argv[] = {
  193.     {
  194.         .type = ARG_TYPE_STRING,
  195.         .buffer = set_buf,
  196.         .len = sizeof(set_buf)
  197.     },
  198.     {
  199.         .type = ARG_TYPE_INT
  200.     }
  201. };
  202. static cmd_info_t set4_info = {
  203.     .name = "set4",
  204.     .description = "set <dest_addr> <value> - 4byte version",
  205.     .func = cmd_set4,
  206.     .argc = 2,
  207.     .argv = set4_argv
  208. };
  209.  
  210. /* Data and methods for 'call0' command. */
  211. static char call0_buf[MAX_CMDLINE + 1];
  212. static char carg1_buf[MAX_CMDLINE + 1];
  213. static char carg2_buf[MAX_CMDLINE + 1];
  214. static char carg3_buf[MAX_CMDLINE + 1];
  215.  
  216. static int cmd_call0(cmd_arg_t *argv);
  217. static cmd_arg_t call0_argv = {
  218.     .type = ARG_TYPE_STRING,
  219.     .buffer = call0_buf,
  220.     .len = sizeof(call0_buf)
  221. };
  222. static cmd_info_t call0_info = {
  223.     .name = "call0",
  224.     .description = "call0 <function> -> call function().",
  225.     .func = cmd_call0,
  226.     .argc = 1,
  227.     .argv = &call0_argv
  228. };
  229.  
  230. /* Data and methods for 'mcall0' command. */
  231. static int cmd_mcall0(cmd_arg_t *argv);
  232. static cmd_arg_t mcall0_argv = {
  233.     .type = ARG_TYPE_STRING,
  234.     .buffer = call0_buf,
  235.     .len = sizeof(call0_buf)
  236. };
  237. static cmd_info_t mcall0_info = {
  238.     .name = "mcall0",
  239.     .description = "mcall0 <function> -> call function() on each CPU.",
  240.     .func = cmd_mcall0,
  241.     .argc = 1,
  242.     .argv = &mcall0_argv
  243. };
  244.  
  245. /* Data and methods for 'call1' command. */
  246. static int cmd_call1(cmd_arg_t *argv);
  247. static cmd_arg_t call1_argv[] = {
  248.     {
  249.         .type = ARG_TYPE_STRING,
  250.         .buffer = call0_buf,
  251.         .len = sizeof(call0_buf)
  252.     },
  253.     {
  254.         .type = ARG_TYPE_VAR,
  255.         .buffer = carg1_buf,
  256.         .len = sizeof(carg1_buf)
  257.     }
  258. };
  259. static cmd_info_t call1_info = {
  260.     .name = "call1",
  261.     .description = "call1 <function> <arg1> -> call function(arg1).",
  262.     .func = cmd_call1,
  263.     .argc = 2,
  264.     .argv = call1_argv
  265. };
  266.  
  267. /* Data and methods for 'call2' command. */
  268. static int cmd_call2(cmd_arg_t *argv);
  269. static cmd_arg_t call2_argv[] = {
  270.     {
  271.         .type = ARG_TYPE_STRING,
  272.         .buffer = call0_buf,
  273.         .len = sizeof(call0_buf)
  274.     },
  275.     {
  276.         .type = ARG_TYPE_VAR,
  277.         .buffer = carg1_buf,
  278.         .len = sizeof(carg1_buf)
  279.     },
  280.     {
  281.         .type = ARG_TYPE_VAR,
  282.         .buffer = carg2_buf,
  283.         .len = sizeof(carg2_buf)
  284.     }
  285. };
  286. static cmd_info_t call2_info = {
  287.     .name = "call2",
  288.     .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
  289.     .func = cmd_call2,
  290.     .argc = 3,
  291.     .argv = call2_argv
  292. };
  293.  
  294. /* Data and methods for 'call3' command. */
  295. static int cmd_call3(cmd_arg_t *argv);
  296. static cmd_arg_t call3_argv[] = {
  297.     {
  298.         .type = ARG_TYPE_STRING,
  299.         .buffer = call0_buf,
  300.         .len = sizeof(call0_buf)
  301.     },
  302.     {
  303.         .type = ARG_TYPE_VAR,
  304.         .buffer = carg1_buf,
  305.         .len = sizeof(carg1_buf)
  306.     },
  307.     {
  308.         .type = ARG_TYPE_VAR,
  309.         .buffer = carg2_buf,
  310.         .len = sizeof(carg2_buf)
  311.     },
  312.     {
  313.         .type = ARG_TYPE_VAR,
  314.         .buffer = carg3_buf,
  315.         .len = sizeof(carg3_buf)
  316.     }
  317.  
  318. };
  319. static cmd_info_t call3_info = {
  320.     .name = "call3",
  321.     .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
  322.     .func = cmd_call3,
  323.     .argc = 4,
  324.     .argv = call3_argv
  325. };
  326.  
  327. /* Data and methods for 'halt' command. */
  328. static int cmd_halt(cmd_arg_t *argv);
  329. static cmd_info_t halt_info = {
  330.     .name = "halt",
  331.     .description = "Halt the kernel.",
  332.     .func = cmd_halt,
  333.     .argc = 0
  334. };
  335.  
  336. /* Data and methods for 'physmem' command. */
  337. static int cmd_physmem(cmd_arg_t *argv);
  338. cmd_info_t physmem_info = {
  339.     .name = "physmem",
  340.     .description = "Print physical memory configuration.",
  341.     .help = NULL,
  342.     .func = cmd_physmem,
  343.     .argc = 0,
  344.     .argv = NULL
  345. };
  346.  
  347. /* Data and methods for 'tlb' command. */
  348. static int cmd_tlb(cmd_arg_t *argv);
  349. cmd_info_t tlb_info = {
  350.     .name = "tlb",
  351.     .description = "Print TLB of current processor.",
  352.     .help = NULL,
  353.     .func = cmd_tlb,
  354.     .argc = 0,
  355.     .argv = NULL
  356. };
  357.  
  358. static int cmd_threads(cmd_arg_t *argv);
  359. static cmd_info_t threads_info = {
  360.     .name = "threads",
  361.     .description = "List all threads.",
  362.     .func = cmd_threads,
  363.     .argc = 0
  364. };
  365.  
  366. static int cmd_tasks(cmd_arg_t *argv);
  367. static cmd_info_t tasks_info = {
  368.     .name = "tasks",
  369.     .description = "List all tasks.",
  370.     .func = cmd_tasks,
  371.     .argc = 0
  372. };
  373.  
  374.  
  375. static int cmd_sched(cmd_arg_t *argv);
  376. static cmd_info_t sched_info = {
  377.     .name = "scheduler",
  378.     .description = "List all scheduler information.",
  379.     .func = cmd_sched,
  380.     .argc = 0
  381. };
  382.  
  383. static int cmd_slabs(cmd_arg_t *argv);
  384. static cmd_info_t slabs_info = {
  385.     .name = "slabs",
  386.     .description = "List slab caches.",
  387.     .func = cmd_slabs,
  388.     .argc = 0
  389. };
  390.  
  391. /* Data and methods for 'zones' command */
  392. static int cmd_zones(cmd_arg_t *argv);
  393. static cmd_info_t zones_info = {
  394.     .name = "zones",
  395.     .description = "List of memory zones.",
  396.     .func = cmd_zones,
  397.     .argc = 0
  398. };
  399.  
  400. /* Data and methods for 'ipc' command */
  401. static int cmd_ipc(cmd_arg_t *argv);
  402. static cmd_arg_t ipc_argv = {
  403.     .type = ARG_TYPE_INT,
  404. };
  405. static cmd_info_t ipc_info = {
  406.     .name = "ipc",
  407.     .description = "ipc <taskid> Show IPC information of given task.",
  408.     .func = cmd_ipc,
  409.     .argc = 1,
  410.     .argv = &ipc_argv
  411. };
  412.  
  413. /* Data and methods for 'zone' command */
  414. static int cmd_zone(cmd_arg_t *argv);
  415. static cmd_arg_t zone_argv = {
  416.     .type = ARG_TYPE_INT,
  417. };
  418.  
  419. static cmd_info_t zone_info = {
  420.     .name = "zone",
  421.     .description = "Show memory zone structure.",
  422.     .func = cmd_zone,
  423.     .argc = 1,
  424.     .argv = &zone_argv
  425. };
  426.  
  427. /* Data and methods for 'cpus' command. */
  428. static int cmd_cpus(cmd_arg_t *argv);
  429. cmd_info_t cpus_info = {
  430.     .name = "cpus",
  431.     .description = "List all processors.",
  432.     .help = NULL,
  433.     .func = cmd_cpus,
  434.     .argc = 0,
  435.     .argv = NULL
  436. };
  437.  
  438. /* Data and methods for 'version' command. */
  439. static int cmd_version(cmd_arg_t *argv);
  440. cmd_info_t version_info = {
  441.     .name = "version",
  442.     .description = "Print version information.",
  443.     .help = NULL,
  444.     .func = cmd_version,
  445.     .argc = 0,
  446.     .argv = NULL
  447. };
  448.  
  449. static cmd_info_t *basic_commands[] = {
  450.     &call0_info,
  451.     &mcall0_info,
  452.     &call1_info,
  453.     &call2_info,
  454.     &call3_info,
  455.     &continue_info,
  456.     &cpus_info,
  457.     &desc_info,
  458.     &exit_info,
  459.     &reboot_info,
  460.     &uptime_info,
  461.     &halt_info,
  462.     &help_info,
  463.     &ipc_info,
  464.     &set4_info,
  465.     &slabs_info,
  466.     &symaddr_info,
  467.     &sched_info,
  468.     &threads_info,
  469.     &tasks_info,
  470.     &physmem_info,
  471.     &tlb_info,
  472.     &version_info,
  473.     &zones_info,
  474.     &zone_info,
  475. #ifdef CONFIG_TEST
  476.     &tests_info,
  477.     &test_info,
  478.     &bench_info,
  479. #endif
  480.     NULL
  481. };
  482.  
  483.  
  484. /** Initialize command info structure.
  485.  *
  486.  * @param cmd Command info structure.
  487.  *
  488.  */
  489. void cmd_initialize(cmd_info_t *cmd)
  490. {
  491.     spinlock_initialize(&cmd->lock, "cmd");
  492.     link_initialize(&cmd->link);
  493. }
  494.  
  495. /** Initialize and register commands. */
  496. void cmd_init(void)
  497. {
  498.     unsigned int i;
  499.  
  500.     for (i = 0; basic_commands[i]; i++) {
  501.         cmd_initialize(basic_commands[i]);
  502.         if (!cmd_register(basic_commands[i]))
  503.             printf("Cannot register command %s\n", basic_commands[i]->name);
  504.     }
  505. }
  506.  
  507.  
  508. /** List supported commands.
  509.  *
  510.  * @param argv Argument vector.
  511.  *
  512.  * @return 0 on failure, 1 on success.
  513.  */
  514. int cmd_help(cmd_arg_t *argv)
  515. {
  516.     link_t *cur;
  517.  
  518.     spinlock_lock(&cmd_lock);
  519.    
  520.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  521.         cmd_info_t *hlp;
  522.        
  523.         hlp = list_get_instance(cur, cmd_info_t, link);
  524.         spinlock_lock(&hlp->lock);
  525.        
  526.         printf("%s - %s\n", hlp->name, hlp->description);
  527.  
  528.         spinlock_unlock(&hlp->lock);
  529.     }
  530.    
  531.     spinlock_unlock(&cmd_lock);
  532.  
  533.     return 1;
  534. }
  535.  
  536.  
  537. /** Reboot the system.
  538.  *
  539.  * @param argv Argument vector.
  540.  *
  541.  * @return 0 on failure, 1 on success.
  542.  */
  543. int cmd_reboot(cmd_arg_t *argv)
  544. {
  545.     reboot();
  546.    
  547.     /* Not reached */
  548.     return 1;
  549. }
  550.  
  551.  
  552. /** Print system uptime information.
  553.  *
  554.  * @param argv Argument vector.
  555.  *
  556.  * @return 0 on failure, 1 on success.
  557.  */
  558. int cmd_uptime(cmd_arg_t *argv)
  559. {
  560.     ASSERT(uptime);
  561.    
  562.     /* This doesn't have to be very accurate */
  563.     unative_t sec = uptime->seconds1;
  564.    
  565.     printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n",
  566.         sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60);
  567.    
  568.     return 1;
  569. }
  570.  
  571. /** Describe specified command.
  572.  *
  573.  * @param argv Argument vector.
  574.  *
  575.  * @return 0 on failure, 1 on success.
  576.  */
  577. int cmd_desc(cmd_arg_t *argv)
  578. {
  579.     link_t *cur;
  580.  
  581.     spinlock_lock(&cmd_lock);
  582.    
  583.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  584.         cmd_info_t *hlp;
  585.        
  586.         hlp = list_get_instance(cur, cmd_info_t, link);
  587.         spinlock_lock(&hlp->lock);
  588.  
  589.         if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
  590.             printf("%s - %s\n", hlp->name, hlp->description);
  591.             if (hlp->help)
  592.                 hlp->help();
  593.             spinlock_unlock(&hlp->lock);
  594.             break;
  595.         }
  596.  
  597.         spinlock_unlock(&hlp->lock);
  598.     }
  599.    
  600.     spinlock_unlock(&cmd_lock);
  601.  
  602.     return 1;
  603. }
  604.  
  605. /** Search symbol table */
  606. int cmd_symaddr(cmd_arg_t *argv)
  607. {
  608.     symtab_print_search((char *) argv->buffer);
  609.    
  610.     return 1;
  611. }
  612.  
  613. /** Call function with zero parameters */
  614. int cmd_call0(cmd_arg_t *argv)
  615. {
  616.     uintptr_t symaddr;
  617.     char *symbol;
  618.     unative_t (*f)(void);
  619. #ifdef ia64
  620.     struct {
  621.         unative_t f;
  622.         unative_t gp;
  623.     } fptr;
  624. #endif
  625.  
  626.     symaddr = get_symbol_addr((char *) argv->buffer);
  627.     if (!symaddr)
  628.         printf("Symbol %s not found.\n", argv->buffer);
  629.     else if (symaddr == (uintptr_t) -1) {
  630.         symtab_print_search((char *) argv->buffer);
  631.         printf("Duplicate symbol, be more specific.\n");
  632.     } else {
  633.         symbol = get_symtab_entry(symaddr);
  634.         printf("Calling %s() (%p)\n", symbol, symaddr);
  635. #ifdef ia64
  636.         fptr.f = symaddr;
  637.         fptr.gp = ((unative_t *)cmd_call2)[1];
  638.         f =  (unative_t (*)(void)) &fptr;
  639. #else
  640.         f =  (unative_t (*)(void)) symaddr;
  641. #endif
  642.         printf("Result: %#" PRIxn "\n", f());
  643.     }
  644.    
  645.     return 1;
  646. }
  647.  
  648. /** Call function with zero parameters on each CPU */
  649. int cmd_mcall0(cmd_arg_t *argv)
  650. {
  651.     /*
  652.      * For each CPU, create a thread which will
  653.      * call the function.
  654.      */
  655.    
  656.     count_t i;
  657.     for (i = 0; i < config.cpu_count; i++) {
  658.         if (!cpus[i].active)
  659.             continue;
  660.        
  661.         thread_t *t;
  662.         if ((t = thread_create((void (*)(void *)) cmd_call0, (void *) argv, TASK, THREAD_FLAG_WIRED, "call0", false))) {
  663.             spinlock_lock(&t->lock);
  664.             t->cpu = &cpus[i];
  665.             spinlock_unlock(&t->lock);
  666.             printf("cpu%u: ", i);
  667.             thread_ready(t);
  668.             thread_join(t);
  669.             thread_detach(t);
  670.         } else
  671.             printf("Unable to create thread for cpu%u\n", i);
  672.     }
  673.    
  674.     return 1;
  675. }
  676.  
  677. /** Call function with one parameter */
  678. int cmd_call1(cmd_arg_t *argv)
  679. {
  680.     uintptr_t symaddr;
  681.     char *symbol;
  682.     unative_t (*f)(unative_t,...);
  683.     unative_t arg1 = argv[1].intval;
  684. #ifdef ia64
  685.     struct {
  686.         unative_t f;
  687.         unative_t gp;
  688.     } fptr;
  689. #endif
  690.  
  691.     symaddr = get_symbol_addr((char *) argv->buffer);
  692.     if (!symaddr)
  693.         printf("Symbol %s not found.\n", argv->buffer);
  694.     else if (symaddr == (uintptr_t) -1) {
  695.         symtab_print_search((char *) argv->buffer);
  696.         printf("Duplicate symbol, be more specific.\n");
  697.     } else {
  698.         symbol = get_symtab_entry(symaddr);
  699.  
  700.         printf("Calling f(%#" PRIxn "): %p: %s\n", arg1, symaddr, symbol);
  701. #ifdef ia64
  702.         fptr.f = symaddr;
  703.         fptr.gp = ((unative_t *)cmd_call2)[1];
  704.         f =  (unative_t (*)(unative_t,...)) &fptr;
  705. #else
  706.         f =  (unative_t (*)(unative_t,...)) symaddr;
  707. #endif
  708.         printf("Result: %#" PRIxn "\n", f(arg1));
  709.     }
  710.    
  711.     return 1;
  712. }
  713.  
  714. /** Call function with two parameters */
  715. int cmd_call2(cmd_arg_t *argv)
  716. {
  717.     uintptr_t symaddr;
  718.     char *symbol;
  719.     unative_t (*f)(unative_t,unative_t,...);
  720.     unative_t arg1 = argv[1].intval;
  721.     unative_t arg2 = argv[2].intval;
  722. #ifdef ia64
  723.     struct {
  724.         unative_t f;
  725.         unative_t gp;
  726.     }fptr;
  727. #endif
  728.  
  729.     symaddr = get_symbol_addr((char *) argv->buffer);
  730.     if (!symaddr)
  731.         printf("Symbol %s not found.\n", argv->buffer);
  732.     else if (symaddr == (uintptr_t) -1) {
  733.         symtab_print_search((char *) argv->buffer);
  734.         printf("Duplicate symbol, be more specific.\n");
  735.     } else {
  736.         symbol = get_symtab_entry(symaddr);
  737.         printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n",
  738.                arg1, arg2, symaddr, symbol);
  739. #ifdef ia64
  740.         fptr.f = symaddr;
  741.         fptr.gp = ((unative_t *)cmd_call2)[1];
  742.         f =  (unative_t (*)(unative_t,unative_t,...)) &fptr;
  743. #else
  744.         f =  (unative_t (*)(unative_t,unative_t,...)) symaddr;
  745. #endif
  746.         printf("Result: %#" PRIxn "\n", f(arg1, arg2));
  747.     }
  748.    
  749.     return 1;
  750. }
  751.  
  752. /** Call function with three parameters */
  753. int cmd_call3(cmd_arg_t *argv)
  754. {
  755.     uintptr_t symaddr;
  756.     char *symbol;
  757.     unative_t (*f)(unative_t,unative_t,unative_t,...);
  758.     unative_t arg1 = argv[1].intval;
  759.     unative_t arg2 = argv[2].intval;
  760.     unative_t arg3 = argv[3].intval;
  761. #ifdef ia64
  762.     struct {
  763.         unative_t f;
  764.         unative_t gp;
  765.     }fptr;
  766. #endif
  767.  
  768.     symaddr = get_symbol_addr((char *) argv->buffer);
  769.     if (!symaddr)
  770.         printf("Symbol %s not found.\n", argv->buffer);
  771.     else if (symaddr == (uintptr_t) -1) {
  772.         symtab_print_search((char *) argv->buffer);
  773.         printf("Duplicate symbol, be more specific.\n");
  774.     } else {
  775.         symbol = get_symtab_entry(symaddr);
  776.         printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n",
  777.                arg1, arg2, arg3, symaddr, symbol);
  778. #ifdef ia64
  779.         fptr.f = symaddr;
  780.         fptr.gp = ((unative_t *)cmd_call2)[1];
  781.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
  782. #else
  783.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
  784. #endif
  785.         printf("Result: %#" PRIxn "\n", f(arg1, arg2, arg3));
  786.     }
  787.    
  788.     return 1;
  789. }
  790.  
  791.  
  792. /** Print detailed description of 'describe' command. */
  793. void desc_help(void)
  794. {
  795.     printf("Syntax: describe command_name\n");
  796. }
  797.  
  798. /** Halt the kernel.
  799.  *
  800.  * @param argv Argument vector (ignored).
  801.  *
  802.  * @return 0 on failure, 1 on success (never returns).
  803.  */
  804. int cmd_halt(cmd_arg_t *argv)
  805. {
  806.     halt();
  807.     return 1;
  808. }
  809.  
  810. /** Command for printing TLB contents.
  811.  *
  812.  * @param argv Not used.
  813.  *
  814.  * @return Always returns 1.
  815.  */
  816. int cmd_tlb(cmd_arg_t *argv)
  817. {
  818.     tlb_print();
  819.     return 1;
  820. }
  821.  
  822. /** Command for printing physical memory configuration.
  823.  *
  824.  * @param argv Not used.
  825.  *
  826.  * @return Always returns 1.
  827.  */
  828. int cmd_physmem(cmd_arg_t *argv)
  829. {
  830.     physmem_print();
  831.     return 1;
  832. }
  833.  
  834. /** Write 4 byte value to address */
  835. int cmd_set4(cmd_arg_t *argv)
  836. {
  837.     uint32_t *addr;
  838.     uint32_t arg1 = argv[1].intval;
  839.     bool pointer = false;
  840.  
  841.     if (((char *)argv->buffer)[0] == '*') {
  842.         addr = (uint32_t *) get_symbol_addr((char *) argv->buffer + 1);
  843.         pointer = true;
  844.     } else if (((char *) argv->buffer)[0] >= '0' &&
  845.            ((char *)argv->buffer)[0] <= '9')
  846.         addr = (uint32_t *)atoi((char *)argv->buffer);
  847.     else
  848.         addr = (uint32_t *)get_symbol_addr((char *) argv->buffer);
  849.  
  850.     if (!addr)
  851.         printf("Symbol %s not found.\n", argv->buffer);
  852.     else if (addr == (uint32_t *) -1) {
  853.         symtab_print_search((char *) argv->buffer);
  854.         printf("Duplicate symbol, be more specific.\n");
  855.     } else {
  856.         if (pointer)
  857.             addr = (uint32_t *)(*(unative_t *)addr);
  858.         printf("Writing %#" PRIx64 " -> %p\n", arg1, addr);
  859.         *addr = arg1;
  860.        
  861.     }
  862.    
  863.     return 1;
  864. }
  865.  
  866. /** Command for listings SLAB caches
  867.  *
  868.  * @param argv Ignores
  869.  *
  870.  * @return Always 1
  871.  */
  872. int cmd_slabs(cmd_arg_t * argv) {
  873.     slab_print_list();
  874.     return 1;
  875. }
  876.  
  877.  
  878. /** Command for listings Thread information
  879.  *
  880.  * @param argv Ignores
  881.  *
  882.  * @return Always 1
  883.  */
  884. int cmd_threads(cmd_arg_t * argv) {
  885.     thread_print_list();
  886.     return 1;
  887. }
  888.  
  889. /** Command for listings Task information
  890.  *
  891.  * @param argv Ignores
  892.  *
  893.  * @return Always 1
  894.  */
  895. int cmd_tasks(cmd_arg_t * argv) {
  896.     task_print_list();
  897.     return 1;
  898. }
  899.  
  900. /** Command for listings Thread information
  901.  *
  902.  * @param argv Ignores
  903.  *
  904.  * @return Always 1
  905.  */
  906. int cmd_sched(cmd_arg_t * argv) {
  907.     sched_print_list();
  908.     return 1;
  909. }
  910.  
  911. /** Command for listing memory zones
  912.  *
  913.  * @param argv Ignored
  914.  *
  915.  * return Always 1
  916.  */
  917. int cmd_zones(cmd_arg_t * argv) {
  918.     zone_print_list();
  919.     return 1;
  920. }
  921.  
  922. /** Command for memory zone details
  923.  *
  924.  * @param argv Integer argument from cmdline expected
  925.  *
  926.  * return Always 1
  927.  */
  928. int cmd_zone(cmd_arg_t * argv) {
  929.     zone_print_one(argv[0].intval);
  930.     return 1;
  931. }
  932.  
  933. /** Command for printing task ipc details
  934.  *
  935.  * @param argv Integer argument from cmdline expected
  936.  *
  937.  * return Always 1
  938.  */
  939. int cmd_ipc(cmd_arg_t * argv) {
  940.     ipc_print_task(argv[0].intval);
  941.     return 1;
  942. }
  943.  
  944.  
  945. /** Command for listing processors.
  946.  *
  947.  * @param argv Ignored.
  948.  *
  949.  * return Always 1.
  950.  */
  951. int cmd_cpus(cmd_arg_t *argv)
  952. {
  953.     cpu_list();
  954.     return 1;
  955. }
  956.  
  957. /** Command for printing kernel version.
  958.  *
  959.  * @param argv Ignored.
  960.  *
  961.  * return Always 1.
  962.  */
  963. int cmd_version(cmd_arg_t *argv)
  964. {
  965.     version_print();
  966.     return 1;
  967. }
  968.  
  969. /** Command for returning console back to userspace.
  970.  *
  971.  * @param argv Ignored.
  972.  *
  973.  * return Always 1.
  974.  */
  975. int cmd_continue(cmd_arg_t *argv)
  976. {
  977.     printf("The kernel will now relinquish the console.\n");
  978.     printf("Use userspace controls to redraw the screen.\n");
  979.     arch_release_console();
  980.     return 1;
  981. }
  982.  
  983. #ifdef CONFIG_TEST
  984. /** Command for printing kernel tests list.
  985.  *
  986.  * @param argv Ignored.
  987.  *
  988.  * return Always 1.
  989.  */
  990. int cmd_tests(cmd_arg_t *argv)
  991. {
  992.     test_t *test;
  993.    
  994.     for (test = tests; test->name != NULL; test++)
  995.         printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
  996.    
  997.     printf("*\t\tRun all safe tests\n");
  998.     return 1;
  999. }
  1000.  
  1001. static bool run_test(const test_t *test)
  1002. {
  1003.     printf("%s\t\t%s\n", test->name, test->desc);
  1004.    
  1005.     /* Update and read thread accounting
  1006.        for benchmarking */
  1007.     ipl_t ipl = interrupts_disable();
  1008.     spinlock_lock(&TASK->lock);
  1009.     uint64_t t0 = task_get_accounting(TASK);
  1010.     spinlock_unlock(&TASK->lock);
  1011.     interrupts_restore(ipl);
  1012.    
  1013.     /* Execute the test */
  1014.     char * ret = test->entry(false);
  1015.    
  1016.     /* Update and read thread accounting */
  1017.     ipl = interrupts_disable();
  1018.     spinlock_lock(&TASK->lock);
  1019.     uint64_t dt = task_get_accounting(TASK) - t0;
  1020.     spinlock_unlock(&TASK->lock);
  1021.     interrupts_restore(ipl);
  1022.    
  1023.     uint64_t cycles;
  1024.     char suffix;
  1025.     order(dt, &cycles, &suffix);
  1026.        
  1027.     printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix);
  1028.    
  1029.     if (ret == NULL) {
  1030.         printf("Test passed\n");
  1031.         return true;
  1032.     }
  1033.  
  1034.     printf("%s\n", ret);
  1035.     return false;
  1036. }
  1037.  
  1038. static bool run_bench(const test_t *test, const uint32_t cnt)
  1039. {
  1040.     uint32_t i;
  1041.     bool ret = true;
  1042.     uint64_t cycles;
  1043.     char suffix;
  1044.    
  1045.     if (cnt < 1)
  1046.         return true;
  1047.    
  1048.     uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
  1049.     if (data == NULL) {
  1050.         printf("Error allocating memory for statistics\n");
  1051.         return false;
  1052.     }
  1053.    
  1054.     for (i = 0; i < cnt; i++) {
  1055.         printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
  1056.        
  1057.         /* Update and read thread accounting
  1058.            for benchmarking */
  1059.         ipl_t ipl = interrupts_disable();
  1060.         spinlock_lock(&TASK->lock);
  1061.         uint64_t t0 = task_get_accounting(TASK);
  1062.         spinlock_unlock(&TASK->lock);
  1063.         interrupts_restore(ipl);
  1064.        
  1065.         /* Execute the test */
  1066.         char * ret = test->entry(true);
  1067.        
  1068.         /* Update and read thread accounting */
  1069.         ipl = interrupts_disable();
  1070.         spinlock_lock(&TASK->lock);
  1071.         uint64_t dt = task_get_accounting(TASK) - t0;
  1072.         spinlock_unlock(&TASK->lock);
  1073.         interrupts_restore(ipl);
  1074.        
  1075.         if (ret != NULL) {
  1076.             printf("%s\n", ret);
  1077.             ret = false;
  1078.             break;
  1079.         }
  1080.        
  1081.         data[i] = dt;
  1082.         order(dt, &cycles, &suffix);
  1083.         printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix);
  1084.     }
  1085.    
  1086.     if (ret) {
  1087.         printf("\n");
  1088.        
  1089.         uint64_t sum = 0;
  1090.        
  1091.         for (i = 0; i < cnt; i++) {
  1092.             sum += data[i];
  1093.         }
  1094.        
  1095.         order(sum / (uint64_t) cnt, &cycles, &suffix);
  1096.         printf("Average\t\t%" PRIu64 "%c\n", cycles, suffix);
  1097.     }
  1098.    
  1099.     free(data);
  1100.    
  1101.     return ret;
  1102. }
  1103.  
  1104. /** Command for returning kernel tests
  1105.  *
  1106.  * @param argv Argument vector.
  1107.  *
  1108.  * return Always 1.
  1109.  */
  1110. int cmd_test(cmd_arg_t *argv)
  1111. {
  1112.     test_t *test;
  1113.    
  1114.     if (strcmp((char *) argv->buffer, "*") == 0) {
  1115.         for (test = tests; test->name != NULL; test++) {
  1116.             if (test->safe) {
  1117.                 printf("\n");
  1118.                 if (!run_test(test))
  1119.                     break;
  1120.             }
  1121.         }
  1122.     } else {
  1123.         bool fnd = false;
  1124.        
  1125.         for (test = tests; test->name != NULL; test++) {
  1126.             if (strcmp(test->name, (char *) argv->buffer) == 0) {
  1127.                 fnd = true;
  1128.                 run_test(test);
  1129.                 break;
  1130.             }
  1131.         }
  1132.        
  1133.         if (!fnd)
  1134.             printf("Unknown test\n");
  1135.     }
  1136.    
  1137.     return 1;
  1138. }
  1139.  
  1140. /** Command for returning kernel tests as benchmarks
  1141.  *
  1142.  * @param argv Argument vector.
  1143.  *
  1144.  * return Always 1.
  1145.  */
  1146. int cmd_bench(cmd_arg_t *argv)
  1147. {
  1148.     test_t *test;
  1149.     uint32_t cnt = argv[1].intval;
  1150.    
  1151.     bool fnd = false;
  1152.    
  1153.     for (test = tests; test->name != NULL; test++) {
  1154.         if (strcmp(test->name, (char *) argv->buffer) == 0) {
  1155.             fnd = true;
  1156.            
  1157.             if (test->safe)
  1158.                 run_bench(test, cnt);
  1159.             else
  1160.                 printf("Unsafe test\n");
  1161.            
  1162.             break;
  1163.         }
  1164.     }
  1165.        
  1166.     if (!fnd)
  1167.         printf("Unknown test\n");
  1168.  
  1169.     return 1;
  1170. }
  1171.  
  1172. #endif
  1173.  
  1174. /** @}
  1175.  */
  1176.