Subversion Repositories HelenOS

Rev

Rev 2039 | Rev 2050 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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