Subversion Repositories HelenOS

Rev

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