Subversion Repositories HelenOS

Rev

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