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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0313ff0 was 0313ff0, checked in by Martin Decky <martin@…>, 19 years ago

accumulate task accounting, run tests as separate kernel task

  • Property mode set to 100644
File size: 19.8 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/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. */
74static int cmd_help(cmd_arg_t *argv);
75static cmd_info_t help_info = {
76 .name = "help",
77 .description = "List of supported commands.",
78 .func = cmd_help,
79 .argc = 0
80};
81
82static cmd_info_t exit_info = {
83 .name = "exit",
84 .description = "Exit kconsole",
85 .argc = 0
86};
87
88static int cmd_continue(cmd_arg_t *argv);
89static 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
97static int cmd_tests(cmd_arg_t *argv);
98static cmd_info_t tests_info = {
99 .name = "tests",
100 .description = "Print available kernel tests.",
101 .func = cmd_tests,
102 .argc = 0
103};
104
105static char test_buf[MAX_CMDLINE + 1];
106static int cmd_test(cmd_arg_t *argv);
107static cmd_arg_t test_argv[] = {
108 {
109 .type = ARG_TYPE_STRING,
110 .buffer = test_buf,
111 .len = sizeof(test_buf)
112 }
113};
114static 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. */
124static int cmd_desc(cmd_arg_t *argv);
125static void desc_help(void);
126static char desc_buf[MAX_CMDLINE+1];
127static cmd_arg_t desc_argv = {
128 .type = ARG_TYPE_STRING,
129 .buffer = desc_buf,
130 .len = sizeof(desc_buf)
131};
132static 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. */
142static int cmd_symaddr(cmd_arg_t *argv);
143static char symaddr_buf[MAX_CMDLINE+1];
144static cmd_arg_t symaddr_argv = {
145 .type = ARG_TYPE_STRING,
146 .buffer = symaddr_buf,
147 .len = sizeof(symaddr_buf)
148};
149static 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
157static char set_buf[MAX_CMDLINE+1];
158static int cmd_set4(cmd_arg_t *argv);
159static 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};
169static 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. */
178static char call0_buf[MAX_CMDLINE+1];
179static char carg1_buf[MAX_CMDLINE+1];
180static char carg2_buf[MAX_CMDLINE+1];
181static char carg3_buf[MAX_CMDLINE+1];
182
183static int cmd_call0(cmd_arg_t *argv);
184static cmd_arg_t call0_argv = {
185 .type = ARG_TYPE_STRING,
186 .buffer = call0_buf,
187 .len = sizeof(call0_buf)
188};
189static 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. */
198static int cmd_call1(cmd_arg_t *argv);
199static 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};
211static 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. */
220static int cmd_call2(cmd_arg_t *argv);
221static 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};
238static 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. */
247static int cmd_call3(cmd_arg_t *argv);
248static 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};
271static 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. */
280static int cmd_halt(cmd_arg_t *argv);
281static 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. */
289static int cmd_tlb(cmd_arg_t *argv);
290cmd_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
299static int cmd_threads(cmd_arg_t *argv);
300static cmd_info_t threads_info = {
301 .name = "threads",
302 .description = "List all threads.",
303 .func = cmd_threads,
304 .argc = 0
305};
306
307static int cmd_tasks(cmd_arg_t *argv);
308static cmd_info_t tasks_info = {
309 .name = "tasks",
310 .description = "List all tasks.",
311 .func = cmd_tasks,
312 .argc = 0
313};
314
315
316static int cmd_sched(cmd_arg_t *argv);
317static cmd_info_t sched_info = {
318 .name = "scheduler",
319 .description = "List all scheduler information.",
320 .func = cmd_sched,
321 .argc = 0
322};
323
324static int cmd_slabs(cmd_arg_t *argv);
325static 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 */
333static int cmd_zones(cmd_arg_t *argv);
334static 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 */
342static int cmd_ipc_task(cmd_arg_t *argv);
343static cmd_arg_t ipc_task_argv = {
344 .type = ARG_TYPE_INT,
345};
346static 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 */
355static int cmd_zone(cmd_arg_t *argv);
356static cmd_arg_t zone_argv = {
357 .type = ARG_TYPE_INT,
358};
359
360static 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. */
369static int cmd_cpus(cmd_arg_t *argv);
370cmd_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. */
380static int cmd_version(cmd_arg_t *argv);
381cmd_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
390static 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 */
425void 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. */
432void 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 */
451int 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 */
479int 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 */
508int 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 */
516int 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 */
551int 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 */
588int 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 */
626int 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. */
666void 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 */
677int 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 */
689int cmd_tlb(cmd_arg_t *argv)
690{
691 tlb_print();
692 return 1;
693}
694
695/** Write 4 byte value to address */
696int 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 */
733int 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 */
745int 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 */
756int 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 */
767int 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 */
778int 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 */
789int 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 */
800int 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 */
812int 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 */
824int 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 */
836int 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 */
851int 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
862static 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
896static 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 */
929int 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 */
Note: See TracBrowser for help on using the repository browser.