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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 66be0288 was b2fa1204, checked in by Martin Sucha <sucha14@…>, 12 years ago

Cherrypick usage of kernel logger

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