source: mainline/kernel/generic/src/console/cmd.c@ 69146b93

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 69146b93 was 69146b93, checked in by Adam Hraska <adam.hraska+hos@…>, 13 years ago

Merged mainline,1723.

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