source: mainline/kernel/generic/src/console/cmd.c@ 52e020b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 52e020b was e8a1530, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

kernel console: Impelment pio_read/write functions.

  • Property mode set to 100644
File size: 33.8 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;
[55b77d9]658 list_foreach(cmd_list, cur) {
[442d0ae]659 cmd_info_t *hlp;
660 hlp = list_get_instance(cur, cmd_info_t, link);
[c1f7f6ea]661
[442d0ae]662 spinlock_lock(&hlp->lock);
[20cc877]663 if (str_length(hlp->name) > len)
664 len = str_length(hlp->name);
[c1f7f6ea]665 spinlock_unlock(&hlp->lock);
666 }
667
[0b0f4bb]668 unsigned int _len = (unsigned int) len;
669 if ((_len != len) || (((int) _len) < 0)) {
670 printf("Command length overflow\n");
671 return 1;
672 }
673
[55b77d9]674 list_foreach(cmd_list, cur) {
[c1f7f6ea]675 cmd_info_t *hlp;
676 hlp = list_get_instance(cur, cmd_info_t, link);
[442d0ae]677
[c1f7f6ea]678 spinlock_lock(&hlp->lock);
[0b0f4bb]679 printf("%-*s %s\n", _len, hlp->name, hlp->description);
[442d0ae]680 spinlock_unlock(&hlp->lock);
681 }
682
[ae318d3]683 spinlock_unlock(&cmd_lock);
[c1f7f6ea]684
[442d0ae]685 return 1;
686}
687
[e8a1530]688/** Read 1 byte from phys memory or io port.
689 *
690 * @param argv Argument vector.
691 *
692 * @return 0 on failure, 1 on success.
693 */
694static int cmd_pio_read_8(cmd_arg_t *argv)
695{
696 uint8_t *ptr = NULL;
697#ifdef IO_SPACE_BOUNDARY
698 if (argv->intval < IO_SPACE_BOUNDARY)
699 ptr = argv[0].intval;
700 else
701#endif
702 ptr = (uint8_t*)km_map(argv[0].intval, sizeof(uint8_t), PAGE_NOT_CACHEABLE);
703 const uint8_t val = pio_read_8(ptr);
704 printf("read %x: %"PRIx8"\n", argv[0].intval, val);
705#ifdef IO_SPACE_BOUNDARY
706 if (argv->intval < IO_SPACE_BOUNDARY)
707 return 1;
708#endif
709 km_unmap((uintptr_t)ptr, sizeof(uint8_t));
710 return 1;
711}
712
713/** Read 2 bytes from phys memory or io port.
714 *
715 * @param argv Argument vector.
716 *
717 * @return 0 on failure, 1 on success.
718 */
719static int cmd_pio_read_16(cmd_arg_t *argv)
720{
721 uint16_t *ptr = NULL;
722#ifdef IO_SPACE_BOUNDARY
723 if (argv->intval < IO_SPACE_BOUNDARY)
724 ptr = argv[0].intval;
725 else
726#endif
727 ptr = (uint16_t*)km_map(argv[0].intval, sizeof(uint16_t), PAGE_NOT_CACHEABLE);
728 const uint16_t val = pio_read_16(ptr);
729 printf("read %x: %"PRIx16"\n", argv[0].intval, val);
730#ifdef IO_SPACE_BOUNDARY
731 if (argv->intval < IO_SPACE_BOUNDARY)
732 return 1;
733#endif
734 km_unmap((uintptr_t)ptr, sizeof(uint16_t));
735 return 1;
736}
737
738/** Read 4 bytes from phys memory or io port.
739 *
740 * @param argv Argument vector.
741 *
742 * @return 0 on failure, 1 on success.
743 */
744static int cmd_pio_read_32(cmd_arg_t *argv)
745{
746 uint32_t *ptr = NULL;
747#ifdef IO_SPACE_BOUNDARY
748 if (argv->intval < IO_SPACE_BOUNDARY)
749 ptr = argv[0].intval;
750 else
751#endif
752 ptr = (uint32_t*)km_map(argv[0].intval, sizeof(uint32_t), PAGE_NOT_CACHEABLE);
753 const uint32_t val = pio_read_32(ptr);
754 printf("read %#x: %#"PRIx32"\n", argv[0].intval, val);
755#ifdef IO_SPACE_BOUNDARY
756 if (argv->intval < IO_SPACE_BOUNDARY)
757 return 1;
758#endif
759 km_unmap((uintptr_t)ptr, sizeof(uint32_t));
760 return 1;
761}
762
763/** Write 1 byte to phys memory or io port.
764 *
765 * @param argv Argument vector.
766 *
767 * @return 0 on failure, 1 on success.
768 */
769static int cmd_pio_write_8(cmd_arg_t *argv)
770{
771 uint8_t *ptr = NULL;
772#ifdef IO_SPACE_BOUNDARY
773 if (argv->intval < IO_SPACE_BOUNDARY)
774 ptr = argv[0].intval;
775 else
776#endif
777 ptr = (uint8_t*)km_map(argv[0].intval, sizeof(uint8_t), PAGE_NOT_CACHEABLE);
778 printf("write %x: %"PRIx8"\n", argv[0].intval, (uint8_t)argv[1].intval);
779 pio_write_8(ptr, (uint8_t)argv[1].intval);
780#ifdef IO_SPACE_BOUNDARY
781 if (argv->intval < IO_SPACE_BOUNDARY)
782 return 1;
783#endif
784 km_unmap((uintptr_t)ptr, sizeof(uint8_t));
785 return 1;
786}
787
788/** Write 2 bytes to phys memory or io port.
789 *
790 * @param argv Argument vector.
791 *
792 * @return 0 on failure, 1 on success.
793 */
794static int cmd_pio_write_16(cmd_arg_t *argv)
795{
796 uint16_t *ptr = NULL;
797#ifdef IO_SPACE_BOUNDARY
798 if (argv->intval < IO_SPACE_BOUNDARY)
799 ptr = argv[0].intval;
800 else
801#endif
802 ptr = (uint16_t*)km_map(argv[0].intval, sizeof(uint16_t), PAGE_NOT_CACHEABLE);
803 printf("write %x: %"PRIx16"\n", argv[0].intval, (uint16_t)argv[1].intval);
804 pio_write_16(ptr, (uint16_t)argv[1].intval);
805#ifdef IO_SPACE_BOUNDARY
806 if (argv->intval < IO_SPACE_BOUNDARY)
807 return 1;
808#endif
809 km_unmap((uintptr_t)ptr, sizeof(uint16_t));
810 return 1;
811}
812
813/** Write 4 bytes to phys memory or io port.
814 *
815 * @param argv Argument vector.
816 *
817 * @return 0 on failure, 1 on success.
818 */
819static int cmd_pio_write_32(cmd_arg_t *argv)
820{
821 uint32_t *ptr = NULL;
822#ifdef IO_SPACE_BOUNDARY
823 if (argv->intval < IO_SPACE_BOUNDARY)
824 ptr = argv[0].intval;
825 else
826#endif
827 ptr = (uint32_t*)km_map(argv[0].intval, sizeof(uint32_t), PAGE_NOT_CACHEABLE);
828 printf("write %x: %"PRIx32"\n", argv[0].intval, (uint32_t)argv[1].intval);
829 pio_write_32(ptr, (uint32_t)argv[1].intval);
830#ifdef IO_SPACE_BOUNDARY
831 if (argv->intval < IO_SPACE_BOUNDARY)
832 return 1;
833#endif
834 km_unmap((uintptr_t)ptr, sizeof(uint32_t));
835 return 1;
836}
837
[f74bbaf]838/** Reboot the system.
839 *
840 * @param argv Argument vector.
841 *
842 * @return 0 on failure, 1 on success.
843 */
844int cmd_reboot(cmd_arg_t *argv)
845{
846 reboot();
847
848 /* Not reached */
849 return 1;
850}
851
[4b662f8c]852/** Print system uptime information.
853 *
854 * @param argv Argument vector.
855 *
856 * @return 0 on failure, 1 on success.
857 */
858int cmd_uptime(cmd_arg_t *argv)
859{
860 ASSERT(uptime);
861
862 /* This doesn't have to be very accurate */
[96b02eb9]863 sysarg_t sec = uptime->seconds1;
[4b662f8c]864
[c859753]865 printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n",
[4b662f8c]866 sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60);
867
868 return 1;
869}
870
[442d0ae]871/** Describe specified command.
872 *
873 * @param argv Argument vector.
874 *
875 * @return 0 on failure, 1 on success.
876 */
877int cmd_desc(cmd_arg_t *argv)
878{
879 spinlock_lock(&cmd_lock);
880
[55b77d9]881 list_foreach(cmd_list, cur) {
[442d0ae]882 cmd_info_t *hlp;
883
884 hlp = list_get_instance(cur, cmd_info_t, link);
885 spinlock_lock(&hlp->lock);
[20cc877]886
887 if (str_lcmp(hlp->name, (const char *) argv->buffer, str_length(hlp->name)) == 0) {
[442d0ae]888 printf("%s - %s\n", hlp->name, hlp->description);
889 if (hlp->help)
890 hlp->help();
891 spinlock_unlock(&hlp->lock);
892 break;
893 }
[20cc877]894
[442d0ae]895 spinlock_unlock(&hlp->lock);
896 }
897
898 spinlock_unlock(&cmd_lock);
[20cc877]899
[442d0ae]900 return 1;
901}
902
903/** Search symbol table */
904int cmd_symaddr(cmd_arg_t *argv)
905{
[828aa05]906 symtab_print_search((char *) argv->buffer);
[442d0ae]907
908 return 1;
909}
910
911/** Call function with zero parameters */
912int cmd_call0(cmd_arg_t *argv)
913{
[7f1c620]914 uintptr_t symaddr;
[e16e0d59]915 char *symbol;
[96b02eb9]916 sysarg_t (*fnc)(void);
[0f81ceb7]917 fncptr_t fptr;
[e16e0d59]918 int rc;
[e2b762ec]919
[e16e0d59]920 symbol = (char *) argv->buffer;
921 rc = symtab_addr_lookup(symbol, &symaddr);
922
923 if (rc == ENOENT)
924 printf("Symbol %s not found.\n", symbol);
925 else if (rc == EOVERFLOW) {
926 symtab_print_search(symbol);
[442d0ae]927 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]928 } else if (rc == EOK) {
[c992538a]929 ipl_t ipl;
930
931 ipl = interrupts_disable();
[96b02eb9]932 fnc = (sysarg_t (*)(void)) arch_construct_function(&fptr,
[e16e0d59]933 (void *) symaddr, (void *) cmd_call0);
[0b0f4bb]934 printf("Calling %s() (%p)\n", symbol, (void *) symaddr);
[0f81ceb7]935 printf("Result: %#" PRIxn "\n", fnc());
[c992538a]936 interrupts_restore(ipl);
[e16e0d59]937 } else {
938 printf("No symbol information available.\n");
[442d0ae]939 }
940 return 1;
941}
942
[e5dbbe5]943/** Call function with zero parameters on each CPU */
944int cmd_mcall0(cmd_arg_t *argv)
945{
946 /*
947 * For each CPU, create a thread which will
948 * call the function.
949 */
950
[0b0f4bb]951 unsigned int i;
[e5dbbe5]952 for (i = 0; i < config.cpu_count; i++) {
[b8f11baa]953 if (!cpus[i].active)
954 continue;
955
[da1bafb]956 thread_t *thread;
957 if ((thread = thread_create((void (*)(void *)) cmd_call0,
[6eef3c4]958 (void *) argv, TASK, THREAD_FLAG_NONE, "call0"))) {
[0b0f4bb]959 printf("cpu%u: ", i);
[6eef3c4]960 thread_wire(thread, &cpus[i]);
[da1bafb]961 thread_ready(thread);
962 thread_join(thread);
963 thread_detach(thread);
[e5dbbe5]964 } else
[0b0f4bb]965 printf("Unable to create thread for cpu%u\n", i);
[e5dbbe5]966 }
967
968 return 1;
969}
970
[442d0ae]971/** Call function with one parameter */
972int cmd_call1(cmd_arg_t *argv)
973{
[7f1c620]974 uintptr_t symaddr;
[442d0ae]975 char *symbol;
[96b02eb9]976 sysarg_t (*fnc)(sysarg_t, ...);
977 sysarg_t arg1 = argv[1].intval;
[0f81ceb7]978 fncptr_t fptr;
[e16e0d59]979 int rc;
[e2b762ec]980
[e16e0d59]981 symbol = (char *) argv->buffer;
982 rc = symtab_addr_lookup(symbol, &symaddr);
983
984 if (rc == ENOENT) {
985 printf("Symbol %s not found.\n", symbol);
986 } else if (rc == EOVERFLOW) {
987 symtab_print_search(symbol);
[442d0ae]988 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]989 } else if (rc == EOK) {
[c992538a]990 ipl_t ipl;
991
992 ipl = interrupts_disable();
[96b02eb9]993 fnc = (sysarg_t (*)(sysarg_t, ...))
[0b0f4bb]994 arch_construct_function(&fptr, (void *) symaddr,
995 (void *) cmd_call1);
996 printf("Calling f(%#" PRIxn "): %p: %s\n", arg1,
997 (void *) symaddr, symbol);
[0f81ceb7]998 printf("Result: %#" PRIxn "\n", fnc(arg1));
[c992538a]999 interrupts_restore(ipl);
[e16e0d59]1000 } else {
1001 printf("No symbol information available.\n");
[442d0ae]1002 }
[e16e0d59]1003
[442d0ae]1004 return 1;
1005}
1006
1007/** Call function with two parameters */
1008int cmd_call2(cmd_arg_t *argv)
1009{
[7f1c620]1010 uintptr_t symaddr;
[442d0ae]1011 char *symbol;
[96b02eb9]1012 sysarg_t (*fnc)(sysarg_t, sysarg_t, ...);
1013 sysarg_t arg1 = argv[1].intval;
1014 sysarg_t arg2 = argv[2].intval;
[0f81ceb7]1015 fncptr_t fptr;
[e16e0d59]1016 int rc;
1017
1018 symbol = (char *) argv->buffer;
1019 rc = symtab_addr_lookup(symbol, &symaddr);
1020
1021 if (rc == ENOENT) {
1022 printf("Symbol %s not found.\n", symbol);
1023 } else if (rc == EOVERFLOW) {
1024 symtab_print_search(symbol);
[442d0ae]1025 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]1026 } else if (rc == EOK) {
[c992538a]1027 ipl_t ipl;
1028
1029 ipl = interrupts_disable();
[96b02eb9]1030 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, ...))
[0b0f4bb]1031 arch_construct_function(&fptr, (void *) symaddr,
1032 (void *) cmd_call2);
[c859753]1033 printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n",
[0b0f4bb]1034 arg1, arg2, (void *) symaddr, symbol);
[0f81ceb7]1035 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2));
[c992538a]1036 interrupts_restore(ipl);
[e16e0d59]1037 } else {
1038 printf("No symbol information available.\n");
1039 }
[442d0ae]1040 return 1;
1041}
1042
1043/** Call function with three parameters */
1044int cmd_call3(cmd_arg_t *argv)
1045{
[7f1c620]1046 uintptr_t symaddr;
[442d0ae]1047 char *symbol;
[96b02eb9]1048 sysarg_t (*fnc)(sysarg_t, sysarg_t, sysarg_t, ...);
1049 sysarg_t arg1 = argv[1].intval;
1050 sysarg_t arg2 = argv[2].intval;
1051 sysarg_t arg3 = argv[3].intval;
[0f81ceb7]1052 fncptr_t fptr;
[e16e0d59]1053 int rc;
[0f81ceb7]1054
[e16e0d59]1055 symbol = (char *) argv->buffer;
1056 rc = symtab_addr_lookup(symbol, &symaddr);
1057
1058 if (rc == ENOENT) {
1059 printf("Symbol %s not found.\n", symbol);
1060 } else if (rc == EOVERFLOW) {
1061 symtab_print_search(symbol);
[442d0ae]1062 printf("Duplicate symbol, be more specific.\n");
[e16e0d59]1063 } else if (rc == EOK) {
[c992538a]1064 ipl_t ipl;
1065
1066 ipl = interrupts_disable();
[96b02eb9]1067 fnc = (sysarg_t (*)(sysarg_t, sysarg_t, sysarg_t, ...))
[0b0f4bb]1068 arch_construct_function(&fptr, (void *) symaddr,
1069 (void *) cmd_call3);
1070 printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n",
1071 arg1, arg2, arg3, (void *) symaddr, symbol);
[0f81ceb7]1072 printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3));
[c992538a]1073 interrupts_restore(ipl);
[e16e0d59]1074 } else {
1075 printf("No symbol information available.\n");
[442d0ae]1076 }
1077 return 1;
1078}
1079
1080/** Print detailed description of 'describe' command. */
1081void desc_help(void)
1082{
1083 printf("Syntax: describe command_name\n");
1084}
1085
1086/** Halt the kernel.
1087 *
1088 * @param argv Argument vector (ignored).
1089 *
1090 * @return 0 on failure, 1 on success (never returns).
1091 */
1092int cmd_halt(cmd_arg_t *argv)
1093{
1094 halt();
1095 return 1;
1096}
1097
1098/** Command for printing TLB contents.
1099 *
1100 * @param argv Not used.
1101 *
1102 * @return Always returns 1.
1103 */
[0132630]1104int cmd_tlb(cmd_arg_t *argv)
[442d0ae]1105{
1106 tlb_print();
1107 return 1;
1108}
[ba276f7]1109
[b07c332]1110/** Command for printing physical memory configuration.
1111 *
1112 * @param argv Not used.
1113 *
1114 * @return Always returns 1.
1115 */
1116int cmd_physmem(cmd_arg_t *argv)
1117{
1118 physmem_print();
1119 return 1;
1120}
1121
[ba276f7]1122/** Write 4 byte value to address */
1123int cmd_set4(cmd_arg_t *argv)
1124{
[e16e0d59]1125 uintptr_t addr;
[7f1c620]1126 uint32_t arg1 = argv[1].intval;
[ba276f7]1127 bool pointer = false;
[e16e0d59]1128 int rc;
[4ce914d4]1129
1130 if (((char *) argv->buffer)[0] == '*') {
[e16e0d59]1131 rc = symtab_addr_lookup((char *) argv->buffer + 1, &addr);
[ba276f7]1132 pointer = true;
[4ce914d4]1133 } else if (((char *) argv->buffer)[0] >= '0' &&
1134 ((char *) argv->buffer)[0] <= '9') {
1135 uint64_t value;
[059a8e4]1136 rc = str_uint64_t((char *) argv->buffer, NULL, 0, true, &value);
[4ce914d4]1137 if (rc == EOK)
1138 addr = (uintptr_t) value;
1139 } else
[e16e0d59]1140 rc = symtab_addr_lookup((char *) argv->buffer, &addr);
[4ce914d4]1141
[e16e0d59]1142 if (rc == ENOENT)
[0b0f4bb]1143 printf("Symbol %s not found.\n", (char *) argv->buffer);
[4ce914d4]1144 else if (rc == EINVAL)
1145 printf("Invalid address.\n");
[e16e0d59]1146 else if (rc == EOVERFLOW) {
[828aa05]1147 symtab_print_search((char *) argv->buffer);
[4ce914d4]1148 printf("Duplicate symbol (be more specific) or address overflow.\n");
[e16e0d59]1149 } else if (rc == EOK) {
[ba276f7]1150 if (pointer)
[e16e0d59]1151 addr = *(uintptr_t *) addr;
[0b0f4bb]1152 printf("Writing %#" PRIx32" -> %p\n", arg1, (void *) addr);
[e16e0d59]1153 *(uint32_t *) addr = arg1;
[4ce914d4]1154 } else
[e16e0d59]1155 printf("No symbol information available.\n");
[ba276f7]1156
1157 return 1;
1158}
[80bff342]1159
[4e147a6]1160/** Command for listings SLAB caches
1161 *
1162 * @param argv Ignores
1163 *
1164 * @return Always 1
1165 */
[df58e44]1166int cmd_slabs(cmd_arg_t *argv)
[095b1534]1167{
[4e147a6]1168 slab_print_list();
1169 return 1;
1170}
1171
[b3631bc]1172/** Command for dumping sysinfo
1173 *
1174 * @param argv Ignores
1175 *
1176 * @return Always 1
1177 */
[df58e44]1178int cmd_sysinfo(cmd_arg_t *argv)
[b3631bc]1179{
[9dae191e]1180 sysinfo_dump(NULL);
[b3631bc]1181 return 1;
1182}
1183
[df58e44]1184/** Command for listing thread information
[55ab0f1]1185 *
[48dcc69]1186 * @param argv Ignored
[55ab0f1]1187 *
1188 * @return Always 1
1189 */
[48dcc69]1190int cmd_threads(cmd_arg_t *argv)
[095b1534]1191{
[48dcc69]1192 if (str_cmp(flag_buf, "-a") == 0)
1193 thread_print_list(true);
1194 else if (str_cmp(flag_buf, "") == 0)
1195 thread_print_list(false);
1196 else
1197 printf("Unknown argument \"%s\".\n", flag_buf);
1198
[55ab0f1]1199 return 1;
1200}
1201
[df58e44]1202/** Command for listing task information
[37c57f2]1203 *
[48dcc69]1204 * @param argv Ignored
[37c57f2]1205 *
1206 * @return Always 1
1207 */
[c0f13d2]1208int cmd_tasks(cmd_arg_t *argv)
[095b1534]1209{
[48dcc69]1210 if (str_cmp(flag_buf, "-a") == 0)
[c0f13d2]1211 task_print_list(true);
[48dcc69]1212 else if (str_cmp(flag_buf, "") == 0)
[c0f13d2]1213 task_print_list(false);
1214 else
[48dcc69]1215 printf("Unknown argument \"%s\".\n", flag_buf);
[c0f13d2]1216
[37c57f2]1217 return 1;
1218}
1219
[5b7a107]1220#ifdef CONFIG_UDEBUG
1221
[df58e44]1222/** Command for printing thread stack trace
1223 *
1224 * @param argv Integer argument from cmdline expected
1225 *
1226 * return Always 1
1227 *
1228 */
1229int cmd_btrace(cmd_arg_t *argv)
1230{
1231 thread_stack_trace(argv[0].intval);
1232 return 1;
1233}
1234
[5b7a107]1235#endif /* CONFIG_UDEBUG */
1236
[df58e44]1237/** Command for printing scheduler information
[10e16a7]1238 *
1239 * @param argv Ignores
1240 *
1241 * @return Always 1
1242 */
[df58e44]1243int cmd_sched(cmd_arg_t *argv)
[095b1534]1244{
[10e16a7]1245 sched_print_list();
1246 return 1;
1247}
1248
[96cacc1]1249/** Command for listing memory zones
1250 *
1251 * @param argv Ignored
1252 *
1253 * return Always 1
1254 */
[df58e44]1255int cmd_zones(cmd_arg_t *argv)
[095b1534]1256{
[9dae191e]1257 zones_print_list();
[80bff342]1258 return 1;
1259}
[0132630]1260
[96cacc1]1261/** Command for memory zone details
1262 *
1263 * @param argv Integer argument from cmdline expected
1264 *
1265 * return Always 1
1266 */
[df58e44]1267int cmd_zone(cmd_arg_t *argv)
[095b1534]1268{
[dfd9186]1269 zone_print_one(argv[0].intval);
[80bff342]1270 return 1;
1271}
1272
[df58e44]1273/** Command for printing task IPC details
[c4e4507]1274 *
1275 * @param argv Integer argument from cmdline expected
1276 *
1277 * return Always 1
1278 */
[df58e44]1279int cmd_ipc(cmd_arg_t *argv)
[095b1534]1280{
[c4e4507]1281 ipc_print_task(argv[0].intval);
1282 return 1;
1283}
1284
[cb3d641a]1285/** Command for killing a task
[2a75302]1286 *
1287 * @param argv Integer argument from cmdline expected
1288 *
[cb3d641a]1289 * return 0 on failure, 1 on success.
[2a75302]1290 */
[df58e44]1291int cmd_kill(cmd_arg_t *argv)
[2a75302]1292{
1293 if (task_kill(argv[0].intval) != EOK)
1294 return 0;
1295
1296 return 1;
1297}
[c4e4507]1298
[0132630]1299/** Command for listing processors.
1300 *
1301 * @param argv Ignored.
1302 *
1303 * return Always 1.
1304 */
1305int cmd_cpus(cmd_arg_t *argv)
1306{
1307 cpu_list();
1308 return 1;
1309}
1310
1311/** Command for printing kernel version.
1312 *
1313 * @param argv Ignored.
1314 *
1315 * return Always 1.
1316 */
1317int cmd_version(cmd_arg_t *argv)
1318{
1319 version_print();
1320 return 1;
1321}
[41d33ac]1322
1323/** Command for returning console back to userspace.
1324 *
1325 * @param argv Ignored.
1326 *
1327 * return Always 1.
1328 */
1329int cmd_continue(cmd_arg_t *argv)
1330{
[dd054bc2]1331 printf("The kernel will now relinquish the console.\n");
[516ff92]1332 release_console();
[3ad953c]1333
[f9061b4]1334 event_notify_0(EVENT_KCONSOLE, false);
[821cc93]1335 indev_pop_character(stdin);
[3ad953c]1336
[41d33ac]1337 return 1;
1338}
[b45c443]1339
[50661ab]1340#ifdef CONFIG_TEST
[62b6d17]1341static bool run_test(const test_t *test)
[34db7fa]1342{
[c1f7f6ea]1343 printf("%s (%s)\n", test->name, test->desc);
[cce6acf]1344
1345 /* Update and read thread accounting
1346 for benchmarking */
[da1bafb]1347 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1348 uint64_t ucycles0, kcycles0;
1349 task_get_accounting(TASK, &ucycles0, &kcycles0);
[da1bafb]1350 irq_spinlock_unlock(&TASK->lock, true);
[cce6acf]1351
1352 /* Execute the test */
[cb01e1e]1353 test_quiet = false;
[a000878c]1354 const char *ret = test->entry();
[cce6acf]1355
1356 /* Update and read thread accounting */
[da1bafb]1357 uint64_t ucycles1, kcycles1;
1358 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1359 task_get_accounting(TASK, &ucycles1, &kcycles1);
[da1bafb]1360 irq_spinlock_unlock(&TASK->lock, true);
[cce6acf]1361
[1ba37fa]1362 uint64_t ucycles, kcycles;
1363 char usuffix, ksuffix;
[e535eeb]1364 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1365 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
[da1bafb]1366
[1ba37fa]1367 printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n",
[da1bafb]1368 ucycles, usuffix, kcycles, ksuffix);
[34db7fa]1369
1370 if (ret == NULL) {
1371 printf("Test passed\n");
[62b6d17]1372 return true;
[34db7fa]1373 }
[da1bafb]1374
[34db7fa]1375 printf("%s\n", ret);
[62b6d17]1376 return false;
[34db7fa]1377}
1378
[95155b0c]1379static bool run_bench(const test_t *test, const uint32_t cnt)
1380{
1381 uint32_t i;
1382 bool ret = true;
[1ba37fa]1383 uint64_t ucycles, kcycles;
1384 char usuffix, ksuffix;
[95155b0c]1385
1386 if (cnt < 1)
1387 return true;
1388
[828aa05]1389 uint64_t *data = (uint64_t *) malloc(sizeof(uint64_t) * cnt, 0);
[95155b0c]1390 if (data == NULL) {
1391 printf("Error allocating memory for statistics\n");
1392 return false;
1393 }
1394
1395 for (i = 0; i < cnt; i++) {
[c859753]1396 printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
[95155b0c]1397
1398 /* Update and read thread accounting
1399 for benchmarking */
[da1bafb]1400 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1401 uint64_t ucycles0, kcycles0;
1402 task_get_accounting(TASK, &ucycles0, &kcycles0);
[da1bafb]1403 irq_spinlock_unlock(&TASK->lock, true);
[95155b0c]1404
1405 /* Execute the test */
[cb01e1e]1406 test_quiet = true;
[21881bd8]1407 const char *test_ret = test->entry();
[95155b0c]1408
1409 /* Update and read thread accounting */
[da1bafb]1410 irq_spinlock_lock(&TASK->lock, true);
[1ba37fa]1411 uint64_t ucycles1, kcycles1;
1412 task_get_accounting(TASK, &ucycles1, &kcycles1);
[da1bafb]1413 irq_spinlock_unlock(&TASK->lock, true);
1414
[21881bd8]1415 if (test_ret != NULL) {
1416 printf("%s\n", test_ret);
[95155b0c]1417 ret = false;
1418 break;
1419 }
1420
[1ba37fa]1421 data[i] = ucycles1 - ucycles0 + kcycles1 - kcycles0;
[e535eeb]1422 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
1423 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
[1ba37fa]1424 printf("OK (%" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles)\n",
[da1bafb]1425 ucycles, usuffix, kcycles, ksuffix);
[95155b0c]1426 }
1427
1428 if (ret) {
1429 printf("\n");
1430
1431 uint64_t sum = 0;
1432
1433 for (i = 0; i < cnt; i++) {
1434 sum += data[i];
1435 }
1436
[e535eeb]1437 order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix);
[1ba37fa]1438 printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix);
[95155b0c]1439 }
1440
1441 free(data);
1442
1443 return ret;
1444}
1445
[851f33a]1446static void list_tests(void)
1447{
1448 size_t len = 0;
1449 test_t *test;
1450
1451 for (test = tests; test->name != NULL; test++) {
1452 if (str_length(test->name) > len)
1453 len = str_length(test->name);
1454 }
1455
[0b0f4bb]1456 unsigned int _len = (unsigned int) len;
1457 if ((_len != len) || (((int) _len) < 0)) {
1458 printf("Command length overflow\n");
1459 return;
1460 }
1461
[851f33a]1462 for (test = tests; test->name != NULL; test++)
[0b0f4bb]1463 printf("%-*s %s%s\n", _len, test->name, test->desc,
1464 (test->safe ? "" : " (unsafe)"));
[851f33a]1465
[0b0f4bb]1466 printf("%-*s Run all safe tests\n", _len, "*");
[851f33a]1467}
1468
1469/** Command for listing and running kernel tests
[319e60e]1470 *
1471 * @param argv Argument vector.
1472 *
1473 * return Always 1.
[851f33a]1474 *
[319e60e]1475 */
1476int cmd_test(cmd_arg_t *argv)
1477{
1478 test_t *test;
1479
[20cc877]1480 if (str_cmp((char *) argv->buffer, "*") == 0) {
[50661ab]1481 for (test = tests; test->name != NULL; test++) {
1482 if (test->safe) {
[34db7fa]1483 printf("\n");
1484 if (!run_test(test))
1485 break;
[50661ab]1486 }
1487 }
[851f33a]1488 } else if (str_cmp((char *) argv->buffer, "") != 0) {
[50661ab]1489 bool fnd = false;
1490
1491 for (test = tests; test->name != NULL; test++) {
[20cc877]1492 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
[50661ab]1493 fnd = true;
[34db7fa]1494 run_test(test);
[50661ab]1495 break;
1496 }
[319e60e]1497 }
[50661ab]1498
1499 if (!fnd)
[34db7fa]1500 printf("Unknown test\n");
[851f33a]1501 } else
1502 list_tests();
[319e60e]1503
1504 return 1;
1505}
[95155b0c]1506
1507/** Command for returning kernel tests as benchmarks
1508 *
1509 * @param argv Argument vector.
1510 *
1511 * return Always 1.
1512 */
1513int cmd_bench(cmd_arg_t *argv)
1514{
1515 test_t *test;
1516 uint32_t cnt = argv[1].intval;
1517
[3f2177e]1518 if (str_cmp((char *) argv->buffer, "*") == 0) {
1519 for (test = tests; test->name != NULL; test++) {
1520 if (test->safe) {
1521 if (!run_bench(test, cnt))
1522 break;
1523 }
[95155b0c]1524 }
[3f2177e]1525 } else {
1526 bool fnd = false;
[95155b0c]1527
[3f2177e]1528 for (test = tests; test->name != NULL; test++) {
1529 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
1530 fnd = true;
1531
1532 if (test->safe)
1533 run_bench(test, cnt);
1534 else
1535 printf("Unsafe test\n");
1536
1537 break;
1538 }
1539 }
1540
1541 if (!fnd)
1542 printf("Unknown test\n");
1543 }
[cb01e1e]1544
[95155b0c]1545 return 1;
1546}
1547
[50661ab]1548#endif
[319e60e]1549
[06e1e95]1550/** @}
[b45c443]1551 */
Note: See TracBrowser for help on using the repository browser.