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

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

detach joined thread

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