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

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

start shutdown infrastructure

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