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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 95319bd was 1ba37fa, checked in by Stanislav Kozina <stanislav.kozina@…>, 15 years ago

Removed useless cycles sum, using ucycles + kcycles instead.

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