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
RevLine 
[442d0ae]1/*
[df4ed85]2 * Copyright (c) 2005 Jakub Jermar
[442d0ae]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
[06e1e95]29/** @addtogroup genericconsole
[b45c443]30 * @{
31 */
32
[442d0ae]33/**
[cf26ba9]34 * @file cmd.c
35 * @brief Kernel console command wrappers.
36 *
[442d0ae]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>
[41d33ac]44#include <console/console.h>
[442d0ae]45#include <console/kconsole.h>
46#include <print.h>
47#include <panic.h>
48#include <arch/types.h>
[5c9a08b]49#include <adt/list.h>
[442d0ae]50#include <arch.h>
[f74bbaf]51#include <config.h>
[442d0ae]52#include <func.h>
53#include <macros.h>
54#include <debug.h>
55#include <symtab.h>
[0132630]56#include <cpu.h>
[442d0ae]57#include <mm/tlb.h>
58#include <arch/mm/tlb.h>
[80bff342]59#include <mm/frame.h>
[0132630]60#include <main/version.h>
[4e147a6]61#include <mm/slab.h>
[10e16a7]62#include <proc/scheduler.h>
[55ab0f1]63#include <proc/thread.h>
[37c57f2]64#include <proc/task.h>
[c4e4507]65#include <ipc/ipc.h>
[62939f7]66#include <ipc/irq.h>
[442d0ae]67
[319e60e]68#ifdef CONFIG_TEST
69#include <test.h>
70#endif
71
[b45c443]72/* Data and methods for 'help' command. */
[442d0ae]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
[e07fe0c]81static cmd_info_t exit_info = {
82 .name = "exit",
[f74bbaf]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,
[e07fe0c]92 .argc = 0
93};
94
[41d33ac]95static int cmd_continue(cmd_arg_t *argv);
96static cmd_info_t continue_info = {
97 .name = "continue",
[319e60e]98 .description = "Return console back to userspace.",
[41d33ac]99 .func = cmd_continue,
100 .argc = 0
101};
102
[319e60e]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};
[95155b0c]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};
[319e60e]147#endif
148
[b45c443]149/* Data and methods for 'description' command. */
[442d0ae]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
[b45c443]167/* Data and methods for 'symaddr' command. */
[442d0ae]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
[ba276f7]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
[b45c443]203/* Data and methods for 'call0' command. */
[e5dbbe5]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];
[442d0ae]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
[e5dbbe5]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
[b45c443]238/* Data and methods for 'call1' command. */
[442d0ae]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
[b45c443]260/* Data and methods for 'call2' command. */
[442d0ae]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
[b45c443]287/* Data and methods for 'call3' command. */
[442d0ae]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
[b45c443]320/* Data and methods for 'halt' command. */
[442d0ae]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
[b45c443]329/* Data and methods for 'tlb' command. */
[0132630]330static int cmd_tlb(cmd_arg_t *argv);
331cmd_info_t tlb_info = {
332 .name = "tlb",
[442d0ae]333 .description = "Print TLB of current processor.",
334 .help = NULL,
[0132630]335 .func = cmd_tlb,
[442d0ae]336 .argc = 0,
337 .argv = NULL
338};
339
[55ab0f1]340static int cmd_threads(cmd_arg_t *argv);
341static cmd_info_t threads_info = {
342 .name = "threads",
[dd054bc2]343 .description = "List all threads.",
[55ab0f1]344 .func = cmd_threads,
345 .argc = 0
346};
347
[37c57f2]348static int cmd_tasks(cmd_arg_t *argv);
349static cmd_info_t tasks_info = {
350 .name = "tasks",
[dd054bc2]351 .description = "List all tasks.",
[37c57f2]352 .func = cmd_tasks,
353 .argc = 0
354};
355
[80bff342]356
[10e16a7]357static int cmd_sched(cmd_arg_t *argv);
358static cmd_info_t sched_info = {
359 .name = "scheduler",
[dd054bc2]360 .description = "List all scheduler information.",
[10e16a7]361 .func = cmd_sched,
362 .argc = 0
363};
364
[4e147a6]365static int cmd_slabs(cmd_arg_t *argv);
366static cmd_info_t slabs_info = {
367 .name = "slabs",
[dd054bc2]368 .description = "List slab caches.",
[4e147a6]369 .func = cmd_slabs,
370 .argc = 0
371};
372
[b45c443]373/* Data and methods for 'zones' command */
[80bff342]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
[b45c443]382/* Data and methods for 'ipc_task' command */
[c4e4507]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",
[dd054bc2]389 .description = "ipc_task <taskid> Show IPC information of given task.",
[c4e4507]390 .func = cmd_ipc_task,
391 .argc = 1,
392 .argv = &ipc_task_argv
393};
394
[b45c443]395/* Data and methods for 'zone' command */
[80bff342]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
[b45c443]409/* Data and methods for 'cpus' command. */
[0132630]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
[b45c443]420/* Data and methods for 'version' command. */
[0132630]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
[10e16a7]431static cmd_info_t *basic_commands[] = {
432 &call0_info,
[e5dbbe5]433 &mcall0_info,
[10e16a7]434 &call1_info,
435 &call2_info,
436 &call3_info,
[41d33ac]437 &continue_info,
[10e16a7]438 &cpus_info,
439 &desc_info,
440 &exit_info,
[f74bbaf]441 &reboot_info,
[10e16a7]442 &halt_info,
443 &help_info,
[c4e4507]444 &ipc_task_info,
[10e16a7]445 &set4_info,
446 &slabs_info,
447 &symaddr_info,
448 &sched_info,
[55ab0f1]449 &threads_info,
[37c57f2]450 &tasks_info,
[10e16a7]451 &tlb_info,
452 &version_info,
453 &zones_info,
454 &zone_info,
[319e60e]455#ifdef CONFIG_TEST
456 &tests_info,
457 &test_info,
[95155b0c]458 &bench_info,
[319e60e]459#endif
[10e16a7]460 NULL
461};
[80bff342]462
463
[442d0ae]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{
[10e16a7]478 int i;
[80bff342]479
[10e16a7]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 }
[442d0ae]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
[f74bbaf]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
[442d0ae]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{
[828aa05]569 symtab_print_search((char *) argv->buffer);
[442d0ae]570
571 return 1;
572}
573
574/** Call function with zero parameters */
575int cmd_call0(cmd_arg_t *argv)
576{
[7f1c620]577 uintptr_t symaddr;
[442d0ae]578 char *symbol;
[7f1c620]579 unative_t (*f)(void);
[3701250]580#ifdef ia64
581 struct {
[7f1c620]582 unative_t f;
583 unative_t gp;
[e5dbbe5]584 } fptr;
[3701250]585#endif
[442d0ae]586
[828aa05]587 symaddr = get_symbol_addr((char *) argv->buffer);
[442d0ae]588 if (!symaddr)
589 printf("Symbol %s not found.\n", argv->buffer);
[7f1c620]590 else if (symaddr == (uintptr_t) -1) {
[828aa05]591 symtab_print_search((char *) argv->buffer);
[442d0ae]592 printf("Duplicate symbol, be more specific.\n");
593 } else {
594 symbol = get_symtab_entry(symaddr);
[e5dbbe5]595 printf("Calling %s() (%.*p)\n", symbol, sizeof(uintptr_t) * 2, symaddr);
[3701250]596#ifdef ia64
597 fptr.f = symaddr;
[7f1c620]598 fptr.gp = ((unative_t *)cmd_call2)[1];
599 f = (unative_t (*)(void)) &fptr;
[3701250]600#else
[7f1c620]601 f = (unative_t (*)(void)) symaddr;
[3701250]602#endif
[ad45bde9]603 printf("Result: %#zx\n", f());
[442d0ae]604 }
605
606 return 1;
607}
608
[e5dbbe5]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);
[72bcb25]627 thread_detach(t);
[e5dbbe5]628 } else
629 printf("Unable to create thread for cpu%u\n", i);
630 }
631
632 return 1;
633}
634
[442d0ae]635/** Call function with one parameter */
636int cmd_call1(cmd_arg_t *argv)
637{
[7f1c620]638 uintptr_t symaddr;
[442d0ae]639 char *symbol;
[7f1c620]640 unative_t (*f)(unative_t,...);
641 unative_t arg1 = argv[1].intval;
[3701250]642#ifdef ia64
643 struct {
[7f1c620]644 unative_t f;
645 unative_t gp;
[3701250]646 }fptr;
647#endif
[442d0ae]648
[828aa05]649 symaddr = get_symbol_addr((char *) argv->buffer);
[442d0ae]650 if (!symaddr)
651 printf("Symbol %s not found.\n", argv->buffer);
[7f1c620]652 else if (symaddr == (uintptr_t) -1) {
[828aa05]653 symtab_print_search((char *) argv->buffer);
[442d0ae]654 printf("Duplicate symbol, be more specific.\n");
655 } else {
656 symbol = get_symtab_entry(symaddr);
[3701250]657
[7f1c620]658 printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
[3701250]659#ifdef ia64
660 fptr.f = symaddr;
[7f1c620]661 fptr.gp = ((unative_t *)cmd_call2)[1];
662 f = (unative_t (*)(unative_t,...)) &fptr;
[3701250]663#else
[7f1c620]664 f = (unative_t (*)(unative_t,...)) symaddr;
[3701250]665#endif
[ad45bde9]666 printf("Result: %#zx\n", f(arg1));
[442d0ae]667 }
668
669 return 1;
670}
671
672/** Call function with two parameters */
673int cmd_call2(cmd_arg_t *argv)
674{
[7f1c620]675 uintptr_t symaddr;
[442d0ae]676 char *symbol;
[7f1c620]677 unative_t (*f)(unative_t,unative_t,...);
678 unative_t arg1 = argv[1].intval;
679 unative_t arg2 = argv[2].intval;
[3701250]680#ifdef ia64
681 struct {
[7f1c620]682 unative_t f;
683 unative_t gp;
[3701250]684 }fptr;
685#endif
[442d0ae]686
[828aa05]687 symaddr = get_symbol_addr((char *) argv->buffer);
[442d0ae]688 if (!symaddr)
689 printf("Symbol %s not found.\n", argv->buffer);
[7f1c620]690 else if (symaddr == (uintptr_t) -1) {
[828aa05]691 symtab_print_search((char *) argv->buffer);
[442d0ae]692 printf("Duplicate symbol, be more specific.\n");
693 } else {
694 symbol = get_symtab_entry(symaddr);
[ad45bde9]695 printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
[7f1c620]696 arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
[3701250]697#ifdef ia64
698 fptr.f = symaddr;
[7f1c620]699 fptr.gp = ((unative_t *)cmd_call2)[1];
700 f = (unative_t (*)(unative_t,unative_t,...)) &fptr;
[3701250]701#else
[7f1c620]702 f = (unative_t (*)(unative_t,unative_t,...)) symaddr;
[3701250]703#endif
[ad45bde9]704 printf("Result: %#zx\n", f(arg1, arg2));
[442d0ae]705 }
706
707 return 1;
708}
709
710/** Call function with three parameters */
711int cmd_call3(cmd_arg_t *argv)
712{
[7f1c620]713 uintptr_t symaddr;
[442d0ae]714 char *symbol;
[7f1c620]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;
[3701250]719#ifdef ia64
720 struct {
[7f1c620]721 unative_t f;
722 unative_t gp;
[3701250]723 }fptr;
724#endif
[442d0ae]725
[828aa05]726 symaddr = get_symbol_addr((char *) argv->buffer);
[442d0ae]727 if (!symaddr)
728 printf("Symbol %s not found.\n", argv->buffer);
[7f1c620]729 else if (symaddr == (uintptr_t) -1) {
[828aa05]730 symtab_print_search((char *) argv->buffer);
[442d0ae]731 printf("Duplicate symbol, be more specific.\n");
732 } else {
733 symbol = get_symtab_entry(symaddr);
[ad45bde9]734 printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
[7f1c620]735 arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
[3701250]736#ifdef ia64
737 fptr.f = symaddr;
[7f1c620]738 fptr.gp = ((unative_t *)cmd_call2)[1];
739 f = (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
[3701250]740#else
[7f1c620]741 f = (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
[3701250]742#endif
[ad45bde9]743 printf("Result: %#zx\n", f(arg1, arg2, arg3));
[442d0ae]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 */
[0132630]774int cmd_tlb(cmd_arg_t *argv)
[442d0ae]775{
776 tlb_print();
777 return 1;
778}
[ba276f7]779
780/** Write 4 byte value to address */
781int cmd_set4(cmd_arg_t *argv)
782{
[201abde]783 uint32_t *addr;
[7f1c620]784 uint32_t arg1 = argv[1].intval;
[ba276f7]785 bool pointer = false;
786
787 if (((char *)argv->buffer)[0] == '*') {
[828aa05]788 addr = (uint32_t *) get_symbol_addr((char *) argv->buffer + 1);
[ba276f7]789 pointer = true;
[828aa05]790 } else if (((char *) argv->buffer)[0] >= '0' &&
[ba276f7]791 ((char *)argv->buffer)[0] <= '9')
[7f1c620]792 addr = (uint32_t *)atoi((char *)argv->buffer);
[ba276f7]793 else
[828aa05]794 addr = (uint32_t *)get_symbol_addr((char *) argv->buffer);
[ba276f7]795
796 if (!addr)
797 printf("Symbol %s not found.\n", argv->buffer);
[7f1c620]798 else if (addr == (uint32_t *) -1) {
[828aa05]799 symtab_print_search((char *) argv->buffer);
[ba276f7]800 printf("Duplicate symbol, be more specific.\n");
801 } else {
802 if (pointer)
[7f1c620]803 addr = (uint32_t *)(*(unative_t *)addr);
804 printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
[ba276f7]805 *addr = arg1;
806
807 }
808
809 return 1;
810}
[80bff342]811
[4e147a6]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
[55ab0f1]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
[37c57f2]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
[10e16a7]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
[96cacc1]857/** Command for listing memory zones
858 *
859 * @param argv Ignored
860 *
861 * return Always 1
862 */
[80bff342]863int cmd_zones(cmd_arg_t * argv) {
[dfd9186]864 zone_print_list();
[80bff342]865 return 1;
866}
[0132630]867
[96cacc1]868/** Command for memory zone details
869 *
870 * @param argv Integer argument from cmdline expected
871 *
872 * return Always 1
873 */
[80bff342]874int cmd_zone(cmd_arg_t * argv) {
[dfd9186]875 zone_print_one(argv[0].intval);
[80bff342]876 return 1;
877}
878
[c4e4507]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
[0132630]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}
[41d33ac]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{
[dd054bc2]923 printf("The kernel will now relinquish the console.\n");
924 printf("Use userspace controls to redraw the screen.\n");
[41d33ac]925 arch_release_console();
926 return 1;
927}
[b45c443]928
[50661ab]929#ifdef CONFIG_TEST
[319e60e]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++)
[50661ab]941 printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
[319e60e]942
[50661ab]943 printf("*\t\tRun all safe tests\n");
[319e60e]944 return 1;
945}
946
[62b6d17]947static bool run_test(const test_t *test)
[34db7fa]948{
[62b6d17]949 printf("%s\t\t%s\n", test->name, test->desc);
[cce6acf]950
951 /* Update and read thread accounting
952 for benchmarking */
953 ipl_t ipl = interrupts_disable();
[0313ff0]954 spinlock_lock(&TASK->lock);
955 uint64_t t0 = task_get_accounting(TASK);
956 spinlock_unlock(&TASK->lock);
[cce6acf]957 interrupts_restore(ipl);
958
959 /* Execute the test */
[95155b0c]960 char * ret = test->entry(false);
[cce6acf]961
962 /* Update and read thread accounting */
963 ipl = interrupts_disable();
[0313ff0]964 spinlock_lock(&TASK->lock);
965 uint64_t dt = task_get_accounting(TASK) - t0;
966 spinlock_unlock(&TASK->lock);
[cce6acf]967 interrupts_restore(ipl);
968
[95155b0c]969 uint64_t cycles;
970 char suffix;
971 order(dt, &cycles, &suffix);
972
973 printf("Time: %llu%c cycles\n", cycles, suffix);
[34db7fa]974
975 if (ret == NULL) {
976 printf("Test passed\n");
[62b6d17]977 return true;
[34db7fa]978 }
979
980 printf("%s\n", ret);
[62b6d17]981 return false;
[34db7fa]982}
983
[95155b0c]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
[828aa05]994 uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
[95155b0c]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
[319e60e]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
[828aa05]1060 if (strcmp((char *) argv->buffer, "*") == 0) {
[50661ab]1061 for (test = tests; test->name != NULL; test++) {
1062 if (test->safe) {
[34db7fa]1063 printf("\n");
1064 if (!run_test(test))
1065 break;
[50661ab]1066 }
1067 }
1068 } else {
1069 bool fnd = false;
1070
1071 for (test = tests; test->name != NULL; test++) {
[828aa05]1072 if (strcmp(test->name, (char *) argv->buffer) == 0) {
[50661ab]1073 fnd = true;
[34db7fa]1074 run_test(test);
[50661ab]1075 break;
1076 }
[319e60e]1077 }
[50661ab]1078
1079 if (!fnd)
[34db7fa]1080 printf("Unknown test\n");
[319e60e]1081 }
1082
1083 return 1;
1084}
[95155b0c]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++) {
[828aa05]1100 if (strcmp(test->name, (char *) argv->buffer) == 0) {
[95155b0c]1101 fnd = true;
[c8410ec9]1102
1103 if (test->safe)
1104 run_bench(test, cnt);
1105 else
1106 printf("Unsafe test\n");
1107
[95155b0c]1108 break;
1109 }
1110 }
1111
1112 if (!fnd)
1113 printf("Unknown test\n");
1114
1115 return 1;
1116}
1117
[50661ab]1118#endif
[319e60e]1119
[06e1e95]1120/** @}
[b45c443]1121 */
Note: See TracBrowser for help on using the repository browser.