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

topic/simplify-dev-export
Last change on this file since 7130754 was 7130754, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 18 months ago

Add printbench command for benchmarking print output

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