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

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

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 35.1 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>
[442d0ae]54#include <func.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 },
279 {
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 },
336 {
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 },
359 {
360 .type = ARG_TYPE_VAR,
361 .buffer = carg1_buf,
362 .len = sizeof(carg1_buf)
363 },
364 {
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 },
387 {
388 .type = ARG_TYPE_VAR,
389 .buffer = carg1_buf,
390 .len = sizeof(carg1_buf)
391 },
392 {
393 .type = ARG_TYPE_VAR,
394 .buffer = carg2_buf,
395 .len = sizeof(carg2_buf)
396 },
397 {
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);
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 }
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 }
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 }
708
[ae318d3]709 spinlock_unlock(&cmd_lock);
[c1f7f6ea]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;
[2f33fbc]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);
[2f33fbc]731
[e8a1530]732 const uint8_t val = pio_read_8(ptr);
[2f33fbc]733 printf("read %" PRIxn ": %" PRIx8 "\n", argv[0].intval, val);
734
[e8a1530]735#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]736 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]737 return 1;
738#endif
[2f33fbc]739
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;
[2f33fbc]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);
[2f33fbc]761
[e8a1530]762 const uint16_t val = pio_read_16(ptr);
[2f33fbc]763 printf("read %" PRIxn ": %" PRIx16 "\n", argv[0].intval, val);
764
[e8a1530]765#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]766 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]767 return 1;
768#endif
[2f33fbc]769
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;
[2f33fbc]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);
[2f33fbc]791
[e8a1530]792 const uint32_t val = pio_read_32(ptr);
[2f33fbc]793 printf("read %" PRIxn ": %" PRIx32 "\n", argv[0].intval, val);
794
[e8a1530]795#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]796 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]797 return 1;
798#endif
[2f33fbc]799
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;
[2f33fbc]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);
[2f33fbc]821
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);
825
[e8a1530]826#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]827 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]828 return 1;
829#endif
[2f33fbc]830
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;
[2f33fbc]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);
[2f33fbc]852
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);
856
[e8a1530]857#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]858 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]859 return 1;
860#endif
[2f33fbc]861
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;
[2f33fbc]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);
[2f33fbc]883
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);
887
[e8a1530]888#ifdef IO_SPACE_BOUNDARY
[3f6c16fe]889 if ((void *) argv->intval < IO_SPACE_BOUNDARY)
[e8a1530]890 return 1;
891#endif
[2f33fbc]892
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();
906
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);
[4b662f8c]920
921 /* This doesn't have to be very accurate */
[96b02eb9]922 sysarg_t sec = uptime->seconds1;
[4b662f8c]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);
926
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);
939
[feeac0d]940 list_foreach(cmd_list, link, cmd_info_t, hlp) {
[442d0ae]941 spinlock_lock(&hlp->lock);
[20cc877]942
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 }
[20cc877]950
[442d0ae]951 spinlock_unlock(&hlp->lock);
952 }
953
954 spinlock_unlock(&cmd_lock);
[20cc877]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);
[442d0ae]963
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 */
1006
[0b0f4bb]1007 unsigned int i;
[e5dbbe5]1008 for (i = 0; i < config.cpu_count; i++) {
[b8f11baa]1009 if (!cpus[i].active)
1010 continue;
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 }
1023
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);
[c859753]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;
[0f81ceb7]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;
[4ce914d4]1185
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);
[4ce914d4]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");
[ba276f7]1212
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);
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);
[c0f13d2]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);
[3ad953c]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);
[cce6acf]1422
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);
[cce6acf]1429
1430 /* Execute the test */
[cb01e1e]1431 test_quiet = false;
[a000878c]1432 const char *ret = test->entry();
[cce6acf]1433
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);
[cce6acf]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);
[da1bafb]1444
[1ba37fa]1445 printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n",
[da1bafb]1446 ucycles, usuffix, kcycles, ksuffix);
[34db7fa]1447
1448 if (ret == NULL) {
1449 printf("Test passed\n");
[62b6d17]1450 return true;
[34db7fa]1451 }
[da1bafb]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;
[95155b0c]1463
1464 if (cnt < 1)
1465 return true;
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 }
1472
1473 for (i = 0; i < cnt; i++) {
[c859753]1474 printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
[95155b0c]1475
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);
[95155b0c]1482
1483 /* Execute the test */
[cb01e1e]1484 test_quiet = true;
[21881bd8]1485 const char *test_ret = test->entry();
[95155b0c]1486
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);
1492
[21881bd8]1493 if (test_ret != NULL) {
1494 printf("%s\n", test_ret);
[95155b0c]1495 ret = false;
1496 break;
1497 }
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 }
1505
1506 if (ret) {
1507 printf("\n");
1508
1509 uint64_t sum = 0;
1510
1511 for (i = 0; i < cnt; i++) {
1512 sum += data[i];
1513 }
1514
[e535eeb]1515 order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix);
[1ba37fa]1516 printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix);
[95155b0c]1517 }
1518
1519 free(data);
1520
1521 return ret;
1522}
1523
[851f33a]1524static void list_tests(void)
1525{
1526 size_t len = 0;
1527 test_t *test;
1528
1529 for (test = tests; test->name != NULL; test++) {
1530 if (str_length(test->name) > len)
1531 len = str_length(test->name);
1532 }
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 }
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)"));
[851f33a]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;
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;
1568
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 }
[50661ab]1576
1577 if (!fnd)
[34db7fa]1578 printf("Unknown test\n");
[851f33a]1579 } else
1580 list_tests();
[319e60e]1581
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;
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;
[95155b0c]1605
[3f2177e]1606 for (test = tests; test->name != NULL; test++) {
1607 if (str_cmp(test->name, (char *) argv->buffer) == 0) {
1608 fnd = true;
1609
1610 if (test->safe)
1611 run_bench(test, cnt);
1612 else
1613 printf("Unsafe test\n");
1614
1615 break;
1616 }
1617 }
1618
1619 if (!fnd)
1620 printf("Unknown test\n");
1621 }
[cb01e1e]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.