Subversion Repositories HelenOS

Rev

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