source: mainline/generic/src/console/cmd.c@ 428aabf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 428aabf was 10e16a7, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Added scheduler queues output. The scheduler is buggy - on SMP
the cpus never get tu cpu_sleep, in slab2 test on 4 cpus everything
is on the first cpu.
The slab allocator passes tests in this configuration, but in slightly
different(more efficient) locking order it panics. TODO Find out why
does it panic.

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2 * Copyright (C) 2005 Jakub Jermar
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
29/**
30 * This file is meant to contain all wrapper functions for
31 * all kconsole commands. The point is in separating
32 * kconsole specific wrappers from kconsole-unaware functions
33 * from other subsystems.
34 */
35
36#include <console/cmd.h>
37#include <console/kconsole.h>
38#include <print.h>
39#include <panic.h>
40#include <typedefs.h>
41#include <arch/types.h>
42#include <list.h>
43#include <arch.h>
44#include <func.h>
45#include <macros.h>
46#include <debug.h>
47#include <symtab.h>
48#include <cpu.h>
49#include <mm/tlb.h>
50#include <arch/mm/tlb.h>
51#include <mm/frame.h>
52#include <main/version.h>
53#include <mm/slab.h>
54#include <proc/scheduler.h>
55
56/** Data and methods for 'help' command. */
57static int cmd_help(cmd_arg_t *argv);
58static cmd_info_t help_info = {
59 .name = "help",
60 .description = "List of supported commands.",
61 .func = cmd_help,
62 .argc = 0
63};
64
65static cmd_info_t exit_info = {
66 .name = "exit",
67 .description ="Exit kconsole",
68 .argc = 0
69};
70
71/** Data and methods for 'description' command. */
72static int cmd_desc(cmd_arg_t *argv);
73static void desc_help(void);
74static char desc_buf[MAX_CMDLINE+1];
75static cmd_arg_t desc_argv = {
76 .type = ARG_TYPE_STRING,
77 .buffer = desc_buf,
78 .len = sizeof(desc_buf)
79};
80static cmd_info_t desc_info = {
81 .name = "describe",
82 .description = "Describe specified command.",
83 .help = desc_help,
84 .func = cmd_desc,
85 .argc = 1,
86 .argv = &desc_argv
87};
88
89/** Data and methods for 'symaddr' command. */
90static int cmd_symaddr(cmd_arg_t *argv);
91static char symaddr_buf[MAX_CMDLINE+1];
92static cmd_arg_t symaddr_argv = {
93 .type = ARG_TYPE_STRING,
94 .buffer = symaddr_buf,
95 .len = sizeof(symaddr_buf)
96};
97static cmd_info_t symaddr_info = {
98 .name = "symaddr",
99 .description = "Return symbol address.",
100 .func = cmd_symaddr,
101 .argc = 1,
102 .argv = &symaddr_argv
103};
104
105static char set_buf[MAX_CMDLINE+1];
106static int cmd_set4(cmd_arg_t *argv);
107static cmd_arg_t set4_argv[] = {
108 {
109 .type = ARG_TYPE_STRING,
110 .buffer = set_buf,
111 .len = sizeof(set_buf)
112 },
113 {
114 .type = ARG_TYPE_INT
115 }
116};
117static cmd_info_t set4_info = {
118 .name = "set4",
119 .description = "set <dest_addr> <value> - 4byte version",
120 .func = cmd_set4,
121 .argc = 2,
122 .argv = set4_argv
123};
124
125/** Data and methods for 'call0' command. */
126static char call0_buf[MAX_CMDLINE+1];
127static char carg1_buf[MAX_CMDLINE+1];
128static char carg2_buf[MAX_CMDLINE+1];
129static char carg3_buf[MAX_CMDLINE+1];
130
131static int cmd_call0(cmd_arg_t *argv);
132static cmd_arg_t call0_argv = {
133 .type = ARG_TYPE_STRING,
134 .buffer = call0_buf,
135 .len = sizeof(call0_buf)
136};
137static cmd_info_t call0_info = {
138 .name = "call0",
139 .description = "call0 <function> -> call function().",
140 .func = cmd_call0,
141 .argc = 1,
142 .argv = &call0_argv
143};
144
145/** Data and methods for 'call1' command. */
146static int cmd_call1(cmd_arg_t *argv);
147static cmd_arg_t call1_argv[] = {
148 {
149 .type = ARG_TYPE_STRING,
150 .buffer = call0_buf,
151 .len = sizeof(call0_buf)
152 },
153 {
154 .type = ARG_TYPE_VAR,
155 .buffer = carg1_buf,
156 .len = sizeof(carg1_buf)
157 }
158};
159static cmd_info_t call1_info = {
160 .name = "call1",
161 .description = "call1 <function> <arg1> -> call function(arg1).",
162 .func = cmd_call1,
163 .argc = 2,
164 .argv = call1_argv
165};
166
167/** Data and methods for 'call2' command. */
168static int cmd_call2(cmd_arg_t *argv);
169static cmd_arg_t call2_argv[] = {
170 {
171 .type = ARG_TYPE_STRING,
172 .buffer = call0_buf,
173 .len = sizeof(call0_buf)
174 },
175 {
176 .type = ARG_TYPE_VAR,
177 .buffer = carg1_buf,
178 .len = sizeof(carg1_buf)
179 },
180 {
181 .type = ARG_TYPE_VAR,
182 .buffer = carg2_buf,
183 .len = sizeof(carg2_buf)
184 }
185};
186static cmd_info_t call2_info = {
187 .name = "call2",
188 .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
189 .func = cmd_call2,
190 .argc = 3,
191 .argv = call2_argv
192};
193
194/** Data and methods for 'call3' command. */
195static int cmd_call3(cmd_arg_t *argv);
196static cmd_arg_t call3_argv[] = {
197 {
198 .type = ARG_TYPE_STRING,
199 .buffer = call0_buf,
200 .len = sizeof(call0_buf)
201 },
202 {
203 .type = ARG_TYPE_VAR,
204 .buffer = carg1_buf,
205 .len = sizeof(carg1_buf)
206 },
207 {
208 .type = ARG_TYPE_VAR,
209 .buffer = carg2_buf,
210 .len = sizeof(carg2_buf)
211 },
212 {
213 .type = ARG_TYPE_VAR,
214 .buffer = carg3_buf,
215 .len = sizeof(carg3_buf)
216 }
217
218};
219static cmd_info_t call3_info = {
220 .name = "call3",
221 .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
222 .func = cmd_call3,
223 .argc = 4,
224 .argv = call3_argv
225};
226
227/** Data and methods for 'halt' command. */
228static int cmd_halt(cmd_arg_t *argv);
229static cmd_info_t halt_info = {
230 .name = "halt",
231 .description = "Halt the kernel.",
232 .func = cmd_halt,
233 .argc = 0
234};
235
236/** Data and methods for 'tlb' command. */
237static int cmd_tlb(cmd_arg_t *argv);
238cmd_info_t tlb_info = {
239 .name = "tlb",
240 .description = "Print TLB of current processor.",
241 .help = NULL,
242 .func = cmd_tlb,
243 .argc = 0,
244 .argv = NULL
245};
246
247
248static int cmd_sched(cmd_arg_t *argv);
249static cmd_info_t sched_info = {
250 .name = "scheduler",
251 .description = "List all scheduler information",
252 .func = cmd_sched,
253 .argc = 0
254};
255
256static int cmd_slabs(cmd_arg_t *argv);
257static cmd_info_t slabs_info = {
258 .name = "slabs",
259 .description = "List SLAB caches.",
260 .func = cmd_slabs,
261 .argc = 0
262};
263
264/** Data and methods for 'zones' command */
265static int cmd_zones(cmd_arg_t *argv);
266static cmd_info_t zones_info = {
267 .name = "zones",
268 .description = "List of memory zones.",
269 .func = cmd_zones,
270 .argc = 0
271};
272
273/** Data and methods for 'zone' command */
274static int cmd_zone(cmd_arg_t *argv);
275static cmd_arg_t zone_argv = {
276 .type = ARG_TYPE_INT,
277};
278
279static cmd_info_t zone_info = {
280 .name = "zone",
281 .description = "Show memory zone structure.",
282 .func = cmd_zone,
283 .argc = 1,
284 .argv = &zone_argv
285};
286
287/** Data and methods for 'cpus' command. */
288static int cmd_cpus(cmd_arg_t *argv);
289cmd_info_t cpus_info = {
290 .name = "cpus",
291 .description = "List all processors.",
292 .help = NULL,
293 .func = cmd_cpus,
294 .argc = 0,
295 .argv = NULL
296};
297
298/** Data and methods for 'version' command. */
299static int cmd_version(cmd_arg_t *argv);
300cmd_info_t version_info = {
301 .name = "version",
302 .description = "Print version information.",
303 .help = NULL,
304 .func = cmd_version,
305 .argc = 0,
306 .argv = NULL
307};
308
309static cmd_info_t *basic_commands[] = {
310 &call0_info,
311 &call1_info,
312 &call2_info,
313 &call3_info,
314 &cpus_info,
315 &desc_info,
316 &exit_info,
317 &halt_info,
318 &help_info,
319 &set4_info,
320 &slabs_info,
321 &symaddr_info,
322 &sched_info,
323 &tlb_info,
324 &version_info,
325 &zones_info,
326 &zone_info,
327 NULL
328};
329
330
331/** Initialize command info structure.
332 *
333 * @param cmd Command info structure.
334 *
335 */
336void cmd_initialize(cmd_info_t *cmd)
337{
338 spinlock_initialize(&cmd->lock, "cmd");
339 link_initialize(&cmd->link);
340}
341
342/** Initialize and register commands. */
343void cmd_init(void)
344{
345 int i;
346
347 for (i=0;basic_commands[i]; i++) {
348 cmd_initialize(basic_commands[i]);
349 if (!cmd_register(basic_commands[i]))
350 panic("could not register command %s\n",
351 basic_commands[i]->name);
352 }
353}
354
355
356/** List supported commands.
357 *
358 * @param argv Argument vector.
359 *
360 * @return 0 on failure, 1 on success.
361 */
362int cmd_help(cmd_arg_t *argv)
363{
364 link_t *cur;
365
366 spinlock_lock(&cmd_lock);
367
368 for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
369 cmd_info_t *hlp;
370
371 hlp = list_get_instance(cur, cmd_info_t, link);
372 spinlock_lock(&hlp->lock);
373
374 printf("%s - %s\n", hlp->name, hlp->description);
375
376 spinlock_unlock(&hlp->lock);
377 }
378
379 spinlock_unlock(&cmd_lock);
380
381 return 1;
382}
383
384/** Describe specified command.
385 *
386 * @param argv Argument vector.
387 *
388 * @return 0 on failure, 1 on success.
389 */
390int cmd_desc(cmd_arg_t *argv)
391{
392 link_t *cur;
393
394 spinlock_lock(&cmd_lock);
395
396 for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
397 cmd_info_t *hlp;
398
399 hlp = list_get_instance(cur, cmd_info_t, link);
400 spinlock_lock(&hlp->lock);
401
402 if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
403 printf("%s - %s\n", hlp->name, hlp->description);
404 if (hlp->help)
405 hlp->help();
406 spinlock_unlock(&hlp->lock);
407 break;
408 }
409
410 spinlock_unlock(&hlp->lock);
411 }
412
413 spinlock_unlock(&cmd_lock);
414
415 return 1;
416}
417
418/** Search symbol table */
419int cmd_symaddr(cmd_arg_t *argv)
420{
421 symtab_print_search(argv->buffer);
422
423 return 1;
424}
425
426/** Call function with zero parameters */
427int cmd_call0(cmd_arg_t *argv)
428{
429 __address symaddr;
430 char *symbol;
431 __native (*f)(void);
432
433 symaddr = get_symbol_addr(argv->buffer);
434 if (!symaddr)
435 printf("Symbol %s not found.\n", argv->buffer);
436 else if (symaddr == (__address) -1) {
437 symtab_print_search(argv->buffer);
438 printf("Duplicate symbol, be more specific.\n");
439 } else {
440 symbol = get_symtab_entry(symaddr);
441 printf("Calling f(): 0x%p: %s\n", symaddr, symbol);
442 f = (__native (*)(void)) symaddr;
443 printf("Result: 0x%p\n", f());
444 }
445
446 return 1;
447}
448
449/** Call function with one parameter */
450int cmd_call1(cmd_arg_t *argv)
451{
452 __address symaddr;
453 char *symbol;
454 __native (*f)(__native,...);
455 __native arg1 = argv[1].intval;
456
457 symaddr = get_symbol_addr(argv->buffer);
458 if (!symaddr)
459 printf("Symbol %s not found.\n", argv->buffer);
460 else if (symaddr == (__address) -1) {
461 symtab_print_search(argv->buffer);
462 printf("Duplicate symbol, be more specific.\n");
463 } else {
464 symbol = get_symtab_entry(symaddr);
465 printf("Calling f(0x%x): 0x%p: %s\n", arg1, symaddr, symbol);
466 f = (__native (*)(__native,...)) symaddr;
467 printf("Result: 0x%p\n", f(arg1));
468 }
469
470 return 1;
471}
472
473/** Call function with two parameters */
474int cmd_call2(cmd_arg_t *argv)
475{
476 __address symaddr;
477 char *symbol;
478 __native (*f)(__native,__native,...);
479 __native arg1 = argv[1].intval;
480 __native arg2 = argv[2].intval;
481
482 symaddr = get_symbol_addr(argv->buffer);
483 if (!symaddr)
484 printf("Symbol %s not found.\n", argv->buffer);
485 else if (symaddr == (__address) -1) {
486 symtab_print_search(argv->buffer);
487 printf("Duplicate symbol, be more specific.\n");
488 } else {
489 symbol = get_symtab_entry(symaddr);
490 printf("Calling f(0x%x,0x%x): 0x%p: %s\n",
491 arg1, arg2, symaddr, symbol);
492 f = (__native (*)(__native,__native,...)) symaddr;
493 printf("Result: 0x%p\n", f(arg1, arg2));
494 }
495
496 return 1;
497}
498
499/** Call function with three parameters */
500int cmd_call3(cmd_arg_t *argv)
501{
502 __address symaddr;
503 char *symbol;
504 __native (*f)(__native,__native,__native,...);
505 __native arg1 = argv[1].intval;
506 __native arg2 = argv[2].intval;
507 __native arg3 = argv[3].intval;
508
509 symaddr = get_symbol_addr(argv->buffer);
510 if (!symaddr)
511 printf("Symbol %s not found.\n", argv->buffer);
512 else if (symaddr == (__address) -1) {
513 symtab_print_search(argv->buffer);
514 printf("Duplicate symbol, be more specific.\n");
515 } else {
516 symbol = get_symtab_entry(symaddr);
517 printf("Calling f(0x%x,0x%x, 0x%x): 0x%p: %s\n",
518 arg1, arg2, arg3, symaddr, symbol);
519 f = (__native (*)(__native,__native,__native,...)) symaddr;
520 printf("Result: 0x%p\n", f(arg1, arg2, arg3));
521 }
522
523 return 1;
524}
525
526
527/** Print detailed description of 'describe' command. */
528void desc_help(void)
529{
530 printf("Syntax: describe command_name\n");
531}
532
533/** Halt the kernel.
534 *
535 * @param argv Argument vector (ignored).
536 *
537 * @return 0 on failure, 1 on success (never returns).
538 */
539int cmd_halt(cmd_arg_t *argv)
540{
541 halt();
542 return 1;
543}
544
545/** Command for printing TLB contents.
546 *
547 * @param argv Not used.
548 *
549 * @return Always returns 1.
550 */
551int cmd_tlb(cmd_arg_t *argv)
552{
553 tlb_print();
554 return 1;
555}
556
557/** Write 4 byte value to address */
558int cmd_set4(cmd_arg_t *argv)
559{
560 __u32 *addr ;
561 __u32 arg1 = argv[1].intval;
562 bool pointer = false;
563
564 if (((char *)argv->buffer)[0] == '*') {
565 addr = (__u32 *) get_symbol_addr(argv->buffer+1);
566 pointer = true;
567 } else if (((char *)argv->buffer)[0] >= '0' &&
568 ((char *)argv->buffer)[0] <= '9')
569 addr = (__u32 *)atoi((char *)argv->buffer);
570 else
571 addr = (__u32 *)get_symbol_addr(argv->buffer);
572
573 if (!addr)
574 printf("Symbol %s not found.\n", argv->buffer);
575 else if (addr == (__u32 *) -1) {
576 symtab_print_search(argv->buffer);
577 printf("Duplicate symbol, be more specific.\n");
578 } else {
579 if (pointer)
580 addr = (__u32 *)(*(__native *)addr);
581 printf("Writing 0x%x -> 0x%p\n", arg1, addr);
582 *addr = arg1;
583
584 }
585
586 return 1;
587}
588
589/** Command for listings SLAB caches
590 *
591 * @param argv Ignores
592 *
593 * @return Always 1
594 */
595int cmd_slabs(cmd_arg_t * argv) {
596 slab_print_list();
597 return 1;
598}
599
600/** Command for listings Thread information
601 *
602 * @param argv Ignores
603 *
604 * @return Always 1
605 */
606int cmd_sched(cmd_arg_t * argv) {
607 sched_print_list();
608 return 1;
609}
610
611/** Command for listing memory zones
612 *
613 * @param argv Ignored
614 *
615 * return Always 1
616 */
617int cmd_zones(cmd_arg_t * argv) {
618 zone_print_list();
619 return 1;
620}
621
622/** Command for memory zone details
623 *
624 * @param argv Integer argument from cmdline expected
625 *
626 * return Always 1
627 */
628int cmd_zone(cmd_arg_t * argv) {
629 zone_print_one(argv[0].intval);
630 return 1;
631}
632
633/** Command for listing processors.
634 *
635 * @param argv Ignored.
636 *
637 * return Always 1.
638 */
639int cmd_cpus(cmd_arg_t *argv)
640{
641 cpu_list();
642 return 1;
643}
644
645/** Command for printing kernel version.
646 *
647 * @param argv Ignored.
648 *
649 * return Always 1.
650 */
651int cmd_version(cmd_arg_t *argv)
652{
653 version_print();
654 return 1;
655}
Note: See TracBrowser for help on using the repository browser.