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

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

cstyle

  • Property mode set to 100644
File size: 34.1 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 <adt/list.h>
50#include <arch.h>
51#include <config.h>
52#include <func.h>
53#include <str.h>
54#include <macros.h>
55#include <debug.h>
56#include <cpu.h>
57#include <mm/tlb.h>
58#include <mm/km.h>
59#include <arch/mm/tlb.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#include <ipc/event.h>
69#include <sysinfo/sysinfo.h>
70#include <symtab.h>
71#include <errno.h>
72
73#ifdef CONFIG_TEST
74#include <test.h>
75#endif
76
77/* Data and methods for 'help' command. */
78static int cmd_help(cmd_arg_t *argv);
79static cmd_info_t help_info = {
80 .name = "help",
81 .description = "List supported commands.",
82 .func = cmd_help,
83 .argc = 0
84};
85
86/* Data and methods for pio_read_8 command */
87static int cmd_pio_read_8(cmd_arg_t *argv);
88static cmd_arg_t pio_read_8_argv[] = { { .type = ARG_TYPE_INT } };
89static cmd_info_t pio_read_8_info = {
90 .name = "pio_read_8",
91 .description = "pio_read_8 <address> Read 1 byte from memory (or port).",
92 .func = cmd_pio_read_8,
93 .argc = 1,
94 .argv = pio_read_8_argv
95};
96
97/* Data and methods for pio_read_16 command */
98static int cmd_pio_read_16(cmd_arg_t *argv);
99static cmd_arg_t pio_read_16_argv[] = { { .type = ARG_TYPE_INT } };
100static cmd_info_t pio_read_16_info = {
101 .name = "pio_read_16",
102 .description = "pio_read_16 <address> Read 2 bytes from memory (or port).",
103 .func = cmd_pio_read_16,
104 .argc = 1,
105 .argv = pio_read_16_argv
106};
107
108/* Data and methods for pio_read_32 command */
109static int cmd_pio_read_32(cmd_arg_t *argv);
110static cmd_arg_t pio_read_32_argv[] = { { .type = ARG_TYPE_INT } };
111static cmd_info_t pio_read_32_info = {
112 .name = "pio_read_32",
113 .description = "pio_read_32 <address> Read 4 bytes from memory (or port).",
114 .func = cmd_pio_read_32,
115 .argc = 1,
116 .argv = pio_read_32_argv
117};
118
119/* Data and methods for pio_write_8 command */
120static int cmd_pio_write_8(cmd_arg_t *argv);
121static cmd_arg_t pio_write_8_argv[] = {
122 { .type = ARG_TYPE_INT },
123 { .type = ARG_TYPE_INT }
124};
125static cmd_info_t pio_write_8_info = {
126 .name = "pio_write_8",
127 .description = "pio_write_8 <address> <value> Write 1 byte to memory (or port).",
128 .func = cmd_pio_write_8,
129 .argc = 2,
130 .argv = pio_write_8_argv
131};
132
133/* Data and methods for pio_write_16 command */
134static int cmd_pio_write_16(cmd_arg_t *argv);
135static cmd_arg_t pio_write_16_argv[] = {
136 { .type = ARG_TYPE_INT },
137 { .type = ARG_TYPE_INT }
138};
139static cmd_info_t pio_write_16_info = {
140 .name = "pio_write_16",
141 .description = "pio_write_16 <address> <value> Write 2 bytes to memory (or port).",
142 .func = cmd_pio_write_16,
143 .argc = 2,
144 .argv = pio_write_16_argv
145};
146
147/* Data and methods for pio_write_32 command */
148static int cmd_pio_write_32(cmd_arg_t *argv);
149static cmd_arg_t pio_write_32_argv[] = {
150 { .type = ARG_TYPE_INT },
151 { .type = ARG_TYPE_INT }
152};
153static cmd_info_t pio_write_32_info = {
154 .name = "pio_write_32",
155 .description = "pio_write_32 <address> <value> Write 4 bytes to memory (or port).",
156 .func = cmd_pio_write_32,
157 .argc = 2,
158 .argv = pio_write_32_argv
159};
160
161/* Data and methods for 'reboot' command. */
162static int cmd_reboot(cmd_arg_t *argv);
163static cmd_info_t reboot_info = {
164 .name = "reboot",
165 .description = "Reboot system.",
166 .func = cmd_reboot,
167 .argc = 0
168};
169
170/* Data and methods for 'uptime' command. */
171static int cmd_uptime(cmd_arg_t *argv);
172static cmd_info_t uptime_info = {
173 .name = "uptime",
174 .description = "Show system uptime.",
175 .func = cmd_uptime,
176 .argc = 0
177};
178
179/* Data and methods for 'continue' command. */
180static int cmd_continue(cmd_arg_t *argv);
181static cmd_info_t continue_info = {
182 .name = "continue",
183 .description = "Return console back to userspace.",
184 .func = cmd_continue,
185 .argc = 0
186};
187
188#ifdef CONFIG_TEST
189
190/* Data and methods for 'test' command. */
191static char test_buf[MAX_CMDLINE + 1];
192static int cmd_test(cmd_arg_t *argv);
193static cmd_arg_t test_argv[] = {
194 {
195 .type = ARG_TYPE_STRING_OPTIONAL,
196 .buffer = test_buf,
197 .len = sizeof(test_buf)
198 }
199};
200static cmd_info_t test_info = {
201 .name = "test",
202 .description = "<test> List kernel tests or run a test.",
203 .func = cmd_test,
204 .argc = 1,
205 .argv = test_argv
206};
207
208/* Data and methods for 'bench' command. */
209static int cmd_bench(cmd_arg_t *argv);
210static cmd_arg_t bench_argv[] = {
211 {
212 .type = ARG_TYPE_STRING,
213 .buffer = test_buf,
214 .len = sizeof(test_buf)
215 },
216 {
217 .type = ARG_TYPE_INT,
218 }
219};
220static cmd_info_t bench_info = {
221 .name = "bench",
222 .description = "<test> <count> Run kernel test as benchmark.",
223 .func = cmd_bench,
224 .argc = 2,
225 .argv = bench_argv
226};
227
228#endif /* CONFIG_TEST */
229
230/* Data and methods for 'description' command. */
231static int cmd_desc(cmd_arg_t *argv);
232static void desc_help(void);
233static char desc_buf[MAX_CMDLINE + 1];
234static cmd_arg_t desc_argv = {
235 .type = ARG_TYPE_STRING,
236 .buffer = desc_buf,
237 .len = sizeof(desc_buf)
238};
239static cmd_info_t desc_info = {
240 .name = "describe",
241 .description = "<command> Describe specified command.",
242 .help = desc_help,
243 .func = cmd_desc,
244 .argc = 1,
245 .argv = &desc_argv
246};
247
248/* Data and methods for 'symaddr' command. */
249static int cmd_symaddr(cmd_arg_t *argv);
250static char symaddr_buf[MAX_CMDLINE + 1];
251static cmd_arg_t symaddr_argv = {
252 .type = ARG_TYPE_STRING,
253 .buffer = symaddr_buf,
254 .len = sizeof(symaddr_buf)
255};
256static cmd_info_t symaddr_info = {
257 .name = "symaddr",
258 .description = "<symbol> Return symbol address.",
259 .func = cmd_symaddr,
260 .argc = 1,
261 .argv = &symaddr_argv
262};
263
264/* Data and methods for 'set4' command. */
265static char set_buf[MAX_CMDLINE + 1];
266static int cmd_set4(cmd_arg_t *argv);
267static cmd_arg_t set4_argv[] = {
268 {
269 .type = ARG_TYPE_STRING,
270 .buffer = set_buf,
271 .len = sizeof(set_buf)
272 },
273 {
274 .type = ARG_TYPE_INT
275 }
276};
277static cmd_info_t set4_info = {
278 .name = "set4",
279 .description = "<addr> <value> Set 4B memory location to a value.",
280 .func = cmd_set4,
281 .argc = 2,
282 .argv = set4_argv
283};
284
285/* Data and methods for 'call0' and 'mcall0' command. */
286static char call0_buf[MAX_CMDLINE + 1];
287static char carg1_buf[MAX_CMDLINE + 1];
288static char carg2_buf[MAX_CMDLINE + 1];
289static char carg3_buf[MAX_CMDLINE + 1];
290
291static int cmd_call0(cmd_arg_t *argv);
292static cmd_arg_t call0_argv = {
293 .type = ARG_TYPE_STRING,
294 .buffer = call0_buf,
295 .len = sizeof(call0_buf)
296};
297static cmd_info_t call0_info = {
298 .name = "call0",
299 .description = "<function> Call function().",
300 .func = cmd_call0,
301 .argc = 1,
302 .argv = &call0_argv
303};
304
305/* Data and methods for 'mcall0' command. */
306static int cmd_mcall0(cmd_arg_t *argv);
307static cmd_arg_t mcall0_argv = {
308 .type = ARG_TYPE_STRING,
309 .buffer = call0_buf,
310 .len = sizeof(call0_buf)
311};
312static cmd_info_t mcall0_info = {
313 .name = "mcall0",
314 .description = "<function> Call function() on each CPU.",
315 .func = cmd_mcall0,
316 .argc = 1,
317 .argv = &mcall0_argv
318};
319
320/* Data and methods for 'call1' command. */
321static int cmd_call1(cmd_arg_t *argv);
322static cmd_arg_t call1_argv[] = {
323 {
324 .type = ARG_TYPE_STRING,
325 .buffer = call0_buf,
326 .len = sizeof(call0_buf)
327 },
328 {
329 .type = ARG_TYPE_VAR,
330 .buffer = carg1_buf,
331 .len = sizeof(carg1_buf)
332 }
333};
334static cmd_info_t call1_info = {
335 .name = "call1",
336 .description = "<function> <arg1> Call function(arg1).",
337 .func = cmd_call1,
338 .argc = 2,
339 .argv = call1_argv
340};
341
342/* Data and methods for 'call2' command. */
343static int cmd_call2(cmd_arg_t *argv);
344static cmd_arg_t call2_argv[] = {
345 {
346 .type = ARG_TYPE_STRING,
347 .buffer = call0_buf,
348 .len = sizeof(call0_buf)
349 },
350 {
351 .type = ARG_TYPE_VAR,
352 .buffer = carg1_buf,
353 .len = sizeof(carg1_buf)
354 },
355 {
356 .type = ARG_TYPE_VAR,
357 .buffer = carg2_buf,
358 .len = sizeof(carg2_buf)
359 }
360};
361static cmd_info_t call2_info = {
362 .name = "call2",
363 .description = "<function> <arg1> <arg2> Call function(arg1, arg2).",
364 .func = cmd_call2,
365 .argc = 3,
366 .argv = call2_argv
367};
368
369/* Data and methods for 'call3' command. */
370static int cmd_call3(cmd_arg_t *argv);
371static cmd_arg_t call3_argv[] = {
372 {
373 .type = ARG_TYPE_STRING,
374 .buffer = call0_buf,
375 .len = sizeof(call0_buf)
376 },
377 {
378 .type = ARG_TYPE_VAR,
379 .buffer = carg1_buf,
380 .len = sizeof(carg1_buf)
381 },
382 {
383 .type = ARG_TYPE_VAR,
384 .buffer = carg2_buf,
385 .len = sizeof(carg2_buf)
386 },
387 {
388 .type = ARG_TYPE_VAR,
389 .buffer = carg3_buf,
390 .len = sizeof(carg3_buf)
391 }
392
393};
394static cmd_info_t call3_info = {
395 .name = "call3",
396 .description = "<function> <arg1> <arg2> <arg3> Call function(arg1, arg2, arg3).",
397 .func = cmd_call3,
398 .argc = 4,
399 .argv = call3_argv
400};
401
402/* Data and methods for 'halt' command. */
403static int cmd_halt(cmd_arg_t *argv);
404static cmd_info_t halt_info = {
405 .name = "halt",
406 .description = "Halt the kernel.",
407 .func = cmd_halt,
408 .argc = 0
409};
410
411/* Data and methods for 'physmem' command. */
412static int cmd_physmem(cmd_arg_t *argv);
413cmd_info_t physmem_info = {
414 .name = "physmem",
415 .description = "Print physical memory configuration.",
416 .help = NULL,
417 .func = cmd_physmem,
418 .argc = 0,
419 .argv = NULL
420};
421
422/* Data and methods for 'tlb' command. */
423static int cmd_tlb(cmd_arg_t *argv);
424cmd_info_t tlb_info = {
425 .name = "tlb",
426 .description = "Print TLB of the current CPU.",
427 .help = NULL,
428 .func = cmd_tlb,
429 .argc = 0,
430 .argv = NULL
431};
432
433static char flag_buf[MAX_CMDLINE + 1];
434
435static int cmd_threads(cmd_arg_t *argv);
436static cmd_arg_t threads_argv = {
437 .type = ARG_TYPE_STRING_OPTIONAL,
438 .buffer = flag_buf,
439 .len = sizeof(flag_buf)
440};
441static cmd_info_t threads_info = {
442 .name = "threads",
443 .description = "List all threads (use -a for additional information).",
444 .func = cmd_threads,
445 .argc = 1,
446 .argv = &threads_argv
447};
448
449static int cmd_tasks(cmd_arg_t *argv);
450static cmd_arg_t tasks_argv = {
451 .type = ARG_TYPE_STRING_OPTIONAL,
452 .buffer = flag_buf,
453 .len = sizeof(flag_buf)
454};
455static cmd_info_t tasks_info = {
456 .name = "tasks",
457 .description = "List all tasks (use -a for additional information).",
458 .func = cmd_tasks,
459 .argc = 1,
460 .argv = &tasks_argv
461};
462
463#ifdef CONFIG_UDEBUG
464
465/* Data and methods for 'btrace' command */
466static int cmd_btrace(cmd_arg_t *argv);
467static cmd_arg_t btrace_argv = {
468 .type = ARG_TYPE_INT,
469};
470static cmd_info_t btrace_info = {
471 .name = "btrace",
472 .description = "<threadid> Show thread stack trace.",
473 .func = cmd_btrace,
474 .argc = 1,
475 .argv = &btrace_argv
476};
477
478#endif /* CONFIG_UDEBUG */
479
480static int cmd_sched(cmd_arg_t *argv);
481static cmd_info_t sched_info = {
482 .name = "scheduler",
483 .description = "Show scheduler information.",
484 .func = cmd_sched,
485 .argc = 0
486};
487
488static int cmd_slabs(cmd_arg_t *argv);
489static cmd_info_t slabs_info = {
490 .name = "slabs",
491 .description = "List slab caches.",
492 .func = cmd_slabs,
493 .argc = 0
494};
495
496static int cmd_sysinfo(cmd_arg_t *argv);
497static cmd_info_t sysinfo_info = {
498 .name = "sysinfo",
499 .description = "Dump sysinfo.",
500 .func = cmd_sysinfo,
501 .argc = 0
502};
503
504/* Data and methods for 'zones' command */
505static int cmd_zones(cmd_arg_t *argv);
506static cmd_info_t zones_info = {
507 .name = "zones",
508 .description = "List memory zones.",
509 .func = cmd_zones,
510 .argc = 0
511};
512
513/* Data and methods for 'zone' command */
514static int cmd_zone(cmd_arg_t *argv);
515static cmd_arg_t zone_argv = {
516 .type = ARG_TYPE_INT,
517};
518
519static cmd_info_t zone_info = {
520 .name = "zone",
521 .description = "<zone> Show memory zone structure.",
522 .func = cmd_zone,
523 .argc = 1,
524 .argv = &zone_argv
525};
526
527/* Data and methods for 'ipc' command */
528static int cmd_ipc(cmd_arg_t *argv);
529static cmd_arg_t ipc_argv = {
530 .type = ARG_TYPE_INT,
531};
532static cmd_info_t ipc_info = {
533 .name = "ipc",
534 .description = "<taskid> Show IPC information of a task.",
535 .func = cmd_ipc,
536 .argc = 1,
537 .argv = &ipc_argv
538};
539
540/* Data and methods for 'kill' command */
541static int cmd_kill(cmd_arg_t *argv);
542static cmd_arg_t kill_argv = {
543 .type = ARG_TYPE_INT,
544};
545static cmd_info_t kill_info = {
546 .name = "kill",
547 .description = "<taskid> Kill a task.",
548 .func = cmd_kill,
549 .argc = 1,
550 .argv = &kill_argv
551};
552
553/* Data and methods for 'cpus' command. */
554static int cmd_cpus(cmd_arg_t *argv);
555cmd_info_t cpus_info = {
556 .name = "cpus",
557 .description = "List all processors.",
558 .help = NULL,
559 .func = cmd_cpus,
560 .argc = 0,
561 .argv = NULL
562};
563
564/* Data and methods for 'version' command. */
565static int cmd_version(cmd_arg_t *argv);
566cmd_info_t version_info = {
567 .name = "version",
568 .description = "Print version information.",
569 .help = NULL,
570 .func = cmd_version,
571 .argc = 0,
572 .argv = NULL
573};
574
575static cmd_info_t *basic_commands[] = {
576 &call0_info,
577 &mcall0_info,
578 &call1_info,
579 &call2_info,
580 &call3_info,
581 &continue_info,
582 &cpus_info,
583 &desc_info,
584 &halt_info,
585 &help_info,
586 &ipc_info,
587 &kill_info,
588 &physmem_info,
589 &reboot_info,
590 &sched_info,
591 &set4_info,
592 &slabs_info,
593 &symaddr_info,
594 &sysinfo_info,
595 &tasks_info,
596 &threads_info,
597 &tlb_info,
598 &uptime_info,
599 &version_info,
600 &zones_info,
601 &zone_info,
602#ifdef CONFIG_TEST
603 &test_info,
604 &bench_info,
605#endif
606#ifdef CONFIG_UDEBUG
607 &btrace_info,
608#endif
609 &pio_read_8_info,
610 &pio_read_16_info,
611 &pio_read_32_info,
612 &pio_write_8_info,
613 &pio_write_16_info,
614 &pio_write_32_info,
615 NULL
616};
617
618
619/** Initialize command info structure.
620 *
621 * @param cmd Command info structure.
622 *
623 */
624void cmd_initialize(cmd_info_t *cmd)
625{
626 spinlock_initialize(&cmd->lock, "cmd.lock");
627 link_initialize(&cmd->link);
628}
629
630/** Initialize and register commands. */
631void cmd_init(void)
632{
633 unsigned int i;
634
635 for (i = 0; basic_commands[i]; i++) {
636 cmd_initialize(basic_commands[i]);
637 }
638
639 for (i = 0; basic_commands[i]; i++) {
640 if (!cmd_register(basic_commands[i])) {
641 printf("Cannot register command %s\n",
642 basic_commands[i]->name);
643 }
644 }
645}
646
647/** List supported commands.
648 *
649 * @param argv Argument vector.
650 *
651 * @return 0 on failure, 1 on success.
652 */
653int cmd_help(cmd_arg_t *argv)
654{
655 spinlock_lock(&cmd_lock);
656
657 size_t len = 0;
658 list_foreach(cmd_list, cur) {
659 cmd_info_t *hlp;
660 hlp = list_get_instance(cur, cmd_info_t, link);
661
662 spinlock_lock(&hlp->lock);
663 if (str_length(hlp->name) > len)
664 len = str_length(hlp->name);
665 spinlock_unlock(&hlp->lock);
666 }
667
668 unsigned int _len = (unsigned int) len;
669 if ((_len != len) || (((int) _len) < 0)) {
670 printf("Command length overflow\n");
671 return 1;
672 }
673
674 list_foreach(cmd_list, cur) {
675 cmd_info_t *hlp;
676 hlp = list_get_instance(cur, cmd_info_t, link);
677
678 spinlock_lock(&hlp->lock);
679 printf("%-*s %s\n", _len, hlp->name, hlp->description);
680 spinlock_unlock(&hlp->lock);
681 }
682
683 spinlock_unlock(&cmd_lock);
684
685 return 1;
686}
687
688/** Read 1 byte from phys memory or io port.
689 *
690 * @param argv Argument vector.
691 *
692 * @return 0 on failure, 1 on success.
693 */
694static int cmd_pio_read_8(cmd_arg_t *argv)
695{
696 uint8_t *ptr = NULL;
697
698#ifdef IO_SPACE_BOUNDARY
699 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
700 ptr = (void *) argv[0].intval;
701 else
702#endif
703 ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
704 PAGE_NOT_CACHEABLE);
705
706 const uint8_t val = pio_read_8(ptr);
707 printf("read %" PRIxn ": %" PRIx8 "\n", argv[0].intval, val);
708
709#ifdef IO_SPACE_BOUNDARY
710 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
711 return 1;
712#endif
713
714 km_unmap((uintptr_t) ptr, sizeof(uint8_t));
715 return 1;
716}
717
718/** Read 2 bytes from phys memory or io port.
719 *
720 * @param argv Argument vector.
721 *
722 * @return 0 on failure, 1 on success.
723 */
724static int cmd_pio_read_16(cmd_arg_t *argv)
725{
726 uint16_t *ptr = NULL;
727
728#ifdef IO_SPACE_BOUNDARY
729 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
730 ptr = (void *) argv[0].intval;
731 else
732#endif
733 ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
734 PAGE_NOT_CACHEABLE);
735
736 const uint16_t val = pio_read_16(ptr);
737 printf("read %" PRIxn ": %" PRIx16 "\n", argv[0].intval, val);
738
739#ifdef IO_SPACE_BOUNDARY
740 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
741 return 1;
742#endif
743
744 km_unmap((uintptr_t) ptr, sizeof(uint16_t));
745 return 1;
746}
747
748/** Read 4 bytes from phys memory or io port.
749 *
750 * @param argv Argument vector.
751 *
752 * @return 0 on failure, 1 on success.
753 */
754static int cmd_pio_read_32(cmd_arg_t *argv)
755{
756 uint32_t *ptr = NULL;
757
758#ifdef IO_SPACE_BOUNDARY
759 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
760 ptr = (void *) argv[0].intval;
761 else
762#endif
763 ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
764 PAGE_NOT_CACHEABLE);
765
766 const uint32_t val = pio_read_32(ptr);
767 printf("read %" PRIxn ": %" PRIx32 "\n", argv[0].intval, val);
768
769#ifdef IO_SPACE_BOUNDARY
770 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
771 return 1;
772#endif
773
774 km_unmap((uintptr_t) ptr, sizeof(uint32_t));
775 return 1;
776}
777
778/** Write 1 byte to phys memory or io port.
779 *
780 * @param argv Argument vector.
781 *
782 * @return 0 on failure, 1 on success.
783 */
784static int cmd_pio_write_8(cmd_arg_t *argv)
785{
786 uint8_t *ptr = NULL;
787
788#ifdef IO_SPACE_BOUNDARY
789 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
790 ptr = (void *) argv[0].intval;
791 else
792#endif
793 ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
794 PAGE_NOT_CACHEABLE);
795
796 printf("write %" PRIxn ": %" PRIx8 "\n", argv[0].intval,
797 (uint8_t) argv[1].intval);
798 pio_write_8(ptr, (uint8_t) argv[1].intval);
799
800#ifdef IO_SPACE_BOUNDARY
801 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
802 return 1;
803#endif
804
805 km_unmap((uintptr_t) ptr, sizeof(uint8_t));
806 return 1;
807}
808
809/** Write 2 bytes to phys memory or io port.
810 *
811 * @param argv Argument vector.
812 *
813 * @return 0 on failure, 1 on success.
814 */
815static int cmd_pio_write_16(cmd_arg_t *argv)
816{
817 uint16_t *ptr = NULL;
818
819#ifdef IO_SPACE_BOUNDARY
820 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
821 ptr = (void *) argv[0].intval;
822 else
823#endif
824 ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
825 PAGE_NOT_CACHEABLE);
826
827 printf("write %" PRIxn ": %" PRIx16 "\n", argv[0].intval,
828 (uint16_t) argv[1].intval);
829 pio_write_16(ptr, (uint16_t) argv[1].intval);
830
831#ifdef IO_SPACE_BOUNDARY
832 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
833 return 1;
834#endif
835
836 km_unmap((uintptr_t) ptr, sizeof(uint16_t));
837 return 1;
838}
839
840/** Write 4 bytes to phys memory or io port.
841 *
842 * @param argv Argument vector.
843 *
844 * @return 0 on failure, 1 on success.
845 */
846static int cmd_pio_write_32(cmd_arg_t *argv)
847{
848 uint32_t *ptr = NULL;
849
850#ifdef IO_SPACE_BOUNDARY
851 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
852 ptr = (void *) argv[0].intval;
853 else
854#endif
855 ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
856 PAGE_NOT_CACHEABLE);
857
858 printf("write %" PRIxn ": %" PRIx32 "\n", argv[0].intval,
859 (uint32_t) argv[1].intval);
860 pio_write_32(ptr, (uint32_t) argv[1].intval);
861
862#ifdef IO_SPACE_BOUNDARY
863 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
864 return 1;
865#endif
866
867 km_unmap((uintptr_t) ptr, sizeof(uint32_t));
868 return 1;
869}
870
871/** Reboot the system.
872 *
873 * @param argv Argument vector.
874 *
875 * @return 0 on failure, 1 on success.
876 */
877int cmd_reboot(cmd_arg_t *argv)
878{
879 reboot();
880
881 /* Not reached */
882 return 1;
883}
884
885/** Print system uptime information.
886 *
887 * @param argv Argument vector.
888 *
889 * @return 0 on failure, 1 on success.
890 */
891int cmd_uptime(cmd_arg_t *argv)
892{
893 ASSERT(uptime);
894
895 /* This doesn't have to be very accurate */
896 sysarg_t sec = uptime->seconds1;
897
898 printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n",
899 sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60);
900
901 return 1;
902}
903
904/** Describe specified command.
905 *
906 * @param argv Argument vector.
907 *
908 * @return 0 on failure, 1 on success.
909 */
910int cmd_desc(cmd_arg_t *argv)
911{
912 spinlock_lock(&cmd_lock);
913
914 list_foreach(cmd_list, cur) {
915 cmd_info_t *hlp;
916
917 hlp = list_get_instance(cur, cmd_info_t, link);
918 spinlock_lock(&hlp->lock);
919
920 if (str_lcmp(hlp->name, (const char *) argv->buffer, str_length(hlp->name)) == 0) {
921 printf("%s - %s\n", hlp->name, hlp->description);
922 if (hlp->help)
923 hlp->help();
924 spinlock_unlock(&hlp->lock);
925 break;
926 }
927
928 spinlock_unlock(&hlp->lock);
929 }
930
931 spinlock_unlock(&cmd_lock);
932
933 return 1;
934}
935
936/** Search symbol table */
937int cmd_symaddr(cmd_arg_t *argv)
938{
939 symtab_print_search((char *) argv->buffer);
940
941 return 1;
942}
943
944/** Call function with zero parameters */
945int cmd_call0(cmd_arg_t *argv)
946{
947 uintptr_t symaddr;
948 char *symbol;
949 sysarg_t (*fnc)(void);
950 fncptr_t fptr;
951 int rc;
952
953 symbol = (char *) argv->buffer;
954 rc = symtab_addr_lookup(symbol, &symaddr);
955
956 if (rc == ENOENT)
957 printf("Symbol %s not found.\n", symbol);
958 else if (rc == EOVERFLOW) {
959 symtab_print_search(symbol);
960 printf("Duplicate symbol, be more specific.\n");
961 } else if (rc == EOK) {
962 ipl_t ipl;
963
964 ipl = interrupts_disable();
965 fnc = (sysarg_t (*)(void)) arch_construct_function(&fptr,
966 (void *) symaddr, (void *) cmd_call0);
967 printf("Calling %s() (%p)\n", symbol, (void *) symaddr);
968 printf("Result: %#" PRIxn "\n", fnc());
969 interrupts_restore(ipl);
970 } else {
971 printf("No symbol information available.\n");
972 }
973 return 1;
974}
975
976/** Call function with zero parameters on each CPU */
977int cmd_mcall0(cmd_arg_t *argv)
978{
979 /*
980 * For each CPU, create a thread which will
981 * call the function.
982 */
983
984 unsigned int i;
985 for (i = 0; i < config.cpu_count; i++) {
986 if (!cpus[i].active)
987 continue;
988
989 thread_t *thread;
990 if ((thread = thread_create((void (*)(void *)) cmd_call0,
991 (void *) argv, TASK, THREAD_FLAG_NONE, "call0"))) {
992 printf("cpu%u: ", i);
993 thread_wire(thread, &cpus[i]);
994 thread_ready(thread);
995 thread_join(thread);
996 thread_detach(thread);
997 } else
998 printf("Unable to create thread for cpu%u\n", i);
999 }
1000
1001 return 1;
1002}
1003
1004/** Call function with one parameter */
1005int cmd_call1(cmd_arg_t *argv)
1006{
1007 uintptr_t symaddr;
1008 char *symbol;
1009 sysarg_t (*fnc)(sysarg_t, ...);
1010 sysarg_t arg1 = argv[1].intval;
1011 fncptr_t fptr;
1012 int rc;
1013
1014 symbol = (char *) argv->buffer;
1015 rc = symtab_addr_lookup(symbol, &symaddr);
1016
1017 if (rc == ENOENT) {
1018 printf("Symbol %s not found.\n", symbol);
1019 } else if (rc == EOVERFLOW) {
1020 symtab_print_search(symbol);
1021 printf("Duplicate symbol, be more specific.\n");
1022 } else if (rc == EOK) {
1023 ipl_t ipl;
1024
1025 ipl = interrupts_disable();
1026 fnc = (sysarg_t (*)(sysarg_t, ...))
1027 arch_construct_function(&fptr, (void *) symaddr,
1028 (void *) cmd_call1);
1029 printf("Calling f(%#" PRIxn "): %p: %s\n", arg1,
1030 (void *) symaddr, symbol);
1031 printf("Result: %#" PRIxn "\n", fnc(arg1));
1032 interrupts_restore(ipl);
1033 } else {
1034 printf("No symbol information available.\n");
1035 }
1036
1037 return 1;
1038}
1039
1040/** Call function with two parameters */
1041int cmd_call2(cmd_arg_t *argv)
1042{
1043 uintptr_t symaddr;
1044 char *symbol;
1045 sysarg_t (*fnc)(sysarg_t, sysarg_t, ...);
1046 sysarg_t arg1 = argv[1].intval;
1047 sysarg_t arg2 = argv[2].intval;
1048 fncptr_t fptr;
1049 int rc;
1050
1051 symbol = (char *) argv->buffer;
1052 rc = symtab_addr_lookup(symbol, &symaddr);
1053
1054 if (rc == ENOENT) {
1055 printf("Symbol %s not found.\n", symbol);
1056 } else if (rc == EOVERFLOW) {
1057 symtab_print_search(symbol);
1058 printf("Duplicate symbol, be more specific.\n");
1059 } else if (rc == EOK) {
1060 ipl_t ipl;
1061
1062 ipl = interrupts_disable();
1063 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, ...))
1064 arch_construct_function(&fptr, (void *) symaddr,
1065 (void *) cmd_call2);
1066 printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n",
1067 arg1, arg2, (void *) symaddr, symbol);
1068 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2));
1069 interrupts_restore(ipl);
1070 } else {
1071 printf("No symbol information available.\n");
1072 }
1073 return 1;
1074}
1075
1076/** Call function with three parameters */
1077int cmd_call3(cmd_arg_t *argv)
1078{
1079 uintptr_t symaddr;
1080 char *symbol;
1081 sysarg_t (*fnc)(sysarg_t, sysarg_t, sysarg_t, ...);
1082 sysarg_t arg1 = argv[1].intval;
1083 sysarg_t arg2 = argv[2].intval;
1084 sysarg_t arg3 = argv[3].intval;
1085 fncptr_t fptr;
1086 int rc;
1087
1088 symbol = (char *) argv->buffer;
1089 rc = symtab_addr_lookup(symbol, &symaddr);
1090
1091 if (rc == ENOENT) {
1092 printf("Symbol %s not found.\n", symbol);
1093 } else if (rc == EOVERFLOW) {
1094 symtab_print_search(symbol);
1095 printf("Duplicate symbol, be more specific.\n");
1096 } else if (rc == EOK) {
1097 ipl_t ipl;
1098
1099 ipl = interrupts_disable();
1100 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, sysarg_t, ...))
1101 arch_construct_function(&fptr, (void *) symaddr,
1102 (void *) cmd_call3);
1103 printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n",
1104 arg1, arg2, arg3, (void *) symaddr, symbol);
1105 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3));
1106 interrupts_restore(ipl);
1107 } else {
1108 printf("No symbol information available.\n");
1109 }
1110 return 1;
1111}
1112
1113/** Print detailed description of 'describe' command. */
1114void desc_help(void)
1115{
1116 printf("Syntax: describe command_name\n");
1117}
1118
1119/** Halt the kernel.
1120 *
1121 * @param argv Argument vector (ignored).
1122 *
1123 * @return 0 on failure, 1 on success (never returns).
1124 */
1125int cmd_halt(cmd_arg_t *argv)
1126{
1127 halt();
1128 return 1;
1129}
1130
1131/** Command for printing TLB contents.
1132 *
1133 * @param argv Not used.
1134 *
1135 * @return Always returns 1.
1136 */
1137int cmd_tlb(cmd_arg_t *argv)
1138{
1139 tlb_print();
1140 return 1;
1141}
1142
1143/** Command for printing physical memory configuration.
1144 *
1145 * @param argv Not used.
1146 *
1147 * @return Always returns 1.
1148 */
1149int cmd_physmem(cmd_arg_t *argv)
1150{
1151 physmem_print();
1152 return 1;
1153}
1154
1155/** Write 4 byte value to address */
1156int cmd_set4(cmd_arg_t *argv)
1157{
1158 uintptr_t addr;
1159 uint32_t arg1 = argv[1].intval;
1160 bool pointer = false;
1161 int rc;
1162
1163 if (((char *) argv->buffer)[0] == '*') {
1164 rc = symtab_addr_lookup((char *) argv->buffer + 1, &addr);
1165 pointer = true;
1166 } else if (((char *) argv->buffer)[0] >= '0' &&
1167 ((char *) argv->buffer)[0] <= '9') {
1168 uint64_t value;
1169 rc = str_uint64_t((char *) argv->buffer, NULL, 0, true, &value);
1170 if (rc == EOK)
1171 addr = (uintptr_t) value;
1172 } else
1173 rc = symtab_addr_lookup((char *) argv->buffer, &addr);
1174
1175 if (rc == ENOENT)
1176 printf("Symbol %s not found.\n", (char *) argv->buffer);
1177 else if (rc == EINVAL)
1178 printf("Invalid address.\n");
1179 else if (rc == EOVERFLOW) {
1180 symtab_print_search((char *) argv->buffer);
1181 printf("Duplicate symbol (be more specific) or address overflow.\n");
1182 } else if (rc == EOK) {
1183 if (pointer)
1184 addr = *(uintptr_t *) addr;
1185 printf("Writing %#" PRIx32" -> %p\n", arg1, (void *) addr);
1186 *(uint32_t *) addr = arg1;
1187 } else
1188 printf("No symbol information available.\n");
1189
1190 return 1;
1191}
1192
1193/** Command for listings SLAB caches
1194 *
1195 * @param argv Ignores
1196 *
1197 * @return Always 1
1198 */
1199int cmd_slabs(cmd_arg_t *argv)
1200{
1201 slab_print_list();
1202 return 1;
1203}
1204
1205/** Command for dumping sysinfo
1206 *
1207 * @param argv Ignores
1208 *
1209 * @return Always 1
1210 */
1211int cmd_sysinfo(cmd_arg_t *argv)
1212{
1213 sysinfo_dump(NULL);
1214 return 1;
1215}
1216
1217/** Command for listing thread information
1218 *
1219 * @param argv Ignored
1220 *
1221 * @return Always 1
1222 */
1223int cmd_threads(cmd_arg_t *argv)
1224{
1225 if (str_cmp(flag_buf, "-a") == 0)
1226 thread_print_list(true);
1227 else if (str_cmp(flag_buf, "") == 0)
1228 thread_print_list(false);
1229 else
1230 printf("Unknown argument \"%s\".\n", flag_buf);
1231
1232 return 1;
1233}
1234
1235/** Command for listing task information
1236 *
1237 * @param argv Ignored
1238 *
1239 * @return Always 1
1240 */
1241int cmd_tasks(cmd_arg_t *argv)
1242{
1243 if (str_cmp(flag_buf, "-a") == 0)
1244 task_print_list(true);
1245 else if (str_cmp(flag_buf, "") == 0)
1246 task_print_list(false);
1247 else
1248 printf("Unknown argument \"%s\".\n", flag_buf);
1249
1250 return 1;
1251}
1252
1253#ifdef CONFIG_UDEBUG
1254
1255/** Command for printing thread stack trace
1256 *
1257 * @param argv Integer argument from cmdline expected
1258 *
1259 * return Always 1
1260 *
1261 */
1262int cmd_btrace(cmd_arg_t *argv)
1263{
1264 thread_stack_trace(argv[0].intval);
1265 return 1;
1266}
1267
1268#endif /* CONFIG_UDEBUG */
1269
1270/** Command for printing scheduler information
1271 *
1272 * @param argv Ignores
1273 *
1274 * @return Always 1
1275 */
1276int cmd_sched(cmd_arg_t *argv)
1277{
1278 sched_print_list();
1279 return 1;
1280}
1281
1282/** Command for listing memory zones
1283 *
1284 * @param argv Ignored
1285 *
1286 * return Always 1
1287 */
1288int cmd_zones(cmd_arg_t *argv)
1289{
1290 zones_print_list();
1291 return 1;
1292}
1293
1294/** Command for memory zone details
1295 *
1296 * @param argv Integer argument from cmdline expected
1297 *
1298 * return Always 1
1299 */
1300int cmd_zone(cmd_arg_t *argv)
1301{
1302 zone_print_one(argv[0].intval);
1303 return 1;
1304}
1305
1306/** Command for printing task IPC details
1307 *
1308 * @param argv Integer argument from cmdline expected
1309 *
1310 * return Always 1
1311 */
1312int cmd_ipc(cmd_arg_t *argv)
1313{
1314 ipc_print_task(argv[0].intval);
1315 return 1;
1316}
1317
1318/** Command for killing a task
1319 *
1320 * @param argv Integer argument from cmdline expected
1321 *
1322 * return 0 on failure, 1 on success.
1323 */
1324int cmd_kill(cmd_arg_t *argv)
1325{
1326 if (task_kill(argv[0].intval) != EOK)
1327 return 0;
1328
1329 return 1;
1330}
1331
1332/** Command for listing processors.
1333 *
1334 * @param argv Ignored.
1335 *
1336 * return Always 1.
1337 */
1338int cmd_cpus(cmd_arg_t *argv)
1339{
1340 cpu_list();
1341 return 1;
1342}
1343
1344/** Command for printing kernel version.
1345 *
1346 * @param argv Ignored.
1347 *
1348 * return Always 1.
1349 */
1350int cmd_version(cmd_arg_t *argv)
1351{
1352 version_print();
1353 return 1;
1354}
1355
1356/** Command for returning console back to userspace.
1357 *
1358 * @param argv Ignored.
1359 *
1360 * return Always 1.
1361 */
1362int cmd_continue(cmd_arg_t *argv)
1363{
1364 printf("The kernel will now relinquish the console.\n");
1365 release_console();
1366
1367 event_notify_0(EVENT_KCONSOLE, false);
1368 indev_pop_character(stdin);
1369
1370 return 1;
1371}
1372
1373#ifdef CONFIG_TEST
1374static bool run_test(const test_t *test)
1375{
1376 printf("%s (%s)\n", test->name, test->desc);
1377
1378 /* Update and read thread accounting
1379 for benchmarking */
1380 irq_spinlock_lock(&TASK->lock, true);
1381 uint64_t ucycles0, kcycles0;
1382 task_get_accounting(TASK, &ucycles0, &kcycles0);
1383 irq_spinlock_unlock(&TASK->lock, true);
1384
1385 /* Execute the test */
1386 test_quiet = false;
1387 const char *ret = test->entry();
1388
1389 /* Update and read thread accounting */
1390 uint64_t ucycles1, kcycles1;
1391 irq_spinlock_lock(&TASK->lock, true);
1392 task_get_accounting(TASK, &ucycles1, &kcycles1);
1393 irq_spinlock_unlock(&TASK->lock, true);
1394
1395 uint64_t ucycles, kcycles;
1396 char usuffix, ksuffix;
1397 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1398 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
1399
1400 printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n",
1401 ucycles, usuffix, kcycles, ksuffix);
1402
1403 if (ret == NULL) {
1404 printf("Test passed\n");
1405 return true;
1406 }
1407
1408 printf("%s\n", ret);
1409 return false;
1410}
1411
1412static bool run_bench(const test_t *test, const uint32_t cnt)
1413{
1414 uint32_t i;
1415 bool ret = true;
1416 uint64_t ucycles, kcycles;
1417 char usuffix, ksuffix;
1418
1419 if (cnt < 1)
1420 return true;
1421
1422 uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
1423 if (data == NULL) {
1424 printf("Error allocating memory for statistics\n");
1425 return false;
1426 }
1427
1428 for (i = 0; i < cnt; i++) {
1429 printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
1430
1431 /* Update and read thread accounting
1432 for benchmarking */
1433 irq_spinlock_lock(&TASK->lock, true);
1434 uint64_t ucycles0, kcycles0;
1435 task_get_accounting(TASK, &ucycles0, &kcycles0);
1436 irq_spinlock_unlock(&TASK->lock, true);
1437
1438 /* Execute the test */
1439 test_quiet = true;
1440 const char *test_ret = test->entry();
1441
1442 /* Update and read thread accounting */
1443 irq_spinlock_lock(&TASK->lock, true);
1444 uint64_t ucycles1, kcycles1;
1445 task_get_accounting(TASK, &ucycles1, &kcycles1);
1446 irq_spinlock_unlock(&TASK->lock, true);
1447
1448 if (test_ret != NULL) {
1449 printf("%s\n", test_ret);
1450 ret = false;
1451 break;
1452 }
1453
1454 data[i] = ucycles1 - ucycles0 + kcycles1 - kcycles0;
1455 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1456 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
1457 printf("OK (%" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles)\n",
1458 ucycles, usuffix, kcycles, ksuffix);
1459 }
1460
1461 if (ret) {
1462 printf("\n");
1463
1464 uint64_t sum = 0;
1465
1466 for (i = 0; i < cnt; i++) {
1467 sum += data[i];
1468 }
1469
1470 order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix);
1471 printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix);
1472 }
1473
1474 free(data);
1475
1476 return ret;
1477}
1478
1479static void list_tests(void)
1480{
1481 size_t len = 0;
1482 test_t *test;
1483
1484 for (test = tests; test->name != NULL; test++) {
1485 if (str_length(test->name) > len)
1486 len = str_length(test->name);
1487 }
1488
1489 unsigned int _len = (unsigned int) len;
1490 if ((_len != len) || (((int) _len) < 0)) {
1491 printf("Command length overflow\n");
1492 return;
1493 }
1494
1495 for (test = tests; test->name != NULL; test++)
1496 printf("%-*s %s%s\n", _len, test->name, test->desc,
1497 (test->safe ? "" : " (unsafe)"));
1498
1499 printf("%-*s Run all safe tests\n", _len, "*");
1500}
1501
1502/** Command for listing and running kernel tests
1503 *
1504 * @param argv Argument vector.
1505 *
1506 * return Always 1.
1507 *
1508 */
1509int cmd_test(cmd_arg_t *argv)
1510{
1511 test_t *test;
1512
1513 if (str_cmp((char *) argv->buffer, "*") == 0) {
1514 for (test = tests; test->name != NULL; test++) {
1515 if (test->safe) {
1516 printf("\n");
1517 if (!run_test(test))
1518 break;
1519 }
1520 }
1521 } else if (str_cmp((char *) argv->buffer, "") != 0) {
1522 bool fnd = false;
1523
1524 for (test = tests; test->name != NULL; test++) {
1525 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
1526 fnd = true;
1527 run_test(test);
1528 break;
1529 }
1530 }
1531
1532 if (!fnd)
1533 printf("Unknown test\n");
1534 } else
1535 list_tests();
1536
1537 return 1;
1538}
1539
1540/** Command for returning kernel tests as benchmarks
1541 *
1542 * @param argv Argument vector.
1543 *
1544 * return Always 1.
1545 */
1546int cmd_bench(cmd_arg_t *argv)
1547{
1548 test_t *test;
1549 uint32_t cnt = argv[1].intval;
1550
1551 if (str_cmp((char *) argv->buffer, "*") == 0) {
1552 for (test = tests; test->name != NULL; test++) {
1553 if (test->safe) {
1554 if (!run_bench(test, cnt))
1555 break;
1556 }
1557 }
1558 } else {
1559 bool fnd = false;
1560
1561 for (test = tests; test->name != NULL; test++) {
1562 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
1563 fnd = true;
1564
1565 if (test->safe)
1566 run_bench(test, cnt);
1567 else
1568 printf("Unsafe test\n");
1569
1570 break;
1571 }
1572 }
1573
1574 if (!fnd)
1575 printf("Unknown test\n");
1576 }
1577
1578 return 1;
1579}
1580
1581#endif
1582
1583/** @}
1584 */
Note: See TracBrowser for help on using the repository browser.