source: mainline/kernel/generic/src/console/cmd.c@ 973be387

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 973be387 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

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