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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 550523f5 was feeac0d, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Simplify use of list_foreach.

  • Property mode set to 100644
File size: 34.0 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>
[e8a1530]58#include <mm/km.h>
[442d0ae]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>
[13a638d]68#include <ipc/event.h>
[b3631bc]69#include <sysinfo/sysinfo.h>
[e2b762ec]70#include <symtab.h>
[e16e0d59]71#include <errno.h>
[e2b762ec]72
[319e60e]73#ifdef CONFIG_TEST
74#include <test.h>
75#endif
76
[b45c443]77/* Data and methods for 'help' command. */
[442d0ae]78static int cmd_help(cmd_arg_t *argv);
79static cmd_info_t help_info = {
80 .name = "help",
[df58e44]81 .description = "List supported commands.",
[442d0ae]82 .func = cmd_help,
83 .argc = 0
84};
85
[e8a1530]86/* Data and methods for pio_read_8 command */
87static int cmd_pio_read_8(cmd_arg_t *argv);
88static cmd_arg_t pio_read_8_argv[] = { { .type = ARG_TYPE_INT } };
89static cmd_info_t pio_read_8_info = {
90 .name = "pio_read_8",
91 .description = "pio_read_8 <address> Read 1 byte from memory (or port).",
92 .func = cmd_pio_read_8,
93 .argc = 1,
94 .argv = pio_read_8_argv
95};
96
97/* Data and methods for pio_read_16 command */
98static int cmd_pio_read_16(cmd_arg_t *argv);
99static cmd_arg_t pio_read_16_argv[] = { { .type = ARG_TYPE_INT } };
100static cmd_info_t pio_read_16_info = {
101 .name = "pio_read_16",
102 .description = "pio_read_16 <address> Read 2 bytes from memory (or port).",
103 .func = cmd_pio_read_16,
104 .argc = 1,
105 .argv = pio_read_16_argv
106};
107
108/* Data and methods for pio_read_32 command */
109static int cmd_pio_read_32(cmd_arg_t *argv);
110static cmd_arg_t pio_read_32_argv[] = { { .type = ARG_TYPE_INT } };
111static cmd_info_t pio_read_32_info = {
112 .name = "pio_read_32",
113 .description = "pio_read_32 <address> Read 4 bytes from memory (or port).",
114 .func = cmd_pio_read_32,
115 .argc = 1,
116 .argv = pio_read_32_argv
117};
118
119/* Data and methods for pio_write_8 command */
120static int cmd_pio_write_8(cmd_arg_t *argv);
121static cmd_arg_t pio_write_8_argv[] = {
122 { .type = ARG_TYPE_INT },
123 { .type = ARG_TYPE_INT }
124};
125static cmd_info_t pio_write_8_info = {
126 .name = "pio_write_8",
127 .description = "pio_write_8 <address> <value> Write 1 byte to memory (or port).",
128 .func = cmd_pio_write_8,
129 .argc = 2,
130 .argv = pio_write_8_argv
131};
132
133/* Data and methods for pio_write_16 command */
134static int cmd_pio_write_16(cmd_arg_t *argv);
135static cmd_arg_t pio_write_16_argv[] = {
136 { .type = ARG_TYPE_INT },
137 { .type = ARG_TYPE_INT }
138};
139static cmd_info_t pio_write_16_info = {
140 .name = "pio_write_16",
141 .description = "pio_write_16 <address> <value> Write 2 bytes to memory (or port).",
142 .func = cmd_pio_write_16,
143 .argc = 2,
144 .argv = pio_write_16_argv
145};
146
147/* Data and methods for pio_write_32 command */
148static int cmd_pio_write_32(cmd_arg_t *argv);
149static cmd_arg_t pio_write_32_argv[] = {
150 { .type = ARG_TYPE_INT },
151 { .type = ARG_TYPE_INT }
152};
153static cmd_info_t pio_write_32_info = {
154 .name = "pio_write_32",
155 .description = "pio_write_32 <address> <value> Write 4 bytes to memory (or port).",
156 .func = cmd_pio_write_32,
157 .argc = 2,
158 .argv = pio_write_32_argv
159};
160
[df58e44]161/* Data and methods for 'reboot' command. */
[f74bbaf]162static int cmd_reboot(cmd_arg_t *argv);
163static cmd_info_t reboot_info = {
164 .name = "reboot",
[df58e44]165 .description = "Reboot system.",
[f74bbaf]166 .func = cmd_reboot,
[e07fe0c]167 .argc = 0
168};
169
[df58e44]170/* Data and methods for 'uptime' command. */
[4b662f8c]171static int cmd_uptime(cmd_arg_t *argv);
172static cmd_info_t uptime_info = {
173 .name = "uptime",
[df58e44]174 .description = "Show system uptime.",
[4b662f8c]175 .func = cmd_uptime,
176 .argc = 0
177};
178
[df58e44]179/* Data and methods for 'continue' command. */
[41d33ac]180static int cmd_continue(cmd_arg_t *argv);
181static cmd_info_t continue_info = {
182 .name = "continue",
[319e60e]183 .description = "Return console back to userspace.",
[41d33ac]184 .func = cmd_continue,
185 .argc = 0
186};
187
[319e60e]188#ifdef CONFIG_TEST
[5b7a107]189
[df58e44]190/* Data and methods for 'test' command. */
[319e60e]191static char test_buf[MAX_CMDLINE + 1];
192static int cmd_test(cmd_arg_t *argv);
193static cmd_arg_t test_argv[] = {
194 {
[851f33a]195 .type = ARG_TYPE_STRING_OPTIONAL,
[319e60e]196 .buffer = test_buf,
197 .len = sizeof(test_buf)
198 }
199};
200static cmd_info_t test_info = {
201 .name = "test",
[df58e44]202 .description = "<test> List kernel tests or run a test.",
[319e60e]203 .func = cmd_test,
204 .argc = 1,
205 .argv = test_argv
206};
[95155b0c]207
[df58e44]208/* Data and methods for 'bench' command. */
[95155b0c]209static int cmd_bench(cmd_arg_t *argv);
210static cmd_arg_t bench_argv[] = {
211 {
212 .type = ARG_TYPE_STRING,
213 .buffer = test_buf,
214 .len = sizeof(test_buf)
215 },
216 {
217 .type = ARG_TYPE_INT,
218 }
219};
220static cmd_info_t bench_info = {
221 .name = "bench",
[df58e44]222 .description = "<test> <count> Run kernel test as benchmark.",
[95155b0c]223 .func = cmd_bench,
224 .argc = 2,
225 .argv = bench_argv
226};
[5b7a107]227
228#endif /* CONFIG_TEST */
[319e60e]229
[b45c443]230/* Data and methods for 'description' command. */
[442d0ae]231static int cmd_desc(cmd_arg_t *argv);
232static void desc_help(void);
[df58e44]233static char desc_buf[MAX_CMDLINE + 1];
[442d0ae]234static cmd_arg_t desc_argv = {
235 .type = ARG_TYPE_STRING,
236 .buffer = desc_buf,
237 .len = sizeof(desc_buf)
238};
239static cmd_info_t desc_info = {
240 .name = "describe",
[df58e44]241 .description = "<command> Describe specified command.",
[442d0ae]242 .help = desc_help,
243 .func = cmd_desc,
244 .argc = 1,
245 .argv = &desc_argv
246};
247
[b45c443]248/* Data and methods for 'symaddr' command. */
[442d0ae]249static int cmd_symaddr(cmd_arg_t *argv);
[df58e44]250static char symaddr_buf[MAX_CMDLINE + 1];
[442d0ae]251static cmd_arg_t symaddr_argv = {
252 .type = ARG_TYPE_STRING,
253 .buffer = symaddr_buf,
254 .len = sizeof(symaddr_buf)
255};
256static cmd_info_t symaddr_info = {
257 .name = "symaddr",
[df58e44]258 .description = "<symbol> Return symbol address.",
[442d0ae]259 .func = cmd_symaddr,
260 .argc = 1,
261 .argv = &symaddr_argv
262};
263
[df58e44]264/* Data and methods for 'set4' command. */
265static char set_buf[MAX_CMDLINE + 1];
[ba276f7]266static int cmd_set4(cmd_arg_t *argv);
267static cmd_arg_t set4_argv[] = {
268 {
269 .type = ARG_TYPE_STRING,
270 .buffer = set_buf,
271 .len = sizeof(set_buf)
272 },
273 {
274 .type = ARG_TYPE_INT
275 }
276};
277static cmd_info_t set4_info = {
278 .name = "set4",
[df58e44]279 .description = "<addr> <value> Set 4B memory location to a value.",
[ba276f7]280 .func = cmd_set4,
281 .argc = 2,
282 .argv = set4_argv
283};
284
[c0f13d2]285/* Data and methods for 'call0' and 'mcall0' command. */
[e5dbbe5]286static char call0_buf[MAX_CMDLINE + 1];
287static char carg1_buf[MAX_CMDLINE + 1];
288static char carg2_buf[MAX_CMDLINE + 1];
289static char carg3_buf[MAX_CMDLINE + 1];
[442d0ae]290
291static int cmd_call0(cmd_arg_t *argv);
292static cmd_arg_t call0_argv = {
293 .type = ARG_TYPE_STRING,
294 .buffer = call0_buf,
295 .len = sizeof(call0_buf)
296};
297static cmd_info_t call0_info = {
298 .name = "call0",
[df58e44]299 .description = "<function> Call function().",
[442d0ae]300 .func = cmd_call0,
301 .argc = 1,
302 .argv = &call0_argv
303};
304
[e5dbbe5]305/* Data and methods for 'mcall0' command. */
306static int cmd_mcall0(cmd_arg_t *argv);
307static cmd_arg_t mcall0_argv = {
308 .type = ARG_TYPE_STRING,
309 .buffer = call0_buf,
310 .len = sizeof(call0_buf)
311};
312static cmd_info_t mcall0_info = {
313 .name = "mcall0",
[df58e44]314 .description = "<function> Call function() on each CPU.",
[e5dbbe5]315 .func = cmd_mcall0,
316 .argc = 1,
317 .argv = &mcall0_argv
318};
319
[b45c443]320/* Data and methods for 'call1' command. */
[442d0ae]321static int cmd_call1(cmd_arg_t *argv);
322static cmd_arg_t call1_argv[] = {
323 {
324 .type = ARG_TYPE_STRING,
325 .buffer = call0_buf,
326 .len = sizeof(call0_buf)
327 },
328 {
329 .type = ARG_TYPE_VAR,
330 .buffer = carg1_buf,
331 .len = sizeof(carg1_buf)
332 }
333};
334static cmd_info_t call1_info = {
335 .name = "call1",
[df58e44]336 .description = "<function> <arg1> Call function(arg1).",
[442d0ae]337 .func = cmd_call1,
338 .argc = 2,
339 .argv = call1_argv
340};
341
[b45c443]342/* Data and methods for 'call2' command. */
[442d0ae]343static int cmd_call2(cmd_arg_t *argv);
344static cmd_arg_t call2_argv[] = {
345 {
346 .type = ARG_TYPE_STRING,
347 .buffer = call0_buf,
348 .len = sizeof(call0_buf)
349 },
350 {
351 .type = ARG_TYPE_VAR,
352 .buffer = carg1_buf,
353 .len = sizeof(carg1_buf)
354 },
355 {
356 .type = ARG_TYPE_VAR,
357 .buffer = carg2_buf,
358 .len = sizeof(carg2_buf)
359 }
360};
361static cmd_info_t call2_info = {
362 .name = "call2",
[df58e44]363 .description = "<function> <arg1> <arg2> Call function(arg1, arg2).",
[442d0ae]364 .func = cmd_call2,
365 .argc = 3,
366 .argv = call2_argv
367};
368
[b45c443]369/* Data and methods for 'call3' command. */
[442d0ae]370static int cmd_call3(cmd_arg_t *argv);
371static cmd_arg_t call3_argv[] = {
372 {
373 .type = ARG_TYPE_STRING,
374 .buffer = call0_buf,
375 .len = sizeof(call0_buf)
376 },
377 {
378 .type = ARG_TYPE_VAR,
379 .buffer = carg1_buf,
380 .len = sizeof(carg1_buf)
381 },
382 {
383 .type = ARG_TYPE_VAR,
384 .buffer = carg2_buf,
385 .len = sizeof(carg2_buf)
386 },
387 {
388 .type = ARG_TYPE_VAR,
389 .buffer = carg3_buf,
390 .len = sizeof(carg3_buf)
391 }
392
393};
394static cmd_info_t call3_info = {
395 .name = "call3",
[df58e44]396 .description = "<function> <arg1> <arg2> <arg3> Call function(arg1, arg2, arg3).",
[442d0ae]397 .func = cmd_call3,
398 .argc = 4,
399 .argv = call3_argv
400};
401
[b45c443]402/* Data and methods for 'halt' command. */
[442d0ae]403static int cmd_halt(cmd_arg_t *argv);
404static cmd_info_t halt_info = {
405 .name = "halt",
406 .description = "Halt the kernel.",
407 .func = cmd_halt,
408 .argc = 0
409};
410
[b07c332]411/* Data and methods for 'physmem' command. */
412static int cmd_physmem(cmd_arg_t *argv);
413cmd_info_t physmem_info = {
414 .name = "physmem",
415 .description = "Print physical memory configuration.",
416 .help = NULL,
417 .func = cmd_physmem,
418 .argc = 0,
419 .argv = NULL
420};
421
[b45c443]422/* Data and methods for 'tlb' command. */
[0132630]423static int cmd_tlb(cmd_arg_t *argv);
424cmd_info_t tlb_info = {
425 .name = "tlb",
[df58e44]426 .description = "Print TLB of the current CPU.",
[442d0ae]427 .help = NULL,
[0132630]428 .func = cmd_tlb,
[442d0ae]429 .argc = 0,
430 .argv = NULL
431};
432
[48dcc69]433static char flag_buf[MAX_CMDLINE + 1];
434
[55ab0f1]435static int cmd_threads(cmd_arg_t *argv);
[48dcc69]436static cmd_arg_t threads_argv = {
437 .type = ARG_TYPE_STRING_OPTIONAL,
438 .buffer = flag_buf,
439 .len = sizeof(flag_buf)
440};
[55ab0f1]441static cmd_info_t threads_info = {
442 .name = "threads",
[48dcc69]443 .description = "List all threads (use -a for additional information).",
[55ab0f1]444 .func = cmd_threads,
[48dcc69]445 .argc = 1,
446 .argv = &threads_argv
[55ab0f1]447};
448
[37c57f2]449static int cmd_tasks(cmd_arg_t *argv);
[c0f13d2]450static cmd_arg_t tasks_argv = {
451 .type = ARG_TYPE_STRING_OPTIONAL,
[48dcc69]452 .buffer = flag_buf,
453 .len = sizeof(flag_buf)
[c0f13d2]454};
[37c57f2]455static cmd_info_t tasks_info = {
456 .name = "tasks",
[c0f13d2]457 .description = "List all tasks (use -a for additional information).",
[37c57f2]458 .func = cmd_tasks,
[c0f13d2]459 .argc = 1,
460 .argv = &tasks_argv
[37c57f2]461};
462
[5b7a107]463#ifdef CONFIG_UDEBUG
464
[df58e44]465/* Data and methods for 'btrace' command */
466static int cmd_btrace(cmd_arg_t *argv);
467static cmd_arg_t btrace_argv = {
468 .type = ARG_TYPE_INT,
469};
470static cmd_info_t btrace_info = {
471 .name = "btrace",
472 .description = "<threadid> Show thread stack trace.",
473 .func = cmd_btrace,
474 .argc = 1,
475 .argv = &btrace_argv
476};
[80bff342]477
[5b7a107]478#endif /* CONFIG_UDEBUG */
[80bff342]479
[10e16a7]480static int cmd_sched(cmd_arg_t *argv);
481static cmd_info_t sched_info = {
482 .name = "scheduler",
[df58e44]483 .description = "Show scheduler information.",
[10e16a7]484 .func = cmd_sched,
485 .argc = 0
486};
487
[4e147a6]488static int cmd_slabs(cmd_arg_t *argv);
489static cmd_info_t slabs_info = {
490 .name = "slabs",
[dd054bc2]491 .description = "List slab caches.",
[4e147a6]492 .func = cmd_slabs,
493 .argc = 0
494};
495
[b3631bc]496static int cmd_sysinfo(cmd_arg_t *argv);
497static cmd_info_t sysinfo_info = {
498 .name = "sysinfo",
499 .description = "Dump sysinfo.",
500 .func = cmd_sysinfo,
501 .argc = 0
502};
503
[b45c443]504/* Data and methods for 'zones' command */
[80bff342]505static int cmd_zones(cmd_arg_t *argv);
506static cmd_info_t zones_info = {
507 .name = "zones",
[df58e44]508 .description = "List memory zones.",
[80bff342]509 .func = cmd_zones,
510 .argc = 0
511};
512
[df58e44]513/* Data and methods for 'zone' command */
514static int cmd_zone(cmd_arg_t *argv);
515static cmd_arg_t zone_argv = {
516 .type = ARG_TYPE_INT,
517};
518
519static cmd_info_t zone_info = {
520 .name = "zone",
521 .description = "<zone> Show memory zone structure.",
522 .func = cmd_zone,
523 .argc = 1,
524 .argv = &zone_argv
525};
526
[073c9e6]527/* Data and methods for 'ipc' command */
528static int cmd_ipc(cmd_arg_t *argv);
529static cmd_arg_t ipc_argv = {
[c4e4507]530 .type = ARG_TYPE_INT,
531};
[073c9e6]532static cmd_info_t ipc_info = {
533 .name = "ipc",
[df58e44]534 .description = "<taskid> Show IPC information of a task.",
[073c9e6]535 .func = cmd_ipc,
[c4e4507]536 .argc = 1,
[073c9e6]537 .argv = &ipc_argv
[c4e4507]538};
539
[2a75302]540/* Data and methods for 'kill' command */
541static int cmd_kill(cmd_arg_t *argv);
542static cmd_arg_t kill_argv = {
543 .type = ARG_TYPE_INT,
544};
545static cmd_info_t kill_info = {
546 .name = "kill",
[df58e44]547 .description = "<taskid> Kill a task.",
[2a75302]548 .func = cmd_kill,
549 .argc = 1,
550 .argv = &kill_argv
551};
552
[b45c443]553/* Data and methods for 'cpus' command. */
[0132630]554static int cmd_cpus(cmd_arg_t *argv);
555cmd_info_t cpus_info = {
556 .name = "cpus",
557 .description = "List all processors.",
558 .help = NULL,
559 .func = cmd_cpus,
560 .argc = 0,
561 .argv = NULL
562};
563
[b45c443]564/* Data and methods for 'version' command. */
[0132630]565static int cmd_version(cmd_arg_t *argv);
566cmd_info_t version_info = {
567 .name = "version",
568 .description = "Print version information.",
569 .help = NULL,
570 .func = cmd_version,
571 .argc = 0,
572 .argv = NULL
573};
574
[10e16a7]575static cmd_info_t *basic_commands[] = {
576 &call0_info,
[e5dbbe5]577 &mcall0_info,
[10e16a7]578 &call1_info,
579 &call2_info,
580 &call3_info,
[41d33ac]581 &continue_info,
[10e16a7]582 &cpus_info,
583 &desc_info,
584 &halt_info,
585 &help_info,
[073c9e6]586 &ipc_info,
[2a75302]587 &kill_info,
[df58e44]588 &physmem_info,
589 &reboot_info,
590 &sched_info,
[10e16a7]591 &set4_info,
592 &slabs_info,
593 &symaddr_info,
[df58e44]594 &sysinfo_info,
[37c57f2]595 &tasks_info,
[df58e44]596 &threads_info,
[10e16a7]597 &tlb_info,
[df58e44]598 &uptime_info,
[10e16a7]599 &version_info,
600 &zones_info,
601 &zone_info,
[319e60e]602#ifdef CONFIG_TEST
603 &test_info,
[95155b0c]604 &bench_info,
[5b7a107]605#endif
606#ifdef CONFIG_UDEBUG
607 &btrace_info,
[319e60e]608#endif
[e8a1530]609 &pio_read_8_info,
610 &pio_read_16_info,
611 &pio_read_32_info,
612 &pio_write_8_info,
613 &pio_write_16_info,
614 &pio_write_32_info,
[10e16a7]615 NULL
616};
[80bff342]617
618
[442d0ae]619/** Initialize command info structure.
620 *
621 * @param cmd Command info structure.
622 *
623 */
624void cmd_initialize(cmd_info_t *cmd)
625{
[da1bafb]626 spinlock_initialize(&cmd->lock, "cmd.lock");
[442d0ae]627 link_initialize(&cmd->link);
628}
629
630/** Initialize and register commands. */
631void cmd_init(void)
632{
[b07c332]633 unsigned int i;
[80bff342]634
[b07c332]635 for (i = 0; basic_commands[i]; i++) {
[10e16a7]636 cmd_initialize(basic_commands[i]);
[40fb017]637 }
638
639 for (i = 0; basic_commands[i]; i++) {
640 if (!cmd_register(basic_commands[i])) {
641 printf("Cannot register command %s\n",
642 basic_commands[i]->name);
643 }
[10e16a7]644 }
[442d0ae]645}
646
647/** List supported commands.
648 *
649 * @param argv Argument vector.
650 *
651 * @return 0 on failure, 1 on success.
652 */
653int cmd_help(cmd_arg_t *argv)
654{
655 spinlock_lock(&cmd_lock);
656
[98000fb]657 size_t len = 0;
[feeac0d]658 list_foreach(cmd_list, link, cmd_info_t, hlp) {
[442d0ae]659 spinlock_lock(&hlp->lock);
[20cc877]660 if (str_length(hlp->name) > len)
661 len = str_length(hlp->name);
[c1f7f6ea]662 spinlock_unlock(&hlp->lock);
663 }
664
[0b0f4bb]665 unsigned int _len = (unsigned int) len;
666 if ((_len != len) || (((int) _len) < 0)) {
667 printf("Command length overflow\n");
668 return 1;
669 }
670
[feeac0d]671 list_foreach(cmd_list, link, cmd_info_t, hlp) {
[c1f7f6ea]672 spinlock_lock(&hlp->lock);
[0b0f4bb]673 printf("%-*s %s\n", _len, hlp->name, hlp->description);
[442d0ae]674 spinlock_unlock(&hlp->lock);
675 }
676
[ae318d3]677 spinlock_unlock(&cmd_lock);
[c1f7f6ea]678
[442d0ae]679 return 1;
680}
681
[e8a1530]682/** Read 1 byte from phys memory or io port.
683 *
684 * @param argv Argument vector.
685 *
686 * @return 0 on failure, 1 on success.
687 */
688static int cmd_pio_read_8(cmd_arg_t *argv)
689{
690 uint8_t *ptr = NULL;
[2f33fbc]691
[e8a1530]692#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]693 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
694 ptr = (void *) argv[0].intval;
[e8a1530]695 else
696#endif
[2f33fbc]697 ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
[3f6c16fe]698 PAGE_NOT_CACHEABLE);
[2f33fbc]699
[e8a1530]700 const uint8_t val = pio_read_8(ptr);
[2f33fbc]701 printf("read %" PRIxn ": %" PRIx8 "\n", argv[0].intval, val);
702
[e8a1530]703#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]704 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]705 return 1;
706#endif
[2f33fbc]707
708 km_unmap((uintptr_t) ptr, sizeof(uint8_t));
[e8a1530]709 return 1;
710}
711
712/** Read 2 bytes from phys memory or io port.
713 *
714 * @param argv Argument vector.
715 *
716 * @return 0 on failure, 1 on success.
717 */
718static int cmd_pio_read_16(cmd_arg_t *argv)
719{
720 uint16_t *ptr = NULL;
[2f33fbc]721
[e8a1530]722#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]723 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[2f33fbc]724 ptr = (void *) argv[0].intval;
[e8a1530]725 else
726#endif
[2f33fbc]727 ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
[3f6c16fe]728 PAGE_NOT_CACHEABLE);
[2f33fbc]729
[e8a1530]730 const uint16_t val = pio_read_16(ptr);
[2f33fbc]731 printf("read %" PRIxn ": %" PRIx16 "\n", argv[0].intval, val);
732
[e8a1530]733#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]734 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]735 return 1;
736#endif
[2f33fbc]737
738 km_unmap((uintptr_t) ptr, sizeof(uint16_t));
[e8a1530]739 return 1;
740}
741
742/** Read 4 bytes from phys memory or io port.
743 *
744 * @param argv Argument vector.
745 *
746 * @return 0 on failure, 1 on success.
747 */
748static int cmd_pio_read_32(cmd_arg_t *argv)
749{
750 uint32_t *ptr = NULL;
[2f33fbc]751
[e8a1530]752#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]753 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
754 ptr = (void *) argv[0].intval;
[e8a1530]755 else
756#endif
[2f33fbc]757 ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
[3f6c16fe]758 PAGE_NOT_CACHEABLE);
[2f33fbc]759
[e8a1530]760 const uint32_t val = pio_read_32(ptr);
[2f33fbc]761 printf("read %" PRIxn ": %" PRIx32 "\n", argv[0].intval, val);
762
[e8a1530]763#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]764 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]765 return 1;
766#endif
[2f33fbc]767
768 km_unmap((uintptr_t) ptr, sizeof(uint32_t));
[e8a1530]769 return 1;
770}
771
772/** Write 1 byte to phys memory or io port.
773 *
774 * @param argv Argument vector.
775 *
776 * @return 0 on failure, 1 on success.
777 */
778static int cmd_pio_write_8(cmd_arg_t *argv)
779{
780 uint8_t *ptr = NULL;
[2f33fbc]781
[e8a1530]782#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]783 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
784 ptr = (void *) argv[0].intval;
[e8a1530]785 else
786#endif
[2f33fbc]787 ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
[3f6c16fe]788 PAGE_NOT_CACHEABLE);
[2f33fbc]789
790 printf("write %" PRIxn ": %" PRIx8 "\n", argv[0].intval,
791 (uint8_t) argv[1].intval);
792 pio_write_8(ptr, (uint8_t) argv[1].intval);
793
[e8a1530]794#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]795 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]796 return 1;
797#endif
[2f33fbc]798
799 km_unmap((uintptr_t) ptr, sizeof(uint8_t));
[e8a1530]800 return 1;
801}
802
803/** Write 2 bytes to phys memory or io port.
804 *
805 * @param argv Argument vector.
806 *
807 * @return 0 on failure, 1 on success.
808 */
809static int cmd_pio_write_16(cmd_arg_t *argv)
810{
811 uint16_t *ptr = NULL;
[2f33fbc]812
[e8a1530]813#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]814 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
815 ptr = (void *) argv[0].intval;
[e8a1530]816 else
817#endif
[2f33fbc]818 ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
[3f6c16fe]819 PAGE_NOT_CACHEABLE);
[2f33fbc]820
821 printf("write %" PRIxn ": %" PRIx16 "\n", argv[0].intval,
822 (uint16_t) argv[1].intval);
823 pio_write_16(ptr, (uint16_t) argv[1].intval);
824
[e8a1530]825#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]826 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]827 return 1;
828#endif
[2f33fbc]829
830 km_unmap((uintptr_t) ptr, sizeof(uint16_t));
[e8a1530]831 return 1;
832}
833
834/** Write 4 bytes to phys memory or io port.
835 *
836 * @param argv Argument vector.
837 *
838 * @return 0 on failure, 1 on success.
839 */
840static int cmd_pio_write_32(cmd_arg_t *argv)
841{
842 uint32_t *ptr = NULL;
[2f33fbc]843
[e8a1530]844#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]845 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
846 ptr = (void *) argv[0].intval;
[e8a1530]847 else
848#endif
[2f33fbc]849 ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
[3f6c16fe]850 PAGE_NOT_CACHEABLE);
[2f33fbc]851
852 printf("write %" PRIxn ": %" PRIx32 "\n", argv[0].intval,
853 (uint32_t) argv[1].intval);
854 pio_write_32(ptr, (uint32_t) argv[1].intval);
855
[e8a1530]856#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]857 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]858 return 1;
859#endif
[2f33fbc]860
861 km_unmap((uintptr_t) ptr, sizeof(uint32_t));
[e8a1530]862 return 1;
863}
864
[f74bbaf]865/** Reboot the system.
866 *
867 * @param argv Argument vector.
868 *
869 * @return 0 on failure, 1 on success.
870 */
871int cmd_reboot(cmd_arg_t *argv)
872{
873 reboot();
874
875 /* Not reached */
876 return 1;
877}
878
[4b662f8c]879/** Print system uptime information.
880 *
881 * @param argv Argument vector.
882 *
883 * @return 0 on failure, 1 on success.
884 */
885int cmd_uptime(cmd_arg_t *argv)
886{
887 ASSERT(uptime);
888
889 /* This doesn't have to be very accurate */
[96b02eb9]890 sysarg_t sec = uptime->seconds1;
[4b662f8c]891
[c859753]892 printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n",
[4b662f8c]893 sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60);
894
895 return 1;
896}
897
[442d0ae]898/** Describe specified command.
899 *
900 * @param argv Argument vector.
901 *
902 * @return 0 on failure, 1 on success.
903 */
904int cmd_desc(cmd_arg_t *argv)
905{
906 spinlock_lock(&cmd_lock);
907
[feeac0d]908 list_foreach(cmd_list, link, cmd_info_t, hlp) {
[442d0ae]909 spinlock_lock(&hlp->lock);
[20cc877]910
911 if (str_lcmp(hlp->name, (const char *) argv->buffer, str_length(hlp->name)) == 0) {
[442d0ae]912 printf("%s - %s\n", hlp->name, hlp->description);
913 if (hlp->help)
914 hlp->help();
915 spinlock_unlock(&hlp->lock);
916 break;
917 }
[20cc877]918
[442d0ae]919 spinlock_unlock(&hlp->lock);
920 }
921
922 spinlock_unlock(&cmd_lock);
[20cc877]923
[442d0ae]924 return 1;
925}
926
927/** Search symbol table */
928int cmd_symaddr(cmd_arg_t *argv)
929{
[828aa05]930 symtab_print_search((char *) argv->buffer);
[442d0ae]931
932 return 1;
933}
934
935/** Call function with zero parameters */
936int cmd_call0(cmd_arg_t *argv)
937{
[7f1c620]938 uintptr_t symaddr;
[e16e0d59]939 char *symbol;
[96b02eb9]940 sysarg_t (*fnc)(void);
[0f81ceb7]941 fncptr_t fptr;
[e16e0d59]942 int rc;
[e2b762ec]943
[e16e0d59]944 symbol = (char *) argv->buffer;
945 rc = symtab_addr_lookup(symbol, &symaddr);
946
947 if (rc == ENOENT)
948 printf("Symbol %s not found.\n", symbol);
949 else if (rc == EOVERFLOW) {
950 symtab_print_search(symbol);
[442d0ae]951 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]952 } else if (rc == EOK) {
[c992538a]953 ipl_t ipl;
954
955 ipl = interrupts_disable();
[96b02eb9]956 fnc = (sysarg_t (*)(void)) arch_construct_function(&fptr,
[e16e0d59]957 (void *) symaddr, (void *) cmd_call0);
[0b0f4bb]958 printf("Calling %s() (%p)\n", symbol, (void *) symaddr);
[0f81ceb7]959 printf("Result: %#" PRIxn "\n", fnc());
[c992538a]960 interrupts_restore(ipl);
[e16e0d59]961 } else {
962 printf("No symbol information available.\n");
[442d0ae]963 }
964 return 1;
965}
966
[e5dbbe5]967/** Call function with zero parameters on each CPU */
968int cmd_mcall0(cmd_arg_t *argv)
969{
970 /*
971 * For each CPU, create a thread which will
972 * call the function.
973 */
974
[0b0f4bb]975 unsigned int i;
[e5dbbe5]976 for (i = 0; i < config.cpu_count; i++) {
[b8f11baa]977 if (!cpus[i].active)
978 continue;
979
[da1bafb]980 thread_t *thread;
981 if ((thread = thread_create((void (*)(void *)) cmd_call0,
[6eef3c4]982 (void *) argv, TASK, THREAD_FLAG_NONE, "call0"))) {
[0b0f4bb]983 printf("cpu%u: ", i);
[6eef3c4]984 thread_wire(thread, &cpus[i]);
[da1bafb]985 thread_ready(thread);
986 thread_join(thread);
987 thread_detach(thread);
[e5dbbe5]988 } else
[0b0f4bb]989 printf("Unable to create thread for cpu%u\n", i);
[e5dbbe5]990 }
991
992 return 1;
993}
994
[442d0ae]995/** Call function with one parameter */
996int cmd_call1(cmd_arg_t *argv)
997{
[7f1c620]998 uintptr_t symaddr;
[442d0ae]999 char *symbol;
[96b02eb9]1000 sysarg_t (*fnc)(sysarg_t, ...);
1001 sysarg_t arg1 = argv[1].intval;
[0f81ceb7]1002 fncptr_t fptr;
[e16e0d59]1003 int rc;
[e2b762ec]1004
[e16e0d59]1005 symbol = (char *) argv->buffer;
1006 rc = symtab_addr_lookup(symbol, &symaddr);
1007
1008 if (rc == ENOENT) {
1009 printf("Symbol %s not found.\n", symbol);
1010 } else if (rc == EOVERFLOW) {
1011 symtab_print_search(symbol);
[442d0ae]1012 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]1013 } else if (rc == EOK) {
[c992538a]1014 ipl_t ipl;
1015
1016 ipl = interrupts_disable();
[96b02eb9]1017 fnc = (sysarg_t (*)(sysarg_t, ...))
[0b0f4bb]1018 arch_construct_function(&fptr, (void *) symaddr,
1019 (void *) cmd_call1);
1020 printf("Calling f(%#" PRIxn "): %p: %s\n", arg1,
1021 (void *) symaddr, symbol);
[0f81ceb7]1022 printf("Result: %#" PRIxn "\n", fnc(arg1));
[c992538a]1023 interrupts_restore(ipl);
[e16e0d59]1024 } else {
1025 printf("No symbol information available.\n");
[442d0ae]1026 }
[e16e0d59]1027
[442d0ae]1028 return 1;
1029}
1030
1031/** Call function with two parameters */
1032int cmd_call2(cmd_arg_t *argv)
1033{
[7f1c620]1034 uintptr_t symaddr;
[442d0ae]1035 char *symbol;
[96b02eb9]1036 sysarg_t (*fnc)(sysarg_t, sysarg_t, ...);
1037 sysarg_t arg1 = argv[1].intval;
1038 sysarg_t arg2 = argv[2].intval;
[0f81ceb7]1039 fncptr_t fptr;
[e16e0d59]1040 int rc;
1041
1042 symbol = (char *) argv->buffer;
1043 rc = symtab_addr_lookup(symbol, &symaddr);
1044
1045 if (rc == ENOENT) {
1046 printf("Symbol %s not found.\n", symbol);
1047 } else if (rc == EOVERFLOW) {
1048 symtab_print_search(symbol);
[442d0ae]1049 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]1050 } else if (rc == EOK) {
[c992538a]1051 ipl_t ipl;
1052
1053 ipl = interrupts_disable();
[96b02eb9]1054 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, ...))
[0b0f4bb]1055 arch_construct_function(&fptr, (void *) symaddr,
1056 (void *) cmd_call2);
[c859753]1057 printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n",
[0b0f4bb]1058 arg1, arg2, (void *) symaddr, symbol);
[0f81ceb7]1059 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2));
[c992538a]1060 interrupts_restore(ipl);
[e16e0d59]1061 } else {
1062 printf("No symbol information available.\n");
1063 }
[442d0ae]1064 return 1;
1065}
1066
1067/** Call function with three parameters */
1068int cmd_call3(cmd_arg_t *argv)
1069{
[7f1c620]1070 uintptr_t symaddr;
[442d0ae]1071 char *symbol;
[96b02eb9]1072 sysarg_t (*fnc)(sysarg_t, sysarg_t, sysarg_t, ...);
1073 sysarg_t arg1 = argv[1].intval;
1074 sysarg_t arg2 = argv[2].intval;
1075 sysarg_t arg3 = argv[3].intval;
[0f81ceb7]1076 fncptr_t fptr;
[e16e0d59]1077 int rc;
[0f81ceb7]1078
[e16e0d59]1079 symbol = (char *) argv->buffer;
1080 rc = symtab_addr_lookup(symbol, &symaddr);
1081
1082 if (rc == ENOENT) {
1083 printf("Symbol %s not found.\n", symbol);
1084 } else if (rc == EOVERFLOW) {
1085 symtab_print_search(symbol);
[442d0ae]1086 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]1087 } else if (rc == EOK) {
[c992538a]1088 ipl_t ipl;
1089
1090 ipl = interrupts_disable();
[96b02eb9]1091 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, sysarg_t, ...))
[0b0f4bb]1092 arch_construct_function(&fptr, (void *) symaddr,
1093 (void *) cmd_call3);
1094 printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n",
1095 arg1, arg2, arg3, (void *) symaddr, symbol);
[0f81ceb7]1096 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3));
[c992538a]1097 interrupts_restore(ipl);
[e16e0d59]1098 } else {
1099 printf("No symbol information available.\n");
[442d0ae]1100 }
1101 return 1;
1102}
1103
1104/** Print detailed description of 'describe' command. */
1105void desc_help(void)
1106{
1107 printf("Syntax: describe command_name\n");
1108}
1109
1110/** Halt the kernel.
1111 *
1112 * @param argv Argument vector (ignored).
1113 *
1114 * @return 0 on failure, 1 on success (never returns).
1115 */
1116int cmd_halt(cmd_arg_t *argv)
1117{
1118 halt();
1119 return 1;
1120}
1121
1122/** Command for printing TLB contents.
1123 *
1124 * @param argv Not used.
1125 *
1126 * @return Always returns 1.
1127 */
[0132630]1128int cmd_tlb(cmd_arg_t *argv)
[442d0ae]1129{
1130 tlb_print();
1131 return 1;
1132}
[ba276f7]1133
[b07c332]1134/** Command for printing physical memory configuration.
1135 *
1136 * @param argv Not used.
1137 *
1138 * @return Always returns 1.
1139 */
1140int cmd_physmem(cmd_arg_t *argv)
1141{
1142 physmem_print();
1143 return 1;
1144}
1145
[ba276f7]1146/** Write 4 byte value to address */
1147int cmd_set4(cmd_arg_t *argv)
1148{
[e16e0d59]1149 uintptr_t addr;
[7f1c620]1150 uint32_t arg1 = argv[1].intval;
[ba276f7]1151 bool pointer = false;
[e16e0d59]1152 int rc;
[4ce914d4]1153
1154 if (((char *) argv->buffer)[0] == '*') {
[e16e0d59]1155 rc = symtab_addr_lookup((char *) argv->buffer + 1, &addr);
[ba276f7]1156 pointer = true;
[4ce914d4]1157 } else if (((char *) argv->buffer)[0] >= '0' &&
1158 ((char *) argv->buffer)[0] <= '9') {
1159 uint64_t value;
[059a8e4]1160 rc = str_uint64_t((char *) argv->buffer, NULL, 0, true, &value);
[4ce914d4]1161 if (rc == EOK)
1162 addr = (uintptr_t) value;
1163 } else
[e16e0d59]1164 rc = symtab_addr_lookup((char *) argv->buffer, &addr);
[4ce914d4]1165
[e16e0d59]1166 if (rc == ENOENT)
[0b0f4bb]1167 printf("Symbol %s not found.\n", (char *) argv->buffer);
[4ce914d4]1168 else if (rc == EINVAL)
1169 printf("Invalid address.\n");
[e16e0d59]1170 else if (rc == EOVERFLOW) {
[828aa05]1171 symtab_print_search((char *) argv->buffer);
[4ce914d4]1172 printf("Duplicate symbol (be more specific) or address overflow.\n");
[e16e0d59]1173 } else if (rc == EOK) {
[ba276f7]1174 if (pointer)
[e16e0d59]1175 addr = *(uintptr_t *) addr;
[0b0f4bb]1176 printf("Writing %#" PRIx32" -> %p\n", arg1, (void *) addr);
[e16e0d59]1177 *(uint32_t *) addr = arg1;
[4ce914d4]1178 } else
[e16e0d59]1179 printf("No symbol information available.\n");
[ba276f7]1180
1181 return 1;
1182}
[80bff342]1183
[4e147a6]1184/** Command for listings SLAB caches
1185 *
1186 * @param argv Ignores
1187 *
1188 * @return Always 1
1189 */
[df58e44]1190int cmd_slabs(cmd_arg_t *argv)
[095b1534]1191{
[4e147a6]1192 slab_print_list();
1193 return 1;
1194}
1195
[b3631bc]1196/** Command for dumping sysinfo
1197 *
1198 * @param argv Ignores
1199 *
1200 * @return Always 1
1201 */
[df58e44]1202int cmd_sysinfo(cmd_arg_t *argv)
[b3631bc]1203{
[9dae191e]1204 sysinfo_dump(NULL);
[b3631bc]1205 return 1;
1206}
1207
[df58e44]1208/** Command for listing thread information
[55ab0f1]1209 *
[48dcc69]1210 * @param argv Ignored
[55ab0f1]1211 *
1212 * @return Always 1
1213 */
[48dcc69]1214int cmd_threads(cmd_arg_t *argv)
[095b1534]1215{
[48dcc69]1216 if (str_cmp(flag_buf, "-a") == 0)
1217 thread_print_list(true);
1218 else if (str_cmp(flag_buf, "") == 0)
1219 thread_print_list(false);
1220 else
1221 printf("Unknown argument \"%s\".\n", flag_buf);
1222
[55ab0f1]1223 return 1;
1224}
1225
[df58e44]1226/** Command for listing task information
[37c57f2]1227 *
[48dcc69]1228 * @param argv Ignored
[37c57f2]1229 *
1230 * @return Always 1
1231 */
[c0f13d2]1232int cmd_tasks(cmd_arg_t *argv)
[095b1534]1233{
[48dcc69]1234 if (str_cmp(flag_buf, "-a") == 0)
[c0f13d2]1235 task_print_list(true);
[48dcc69]1236 else if (str_cmp(flag_buf, "") == 0)
[c0f13d2]1237 task_print_list(false);
1238 else
[48dcc69]1239 printf("Unknown argument \"%s\".\n", flag_buf);
[c0f13d2]1240
[37c57f2]1241 return 1;
1242}
1243
[5b7a107]1244#ifdef CONFIG_UDEBUG
1245
[df58e44]1246/** Command for printing thread stack trace
1247 *
1248 * @param argv Integer argument from cmdline expected
1249 *
1250 * return Always 1
1251 *
1252 */
1253int cmd_btrace(cmd_arg_t *argv)
1254{
1255 thread_stack_trace(argv[0].intval);
1256 return 1;
1257}
1258
[5b7a107]1259#endif /* CONFIG_UDEBUG */
1260
[df58e44]1261/** Command for printing scheduler information
[10e16a7]1262 *
1263 * @param argv Ignores
1264 *
1265 * @return Always 1
1266 */
[df58e44]1267int cmd_sched(cmd_arg_t *argv)
[095b1534]1268{
[10e16a7]1269 sched_print_list();
1270 return 1;
1271}
1272
[96cacc1]1273/** Command for listing memory zones
1274 *
1275 * @param argv Ignored
1276 *
1277 * return Always 1
1278 */
[df58e44]1279int cmd_zones(cmd_arg_t *argv)
[095b1534]1280{
[9dae191e]1281 zones_print_list();
[80bff342]1282 return 1;
1283}
[0132630]1284
[96cacc1]1285/** Command for memory zone details
1286 *
1287 * @param argv Integer argument from cmdline expected
1288 *
1289 * return Always 1
1290 */
[df58e44]1291int cmd_zone(cmd_arg_t *argv)
[095b1534]1292{
[dfd9186]1293 zone_print_one(argv[0].intval);
[80bff342]1294 return 1;
1295}
1296
[df58e44]1297/** Command for printing task IPC details
[c4e4507]1298 *
1299 * @param argv Integer argument from cmdline expected
1300 *
1301 * return Always 1
1302 */
[df58e44]1303int cmd_ipc(cmd_arg_t *argv)
[095b1534]1304{
[c4e4507]1305 ipc_print_task(argv[0].intval);
1306 return 1;
1307}
1308
[cb3d641a]1309/** Command for killing a task
[2a75302]1310 *
1311 * @param argv Integer argument from cmdline expected
1312 *
[cb3d641a]1313 * return 0 on failure, 1 on success.
[2a75302]1314 */
[df58e44]1315int cmd_kill(cmd_arg_t *argv)
[2a75302]1316{
1317 if (task_kill(argv[0].intval) != EOK)
1318 return 0;
1319
1320 return 1;
1321}
[c4e4507]1322
[0132630]1323/** Command for listing processors.
1324 *
1325 * @param argv Ignored.
1326 *
1327 * return Always 1.
1328 */
1329int cmd_cpus(cmd_arg_t *argv)
1330{
1331 cpu_list();
1332 return 1;
1333}
1334
1335/** Command for printing kernel version.
1336 *
1337 * @param argv Ignored.
1338 *
1339 * return Always 1.
1340 */
1341int cmd_version(cmd_arg_t *argv)
1342{
1343 version_print();
1344 return 1;
1345}
[41d33ac]1346
1347/** Command for returning console back to userspace.
1348 *
1349 * @param argv Ignored.
1350 *
1351 * return Always 1.
1352 */
1353int cmd_continue(cmd_arg_t *argv)
1354{
[dd054bc2]1355 printf("The kernel will now relinquish the console.\n");
[516ff92]1356 release_console();
[3ad953c]1357
[f9061b4]1358 event_notify_0(EVENT_KCONSOLE, false);
[821cc93]1359 indev_pop_character(stdin);
[3ad953c]1360
[41d33ac]1361 return 1;
1362}
[b45c443]1363
[50661ab]1364#ifdef CONFIG_TEST
[62b6d17]1365static bool run_test(const test_t *test)
[34db7fa]1366{
[c1f7f6ea]1367 printf("%s (%s)\n", test->name, test->desc);
[cce6acf]1368
1369 /* Update and read thread accounting
1370 for benchmarking */
[da1bafb]1371 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1372 uint64_t ucycles0, kcycles0;
1373 task_get_accounting(TASK, &ucycles0, &kcycles0);
[da1bafb]1374 irq_spinlock_unlock(&TASK->lock, true);
[cce6acf]1375
1376 /* Execute the test */
[cb01e1e]1377 test_quiet = false;
[a000878c]1378 const char *ret = test->entry();
[cce6acf]1379
1380 /* Update and read thread accounting */
[da1bafb]1381 uint64_t ucycles1, kcycles1;
1382 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1383 task_get_accounting(TASK, &ucycles1, &kcycles1);
[da1bafb]1384 irq_spinlock_unlock(&TASK->lock, true);
[cce6acf]1385
[1ba37fa]1386 uint64_t ucycles, kcycles;
1387 char usuffix, ksuffix;
[e535eeb]1388 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1389 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
[da1bafb]1390
[1ba37fa]1391 printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n",
[da1bafb]1392 ucycles, usuffix, kcycles, ksuffix);
[34db7fa]1393
1394 if (ret == NULL) {
1395 printf("Test passed\n");
[62b6d17]1396 return true;
[34db7fa]1397 }
[da1bafb]1398
[34db7fa]1399 printf("%s\n", ret);
[62b6d17]1400 return false;
[34db7fa]1401}
1402
[95155b0c]1403static bool run_bench(const test_t *test, const uint32_t cnt)
1404{
1405 uint32_t i;
1406 bool ret = true;
[1ba37fa]1407 uint64_t ucycles, kcycles;
1408 char usuffix, ksuffix;
[95155b0c]1409
1410 if (cnt < 1)
1411 return true;
1412
[828aa05]1413 uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
[95155b0c]1414 if (data == NULL) {
1415 printf("Error allocating memory for statistics\n");
1416 return false;
1417 }
1418
1419 for (i = 0; i < cnt; i++) {
[c859753]1420 printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
[95155b0c]1421
1422 /* Update and read thread accounting
1423 for benchmarking */
[da1bafb]1424 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1425 uint64_t ucycles0, kcycles0;
1426 task_get_accounting(TASK, &ucycles0, &kcycles0);
[da1bafb]1427 irq_spinlock_unlock(&TASK->lock, true);
[95155b0c]1428
1429 /* Execute the test */
[cb01e1e]1430 test_quiet = true;
[21881bd8]1431 const char *test_ret = test->entry();
[95155b0c]1432
1433 /* Update and read thread accounting */
[da1bafb]1434 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1435 uint64_t ucycles1, kcycles1;
1436 task_get_accounting(TASK, &ucycles1, &kcycles1);
[da1bafb]1437 irq_spinlock_unlock(&TASK->lock, true);
1438
[21881bd8]1439 if (test_ret != NULL) {
1440 printf("%s\n", test_ret);
[95155b0c]1441 ret = false;
1442 break;
1443 }
1444
[1ba37fa]1445 data[i] = ucycles1 - ucycles0 + kcycles1 - kcycles0;
[e535eeb]1446 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1447 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
[1ba37fa]1448 printf("OK (%" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles)\n",
[da1bafb]1449 ucycles, usuffix, kcycles, ksuffix);
[95155b0c]1450 }
1451
1452 if (ret) {
1453 printf("\n");
1454
1455 uint64_t sum = 0;
1456
1457 for (i = 0; i < cnt; i++) {
1458 sum += data[i];
1459 }
1460
[e535eeb]1461 order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix);
[1ba37fa]1462 printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix);
[95155b0c]1463 }
1464
1465 free(data);
1466
1467 return ret;
1468}
1469
[851f33a]1470static void list_tests(void)
1471{
1472 size_t len = 0;
1473 test_t *test;
1474
1475 for (test = tests; test->name != NULL; test++) {
1476 if (str_length(test->name) > len)
1477 len = str_length(test->name);
1478 }
1479
[0b0f4bb]1480 unsigned int _len = (unsigned int) len;
1481 if ((_len != len) || (((int) _len) < 0)) {
1482 printf("Command length overflow\n");
1483 return;
1484 }
1485
[851f33a]1486 for (test = tests; test->name != NULL; test++)
[0b0f4bb]1487 printf("%-*s %s%s\n", _len, test->name, test->desc,
1488 (test->safe ? "" : " (unsafe)"));
[851f33a]1489
[0b0f4bb]1490 printf("%-*s Run all safe tests\n", _len, "*");
[851f33a]1491}
1492
1493/** Command for listing and running kernel tests
[319e60e]1494 *
1495 * @param argv Argument vector.
1496 *
1497 * return Always 1.
[851f33a]1498 *
[319e60e]1499 */
1500int cmd_test(cmd_arg_t *argv)
1501{
1502 test_t *test;
1503
[20cc877]1504 if (str_cmp((char *) argv->buffer, "*") == 0) {
[50661ab]1505 for (test = tests; test->name != NULL; test++) {
1506 if (test->safe) {
[34db7fa]1507 printf("\n");
1508 if (!run_test(test))
1509 break;
[50661ab]1510 }
1511 }
[851f33a]1512 } else if (str_cmp((char *) argv->buffer, "") != 0) {
[50661ab]1513 bool fnd = false;
1514
1515 for (test = tests; test->name != NULL; test++) {
[20cc877]1516 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
[50661ab]1517 fnd = true;
[34db7fa]1518 run_test(test);
[50661ab]1519 break;
1520 }
[319e60e]1521 }
[50661ab]1522
1523 if (!fnd)
[34db7fa]1524 printf("Unknown test\n");
[851f33a]1525 } else
1526 list_tests();
[319e60e]1527
1528 return 1;
1529}
[95155b0c]1530
1531/** Command for returning kernel tests as benchmarks
1532 *
1533 * @param argv Argument vector.
1534 *
1535 * return Always 1.
1536 */
1537int cmd_bench(cmd_arg_t *argv)
1538{
1539 test_t *test;
1540 uint32_t cnt = argv[1].intval;
1541
[3f2177e]1542 if (str_cmp((char *) argv->buffer, "*") == 0) {
1543 for (test = tests; test->name != NULL; test++) {
1544 if (test->safe) {
1545 if (!run_bench(test, cnt))
1546 break;
1547 }
[95155b0c]1548 }
[3f2177e]1549 } else {
1550 bool fnd = false;
[95155b0c]1551
[3f2177e]1552 for (test = tests; test->name != NULL; test++) {
1553 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
1554 fnd = true;
1555
1556 if (test->safe)
1557 run_bench(test, cnt);
1558 else
1559 printf("Unsafe test\n");
1560
1561 break;
1562 }
1563 }
1564
1565 if (!fnd)
1566 printf("Unknown test\n");
1567 }
[cb01e1e]1568
[95155b0c]1569 return 1;
1570}
1571
[50661ab]1572#endif
[319e60e]1573
[06e1e95]1574/** @}
[b45c443]1575 */
Note: See TracBrowser for help on using the repository browser.