source: mainline/kernel/generic/src/console/cmd.c@ df24ec3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since df24ec3 was df4ed85, checked in by Jakub Jermar <jakub@…>, 18 years ago

© versus ©

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