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

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

add mcall0 command (calling a function on each CPU)

  • 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 } else
603 printf("Unable to create thread for cpu%u\n", i);
604 }
605
606 return 1;
607}
608
609/** Call function with one parameter */
610int cmd_call1(cmd_arg_t *argv)
611{
612 uintptr_t symaddr;
613 char *symbol;
614 unative_t (*f)(unative_t,...);
615 unative_t arg1 = argv[1].intval;
616#ifdef ia64
617 struct {
618 unative_t f;
619 unative_t gp;
620 }fptr;
621#endif
622
623 symaddr = get_symbol_addr((char *) argv->buffer);
624 if (!symaddr)
625 printf("Symbol %s not found.\n", argv->buffer);
626 else if (symaddr == (uintptr_t) -1) {
627 symtab_print_search((char *) argv->buffer);
628 printf("Duplicate symbol, be more specific.\n");
629 } else {
630 symbol = get_symtab_entry(symaddr);
631
632 printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
633#ifdef ia64
634 fptr.f = symaddr;
635 fptr.gp = ((unative_t *)cmd_call2)[1];
636 f = (unative_t (*)(unative_t,...)) &fptr;
637#else
638 f = (unative_t (*)(unative_t,...)) symaddr;
639#endif
640 printf("Result: %#zx\n", f(arg1));
641 }
642
643 return 1;
644}
645
646/** Call function with two parameters */
647int cmd_call2(cmd_arg_t *argv)
648{
649 uintptr_t symaddr;
650 char *symbol;
651 unative_t (*f)(unative_t,unative_t,...);
652 unative_t arg1 = argv[1].intval;
653 unative_t arg2 = argv[2].intval;
654#ifdef ia64
655 struct {
656 unative_t f;
657 unative_t gp;
658 }fptr;
659#endif
660
661 symaddr = get_symbol_addr((char *) argv->buffer);
662 if (!symaddr)
663 printf("Symbol %s not found.\n", argv->buffer);
664 else if (symaddr == (uintptr_t) -1) {
665 symtab_print_search((char *) argv->buffer);
666 printf("Duplicate symbol, be more specific.\n");
667 } else {
668 symbol = get_symtab_entry(symaddr);
669 printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
670 arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
671#ifdef ia64
672 fptr.f = symaddr;
673 fptr.gp = ((unative_t *)cmd_call2)[1];
674 f = (unative_t (*)(unative_t,unative_t,...)) &fptr;
675#else
676 f = (unative_t (*)(unative_t,unative_t,...)) symaddr;
677#endif
678 printf("Result: %#zx\n", f(arg1, arg2));
679 }
680
681 return 1;
682}
683
684/** Call function with three parameters */
685int cmd_call3(cmd_arg_t *argv)
686{
687 uintptr_t symaddr;
688 char *symbol;
689 unative_t (*f)(unative_t,unative_t,unative_t,...);
690 unative_t arg1 = argv[1].intval;
691 unative_t arg2 = argv[2].intval;
692 unative_t arg3 = argv[3].intval;
693#ifdef ia64
694 struct {
695 unative_t f;
696 unative_t gp;
697 }fptr;
698#endif
699
700 symaddr = get_symbol_addr((char *) argv->buffer);
701 if (!symaddr)
702 printf("Symbol %s not found.\n", argv->buffer);
703 else if (symaddr == (uintptr_t) -1) {
704 symtab_print_search((char *) argv->buffer);
705 printf("Duplicate symbol, be more specific.\n");
706 } else {
707 symbol = get_symtab_entry(symaddr);
708 printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
709 arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
710#ifdef ia64
711 fptr.f = symaddr;
712 fptr.gp = ((unative_t *)cmd_call2)[1];
713 f = (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
714#else
715 f = (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
716#endif
717 printf("Result: %#zx\n", f(arg1, arg2, arg3));
718 }
719
720 return 1;
721}
722
723
724/** Print detailed description of 'describe' command. */
725void desc_help(void)
726{
727 printf("Syntax: describe command_name\n");
728}
729
730/** Halt the kernel.
731 *
732 * @param argv Argument vector (ignored).
733 *
734 * @return 0 on failure, 1 on success (never returns).
735 */
736int cmd_halt(cmd_arg_t *argv)
737{
738 halt();
739 return 1;
740}
741
742/** Command for printing TLB contents.
743 *
744 * @param argv Not used.
745 *
746 * @return Always returns 1.
747 */
748int cmd_tlb(cmd_arg_t *argv)
749{
750 tlb_print();
751 return 1;
752}
753
754/** Write 4 byte value to address */
755int cmd_set4(cmd_arg_t *argv)
756{
757 uint32_t *addr;
758 uint32_t arg1 = argv[1].intval;
759 bool pointer = false;
760
761 if (((char *)argv->buffer)[0] == '*') {
762 addr = (uint32_t *) get_symbol_addr((char *) argv->buffer + 1);
763 pointer = true;
764 } else if (((char *) argv->buffer)[0] >= '0' &&
765 ((char *)argv->buffer)[0] <= '9')
766 addr = (uint32_t *)atoi((char *)argv->buffer);
767 else
768 addr = (uint32_t *)get_symbol_addr((char *) argv->buffer);
769
770 if (!addr)
771 printf("Symbol %s not found.\n", argv->buffer);
772 else if (addr == (uint32_t *) -1) {
773 symtab_print_search((char *) argv->buffer);
774 printf("Duplicate symbol, be more specific.\n");
775 } else {
776 if (pointer)
777 addr = (uint32_t *)(*(unative_t *)addr);
778 printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
779 *addr = arg1;
780
781 }
782
783 return 1;
784}
785
786/** Command for listings SLAB caches
787 *
788 * @param argv Ignores
789 *
790 * @return Always 1
791 */
792int cmd_slabs(cmd_arg_t * argv) {
793 slab_print_list();
794 return 1;
795}
796
797
798/** Command for listings Thread information
799 *
800 * @param argv Ignores
801 *
802 * @return Always 1
803 */
804int cmd_threads(cmd_arg_t * argv) {
805 thread_print_list();
806 return 1;
807}
808
809/** Command for listings Task information
810 *
811 * @param argv Ignores
812 *
813 * @return Always 1
814 */
815int cmd_tasks(cmd_arg_t * argv) {
816 task_print_list();
817 return 1;
818}
819
820/** Command for listings Thread information
821 *
822 * @param argv Ignores
823 *
824 * @return Always 1
825 */
826int cmd_sched(cmd_arg_t * argv) {
827 sched_print_list();
828 return 1;
829}
830
831/** Command for listing memory zones
832 *
833 * @param argv Ignored
834 *
835 * return Always 1
836 */
837int cmd_zones(cmd_arg_t * argv) {
838 zone_print_list();
839 return 1;
840}
841
842/** Command for memory zone details
843 *
844 * @param argv Integer argument from cmdline expected
845 *
846 * return Always 1
847 */
848int cmd_zone(cmd_arg_t * argv) {
849 zone_print_one(argv[0].intval);
850 return 1;
851}
852
853/** Command for printing task ipc details
854 *
855 * @param argv Integer argument from cmdline expected
856 *
857 * return Always 1
858 */
859int cmd_ipc_task(cmd_arg_t * argv) {
860 ipc_print_task(argv[0].intval);
861 return 1;
862}
863
864
865/** Command for listing processors.
866 *
867 * @param argv Ignored.
868 *
869 * return Always 1.
870 */
871int cmd_cpus(cmd_arg_t *argv)
872{
873 cpu_list();
874 return 1;
875}
876
877/** Command for printing kernel version.
878 *
879 * @param argv Ignored.
880 *
881 * return Always 1.
882 */
883int cmd_version(cmd_arg_t *argv)
884{
885 version_print();
886 return 1;
887}
888
889/** Command for returning console back to userspace.
890 *
891 * @param argv Ignored.
892 *
893 * return Always 1.
894 */
895int cmd_continue(cmd_arg_t *argv)
896{
897 printf("The kernel will now relinquish the console.\n");
898 printf("Use userspace controls to redraw the screen.\n");
899 arch_release_console();
900 return 1;
901}
902
903#ifdef CONFIG_TEST
904/** Command for printing kernel tests list.
905 *
906 * @param argv Ignored.
907 *
908 * return Always 1.
909 */
910int cmd_tests(cmd_arg_t *argv)
911{
912 test_t *test;
913
914 for (test = tests; test->name != NULL; test++)
915 printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
916
917 printf("*\t\tRun all safe tests\n");
918 return 1;
919}
920
921static bool run_test(const test_t *test)
922{
923 printf("%s\t\t%s\n", test->name, test->desc);
924
925 /* Update and read thread accounting
926 for benchmarking */
927 ipl_t ipl = interrupts_disable();
928 spinlock_lock(&TASK->lock);
929 uint64_t t0 = task_get_accounting(TASK);
930 spinlock_unlock(&TASK->lock);
931 interrupts_restore(ipl);
932
933 /* Execute the test */
934 char * ret = test->entry(false);
935
936 /* Update and read thread accounting */
937 ipl = interrupts_disable();
938 spinlock_lock(&TASK->lock);
939 uint64_t dt = task_get_accounting(TASK) - t0;
940 spinlock_unlock(&TASK->lock);
941 interrupts_restore(ipl);
942
943 uint64_t cycles;
944 char suffix;
945 order(dt, &cycles, &suffix);
946
947 printf("Time: %llu%c cycles\n", cycles, suffix);
948
949 if (ret == NULL) {
950 printf("Test passed\n");
951 return true;
952 }
953
954 printf("%s\n", ret);
955 return false;
956}
957
958static bool run_bench(const test_t *test, const uint32_t cnt)
959{
960 uint32_t i;
961 bool ret = true;
962 uint64_t cycles;
963 char suffix;
964
965 if (cnt < 1)
966 return true;
967
968 uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
969 if (data == NULL) {
970 printf("Error allocating memory for statistics\n");
971 return false;
972 }
973
974 for (i = 0; i < cnt; i++) {
975 printf("%s (%d/%d) ... ", test->name, i + 1, cnt);
976
977 /* Update and read thread accounting
978 for benchmarking */
979 ipl_t ipl = interrupts_disable();
980 spinlock_lock(&TASK->lock);
981 uint64_t t0 = task_get_accounting(TASK);
982 spinlock_unlock(&TASK->lock);
983 interrupts_restore(ipl);
984
985 /* Execute the test */
986 char * ret = test->entry(true);
987
988 /* Update and read thread accounting */
989 ipl = interrupts_disable();
990 spinlock_lock(&TASK->lock);
991 uint64_t dt = task_get_accounting(TASK) - t0;
992 spinlock_unlock(&TASK->lock);
993 interrupts_restore(ipl);
994
995 if (ret != NULL) {
996 printf("%s\n", ret);
997 ret = false;
998 break;
999 }
1000
1001 data[i] = dt;
1002 order(dt, &cycles, &suffix);
1003 printf("OK (%llu%c cycles)\n", cycles, suffix);
1004 }
1005
1006 if (ret) {
1007 printf("\n");
1008
1009 uint64_t sum = 0;
1010
1011 for (i = 0; i < cnt; i++) {
1012 sum += data[i];
1013 }
1014
1015 order(sum / (uint64_t) cnt, &cycles, &suffix);
1016 printf("Average\t\t%llu%c\n", cycles, suffix);
1017 }
1018
1019 free(data);
1020
1021 return ret;
1022}
1023
1024/** Command for returning kernel tests
1025 *
1026 * @param argv Argument vector.
1027 *
1028 * return Always 1.
1029 */
1030int cmd_test(cmd_arg_t *argv)
1031{
1032 test_t *test;
1033
1034 if (strcmp((char *) argv->buffer, "*") == 0) {
1035 for (test = tests; test->name != NULL; test++) {
1036 if (test->safe) {
1037 printf("\n");
1038 if (!run_test(test))
1039 break;
1040 }
1041 }
1042 } else {
1043 bool fnd = false;
1044
1045 for (test = tests; test->name != NULL; test++) {
1046 if (strcmp(test->name, (char *) argv->buffer) == 0) {
1047 fnd = true;
1048 run_test(test);
1049 break;
1050 }
1051 }
1052
1053 if (!fnd)
1054 printf("Unknown test\n");
1055 }
1056
1057 return 1;
1058}
1059
1060/** Command for returning kernel tests as benchmarks
1061 *
1062 * @param argv Argument vector.
1063 *
1064 * return Always 1.
1065 */
1066int cmd_bench(cmd_arg_t *argv)
1067{
1068 test_t *test;
1069 uint32_t cnt = argv[1].intval;
1070
1071 bool fnd = false;
1072
1073 for (test = tests; test->name != NULL; test++) {
1074 if (strcmp(test->name, (char *) argv->buffer) == 0) {
1075 fnd = true;
1076
1077 if (test->safe)
1078 run_bench(test, cnt);
1079 else
1080 printf("Unsafe test\n");
1081
1082 break;
1083 }
1084 }
1085
1086 if (!fnd)
1087 printf("Unknown test\n");
1088
1089 return 1;
1090}
1091
1092#endif
1093
1094/** @}
1095 */
Note: See TracBrowser for help on using the repository browser.