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

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

Declare malloc() etc in standard <stdlib.h> rather than <mm/slab.h>

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