source: mainline/generic/src/console/cmd.c@ 4e49572

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

Added debugger to AMD64.
Added automatic debugging of AS if it is not rewritten with zero.
Did small changes to IPC infrastructure.

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