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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cc01214 was aae365bc, checked in by Jakub Jermar <jakub@…>, 7 years ago

Remove RCU and CHT support

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