Subversion Repositories HelenOS

Rev

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