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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 20f1597 was 16da5f8e, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

String functions should be declared in string.h (and implemented in string.c) in the kernel.

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