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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b0b4592e was b2fa1204, checked in by Martin Sucha <sucha14@…>, 12 years ago

Cherrypick usage of kernel logger

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