Subversion Repositories HelenOS

Rev

Rev 2216 | Rev 2224 | 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.         } else
  603.             printf("Unable to create thread for cpu%u\n", i);
  604.     }
  605.    
  606.     return 1;
  607. }
  608.  
  609. /** Call function with one parameter */
  610. int cmd_call1(cmd_arg_t *argv)
  611. {
  612.     uintptr_t symaddr;
  613.     char *symbol;
  614.     unative_t (*f)(unative_t,...);
  615.     unative_t arg1 = argv[1].intval;
  616. #ifdef ia64
  617.     struct {
  618.         unative_t f;
  619.         unative_t gp;
  620.     }fptr;
  621. #endif
  622.  
  623.     symaddr = get_symbol_addr((char *) argv->buffer);
  624.     if (!symaddr)
  625.         printf("Symbol %s not found.\n", argv->buffer);
  626.     else if (symaddr == (uintptr_t) -1) {
  627.         symtab_print_search((char *) argv->buffer);
  628.         printf("Duplicate symbol, be more specific.\n");
  629.     } else {
  630.         symbol = get_symtab_entry(symaddr);
  631.  
  632.         printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
  633. #ifdef ia64
  634.         fptr.f = symaddr;
  635.         fptr.gp = ((unative_t *)cmd_call2)[1];
  636.         f =  (unative_t (*)(unative_t,...)) &fptr;
  637. #else
  638.         f =  (unative_t (*)(unative_t,...)) symaddr;
  639. #endif
  640.         printf("Result: %#zx\n", f(arg1));
  641.     }
  642.    
  643.     return 1;
  644. }
  645.  
  646. /** Call function with two parameters */
  647. int cmd_call2(cmd_arg_t *argv)
  648. {
  649.     uintptr_t symaddr;
  650.     char *symbol;
  651.     unative_t (*f)(unative_t,unative_t,...);
  652.     unative_t arg1 = argv[1].intval;
  653.     unative_t arg2 = argv[2].intval;
  654. #ifdef ia64
  655.     struct {
  656.         unative_t f;
  657.         unative_t gp;
  658.     }fptr;
  659. #endif
  660.  
  661.     symaddr = get_symbol_addr((char *) argv->buffer);
  662.     if (!symaddr)
  663.         printf("Symbol %s not found.\n", argv->buffer);
  664.     else if (symaddr == (uintptr_t) -1) {
  665.         symtab_print_search((char *) argv->buffer);
  666.         printf("Duplicate symbol, be more specific.\n");
  667.     } else {
  668.         symbol = get_symtab_entry(symaddr);
  669.         printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
  670.                arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
  671. #ifdef ia64
  672.         fptr.f = symaddr;
  673.         fptr.gp = ((unative_t *)cmd_call2)[1];
  674.         f =  (unative_t (*)(unative_t,unative_t,...)) &fptr;
  675. #else
  676.         f =  (unative_t (*)(unative_t,unative_t,...)) symaddr;
  677. #endif
  678.         printf("Result: %#zx\n", f(arg1, arg2));
  679.     }
  680.    
  681.     return 1;
  682. }
  683.  
  684. /** Call function with three parameters */
  685. int cmd_call3(cmd_arg_t *argv)
  686. {
  687.     uintptr_t symaddr;
  688.     char *symbol;
  689.     unative_t (*f)(unative_t,unative_t,unative_t,...);
  690.     unative_t arg1 = argv[1].intval;
  691.     unative_t arg2 = argv[2].intval;
  692.     unative_t arg3 = argv[3].intval;
  693. #ifdef ia64
  694.     struct {
  695.         unative_t f;
  696.         unative_t gp;
  697.     }fptr;
  698. #endif
  699.  
  700.     symaddr = get_symbol_addr((char *) argv->buffer);
  701.     if (!symaddr)
  702.         printf("Symbol %s not found.\n", argv->buffer);
  703.     else if (symaddr == (uintptr_t) -1) {
  704.         symtab_print_search((char *) argv->buffer);
  705.         printf("Duplicate symbol, be more specific.\n");
  706.     } else {
  707.         symbol = get_symtab_entry(symaddr);
  708.         printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
  709.                arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
  710. #ifdef ia64
  711.         fptr.f = symaddr;
  712.         fptr.gp = ((unative_t *)cmd_call2)[1];
  713.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
  714. #else
  715.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
  716. #endif
  717.         printf("Result: %#zx\n", f(arg1, arg2, arg3));
  718.     }
  719.    
  720.     return 1;
  721. }
  722.  
  723.  
  724. /** Print detailed description of 'describe' command. */
  725. void desc_help(void)
  726. {
  727.     printf("Syntax: describe command_name\n");
  728. }
  729.  
  730. /** Halt the kernel.
  731.  *
  732.  * @param argv Argument vector (ignored).
  733.  *
  734.  * @return 0 on failure, 1 on success (never returns).
  735.  */
  736. int cmd_halt(cmd_arg_t *argv)
  737. {
  738.     halt();
  739.     return 1;
  740. }
  741.  
  742. /** Command for printing TLB contents.
  743.  *
  744.  * @param argv Not used.
  745.  *
  746.  * @return Always returns 1.
  747.  */
  748. int cmd_tlb(cmd_arg_t *argv)
  749. {
  750.     tlb_print();
  751.     return 1;
  752. }
  753.  
  754. /** Write 4 byte value to address */
  755. int cmd_set4(cmd_arg_t *argv)
  756. {
  757.     uint32_t *addr;
  758.     uint32_t arg1 = argv[1].intval;
  759.     bool pointer = false;
  760.  
  761.     if (((char *)argv->buffer)[0] == '*') {
  762.         addr = (uint32_t *) get_symbol_addr((char *) argv->buffer + 1);
  763.         pointer = true;
  764.     } else if (((char *) argv->buffer)[0] >= '0' &&
  765.            ((char *)argv->buffer)[0] <= '9')
  766.         addr = (uint32_t *)atoi((char *)argv->buffer);
  767.     else
  768.         addr = (uint32_t *)get_symbol_addr((char *) argv->buffer);
  769.  
  770.     if (!addr)
  771.         printf("Symbol %s not found.\n", argv->buffer);
  772.     else if (addr == (uint32_t *) -1) {
  773.         symtab_print_search((char *) argv->buffer);
  774.         printf("Duplicate symbol, be more specific.\n");
  775.     } else {
  776.         if (pointer)
  777.             addr = (uint32_t *)(*(unative_t *)addr);
  778.         printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
  779.         *addr = arg1;
  780.        
  781.     }
  782.    
  783.     return 1;
  784. }
  785.  
  786. /** Command for listings SLAB caches
  787.  *
  788.  * @param argv Ignores
  789.  *
  790.  * @return Always 1
  791.  */
  792. int cmd_slabs(cmd_arg_t * argv) {
  793.     slab_print_list();
  794.     return 1;
  795. }
  796.  
  797.  
  798. /** Command for listings Thread information
  799.  *
  800.  * @param argv Ignores
  801.  *
  802.  * @return Always 1
  803.  */
  804. int cmd_threads(cmd_arg_t * argv) {
  805.     thread_print_list();
  806.     return 1;
  807. }
  808.  
  809. /** Command for listings Task information
  810.  *
  811.  * @param argv Ignores
  812.  *
  813.  * @return Always 1
  814.  */
  815. int cmd_tasks(cmd_arg_t * argv) {
  816.     task_print_list();
  817.     return 1;
  818. }
  819.  
  820. /** Command for listings Thread information
  821.  *
  822.  * @param argv Ignores
  823.  *
  824.  * @return Always 1
  825.  */
  826. int cmd_sched(cmd_arg_t * argv) {
  827.     sched_print_list();
  828.     return 1;
  829. }
  830.  
  831. /** Command for listing memory zones
  832.  *
  833.  * @param argv Ignored
  834.  *
  835.  * return Always 1
  836.  */
  837. int cmd_zones(cmd_arg_t * argv) {
  838.     zone_print_list();
  839.     return 1;
  840. }
  841.  
  842. /** Command for memory zone details
  843.  *
  844.  * @param argv Integer argument from cmdline expected
  845.  *
  846.  * return Always 1
  847.  */
  848. int cmd_zone(cmd_arg_t * argv) {
  849.     zone_print_one(argv[0].intval);
  850.     return 1;
  851. }
  852.  
  853. /** Command for printing task ipc details
  854.  *
  855.  * @param argv Integer argument from cmdline expected
  856.  *
  857.  * return Always 1
  858.  */
  859. int cmd_ipc_task(cmd_arg_t * argv) {
  860.     ipc_print_task(argv[0].intval);
  861.     return 1;
  862. }
  863.  
  864.  
  865. /** Command for listing processors.
  866.  *
  867.  * @param argv Ignored.
  868.  *
  869.  * return Always 1.
  870.  */
  871. int cmd_cpus(cmd_arg_t *argv)
  872. {
  873.     cpu_list();
  874.     return 1;
  875. }
  876.  
  877. /** Command for printing kernel version.
  878.  *
  879.  * @param argv Ignored.
  880.  *
  881.  * return Always 1.
  882.  */
  883. int cmd_version(cmd_arg_t *argv)
  884. {
  885.     version_print();
  886.     return 1;
  887. }
  888.  
  889. /** Command for returning console back to userspace.
  890.  *
  891.  * @param argv Ignored.
  892.  *
  893.  * return Always 1.
  894.  */
  895. int cmd_continue(cmd_arg_t *argv)
  896. {
  897.     printf("The kernel will now relinquish the console.\n");
  898.     printf("Use userspace controls to redraw the screen.\n");
  899.     arch_release_console();
  900.     return 1;
  901. }
  902.  
  903. #ifdef CONFIG_TEST
  904. /** Command for printing kernel tests list.
  905.  *
  906.  * @param argv Ignored.
  907.  *
  908.  * return Always 1.
  909.  */
  910. int cmd_tests(cmd_arg_t *argv)
  911. {
  912.     test_t *test;
  913.    
  914.     for (test = tests; test->name != NULL; test++)
  915.         printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
  916.    
  917.     printf("*\t\tRun all safe tests\n");
  918.     return 1;
  919. }
  920.  
  921. static bool run_test(const test_t *test)
  922. {
  923.     printf("%s\t\t%s\n", test->name, test->desc);
  924.    
  925.     /* Update and read thread accounting
  926.        for benchmarking */
  927.     ipl_t ipl = interrupts_disable();
  928.     spinlock_lock(&TASK->lock);
  929.     uint64_t t0 = task_get_accounting(TASK);
  930.     spinlock_unlock(&TASK->lock);
  931.     interrupts_restore(ipl);
  932.    
  933.     /* Execute the test */
  934.     char * ret = test->entry(false);
  935.    
  936.     /* Update and read thread accounting */
  937.     ipl = interrupts_disable();
  938.     spinlock_lock(&TASK->lock);
  939.     uint64_t dt = task_get_accounting(TASK) - t0;
  940.     spinlock_unlock(&TASK->lock);
  941.     interrupts_restore(ipl);
  942.    
  943.     uint64_t cycles;
  944.     char suffix;
  945.     order(dt, &cycles, &suffix);
  946.        
  947.     printf("Time: %llu%c cycles\n", cycles, suffix);
  948.    
  949.     if (ret == NULL) {
  950.         printf("Test passed\n");
  951.         return true;
  952.     }
  953.  
  954.     printf("%s\n", ret);
  955.     return false;
  956. }
  957.  
  958. static bool run_bench(const test_t *test, const uint32_t cnt)
  959. {
  960.     uint32_t i;
  961.     bool ret = true;
  962.     uint64_t cycles;
  963.     char suffix;
  964.    
  965.     if (cnt < 1)
  966.         return true;
  967.    
  968.     uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
  969.     if (data == NULL) {
  970.         printf("Error allocating memory for statistics\n");
  971.         return false;
  972.     }
  973.    
  974.     for (i = 0; i < cnt; i++) {
  975.         printf("%s (%d/%d) ... ", test->name, i + 1, cnt);
  976.        
  977.         /* Update and read thread accounting
  978.            for benchmarking */
  979.         ipl_t ipl = interrupts_disable();
  980.         spinlock_lock(&TASK->lock);
  981.         uint64_t t0 = task_get_accounting(TASK);
  982.         spinlock_unlock(&TASK->lock);
  983.         interrupts_restore(ipl);
  984.        
  985.         /* Execute the test */
  986.         char * ret = test->entry(true);
  987.        
  988.         /* Update and read thread accounting */
  989.         ipl = interrupts_disable();
  990.         spinlock_lock(&TASK->lock);
  991.         uint64_t dt = task_get_accounting(TASK) - t0;
  992.         spinlock_unlock(&TASK->lock);
  993.         interrupts_restore(ipl);
  994.        
  995.         if (ret != NULL) {
  996.             printf("%s\n", ret);
  997.             ret = false;
  998.             break;
  999.         }
  1000.        
  1001.         data[i] = dt;
  1002.         order(dt, &cycles, &suffix);
  1003.         printf("OK (%llu%c cycles)\n", cycles, suffix);
  1004.     }
  1005.    
  1006.     if (ret) {
  1007.         printf("\n");
  1008.        
  1009.         uint64_t sum = 0;
  1010.        
  1011.         for (i = 0; i < cnt; i++) {
  1012.             sum += data[i];
  1013.         }
  1014.        
  1015.         order(sum / (uint64_t) cnt, &cycles, &suffix);
  1016.         printf("Average\t\t%llu%c\n", cycles, suffix);
  1017.     }
  1018.    
  1019.     free(data);
  1020.    
  1021.     return ret;
  1022. }
  1023.  
  1024. /** Command for returning kernel tests
  1025.  *
  1026.  * @param argv Argument vector.
  1027.  *
  1028.  * return Always 1.
  1029.  */
  1030. int cmd_test(cmd_arg_t *argv)
  1031. {
  1032.     test_t *test;
  1033.    
  1034.     if (strcmp((char *) argv->buffer, "*") == 0) {
  1035.         for (test = tests; test->name != NULL; test++) {
  1036.             if (test->safe) {
  1037.                 printf("\n");
  1038.                 if (!run_test(test))
  1039.                     break;
  1040.             }
  1041.         }
  1042.     } else {
  1043.         bool fnd = false;
  1044.        
  1045.         for (test = tests; test->name != NULL; test++) {
  1046.             if (strcmp(test->name, (char *) argv->buffer) == 0) {
  1047.                 fnd = true;
  1048.                 run_test(test);
  1049.                 break;
  1050.             }
  1051.         }
  1052.        
  1053.         if (!fnd)
  1054.             printf("Unknown test\n");
  1055.     }
  1056.    
  1057.     return 1;
  1058. }
  1059.  
  1060. /** Command for returning kernel tests as benchmarks
  1061.  *
  1062.  * @param argv Argument vector.
  1063.  *
  1064.  * return Always 1.
  1065.  */
  1066. int cmd_bench(cmd_arg_t *argv)
  1067. {
  1068.     test_t *test;
  1069.     uint32_t cnt = argv[1].intval;
  1070.    
  1071.     bool fnd = false;
  1072.    
  1073.     for (test = tests; test->name != NULL; test++) {
  1074.         if (strcmp(test->name, (char *) argv->buffer) == 0) {
  1075.             fnd = true;
  1076.            
  1077.             if (test->safe)
  1078.                 run_bench(test, cnt);
  1079.             else
  1080.                 printf("Unsafe test\n");
  1081.            
  1082.             break;
  1083.         }
  1084.     }
  1085.        
  1086.     if (!fnd)
  1087.         printf("Unknown test\n");
  1088.  
  1089.     return 1;
  1090. }
  1091.  
  1092. #endif
  1093.  
  1094. /** @}
  1095.  */
  1096.