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

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

merge from measuring branch

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