Subversion Repositories HelenOS

Rev

Rev 2030 | Rev 2042 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
596 jermar 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
 
1888 jermar 29
/** @addtogroup genericconsole
1702 cejka 30
 * @{
31
 */
32
 
596 jermar 33
/**
1264 jermar 34
 * @file    cmd.c
35
 * @brief   Kernel console command wrappers.
36
 *
596 jermar 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>
1474 palkovsky 44
#include <console/console.h>
596 jermar 45
#include <console/kconsole.h>
46
#include <print.h>
47
#include <panic.h>
48
#include <typedefs.h>
49
#include <arch/types.h>
788 jermar 50
#include <adt/list.h>
596 jermar 51
#include <arch.h>
52
#include <func.h>
53
#include <macros.h>
54
#include <debug.h>
55
#include <symtab.h>
673 jermar 56
#include <cpu.h>
596 jermar 57
#include <mm/tlb.h>
58
#include <arch/mm/tlb.h>
2039 decky 59
#include <mm/as.h>
668 bondari 60
#include <mm/frame.h>
673 jermar 61
#include <main/version.h>
759 palkovsky 62
#include <mm/slab.h>
775 palkovsky 63
#include <proc/scheduler.h>
777 palkovsky 64
#include <proc/thread.h>
1060 palkovsky 65
#include <proc/task.h>
1573 palkovsky 66
#include <ipc/ipc.h>
1712 palkovsky 67
#include <ipc/irq.h>
596 jermar 68
 
2019 decky 69
#ifdef CONFIG_TEST
70
#include <test.h>
71
#endif
72
 
1702 cejka 73
/* Data and methods for 'help' command. */
596 jermar 74
static int cmd_help(cmd_arg_t *argv);
75
static cmd_info_t help_info = {
76
    .name = "help",
77
    .description = "List of supported commands.",
78
    .func = cmd_help,
79
    .argc = 0
80
};
81
 
609 palkovsky 82
static cmd_info_t exit_info = {
83
    .name = "exit",
2019 decky 84
    .description = "Exit kconsole",
609 palkovsky 85
    .argc = 0
86
};
87
 
1474 palkovsky 88
static int cmd_continue(cmd_arg_t *argv);
89
static cmd_info_t continue_info = {
90
    .name = "continue",
2019 decky 91
    .description = "Return console back to userspace.",
1474 palkovsky 92
    .func = cmd_continue,
93
    .argc = 0
94
};
95
 
2019 decky 96
#ifdef CONFIG_TEST
97
static int cmd_tests(cmd_arg_t *argv);
98
static cmd_info_t tests_info = {
99
    .name = "tests",
100
    .description = "Print available kernel tests.",
101
    .func = cmd_tests,
102
    .argc = 0
103
};
104
 
105
static char test_buf[MAX_CMDLINE + 1];
106
static int cmd_test(cmd_arg_t *argv);
107
static cmd_arg_t test_argv[] = {
108
    {
109
        .type = ARG_TYPE_STRING,
110
        .buffer = test_buf,
111
        .len = sizeof(test_buf)
112
    }
113
};
114
static cmd_info_t test_info = {
115
    .name = "test",
116
    .description = "Run kernel test.",
117
    .func = cmd_test,
118
    .argc = 1,
119
    .argv = test_argv
120
};
121
#endif
122
 
1702 cejka 123
/* Data and methods for 'description' command. */
596 jermar 124
static int cmd_desc(cmd_arg_t *argv);
125
static void desc_help(void);
126
static char desc_buf[MAX_CMDLINE+1];
127
static cmd_arg_t desc_argv = {
128
    .type = ARG_TYPE_STRING,
129
    .buffer = desc_buf,
130
    .len = sizeof(desc_buf)
131
};
132
static cmd_info_t desc_info = {
133
    .name = "describe",
134
    .description = "Describe specified command.",
135
    .help = desc_help,
136
    .func = cmd_desc,
137
    .argc = 1,
138
    .argv = &desc_argv
139
};
140
 
1702 cejka 141
/* Data and methods for 'symaddr' command. */
596 jermar 142
static int cmd_symaddr(cmd_arg_t *argv);
143
static char symaddr_buf[MAX_CMDLINE+1];
144
static cmd_arg_t symaddr_argv = {
145
    .type = ARG_TYPE_STRING,
146
    .buffer = symaddr_buf,
147
    .len = sizeof(symaddr_buf)
148
};
149
static cmd_info_t symaddr_info = {
150
    .name = "symaddr",
151
    .description = "Return symbol address.",
152
    .func = cmd_symaddr,
153
    .argc = 1,
154
    .argv = &symaddr_argv
155
};
156
 
603 palkovsky 157
static char set_buf[MAX_CMDLINE+1];
158
static int cmd_set4(cmd_arg_t *argv);
159
static cmd_arg_t set4_argv[] = {
160
    {
161
        .type = ARG_TYPE_STRING,
162
        .buffer = set_buf,
163
        .len = sizeof(set_buf)
164
    },
165
    {
166
        .type = ARG_TYPE_INT
167
    }
168
};
169
static cmd_info_t set4_info = {
170
    .name = "set4",
171
    .description = "set <dest_addr> <value> - 4byte version",
172
    .func = cmd_set4,
173
    .argc = 2,
174
    .argv = set4_argv
175
};
176
 
1702 cejka 177
/* Data and methods for 'call0' command. */
596 jermar 178
static char call0_buf[MAX_CMDLINE+1];
179
static char carg1_buf[MAX_CMDLINE+1];
180
static char carg2_buf[MAX_CMDLINE+1];
181
static char carg3_buf[MAX_CMDLINE+1];
182
 
183
static int cmd_call0(cmd_arg_t *argv);
184
static cmd_arg_t call0_argv = {
185
    .type = ARG_TYPE_STRING,
186
    .buffer = call0_buf,
187
    .len = sizeof(call0_buf)
188
};
189
static cmd_info_t call0_info = {
190
    .name = "call0",
191
    .description = "call0 <function> -> call function().",
192
    .func = cmd_call0,
193
    .argc = 1,
194
    .argv = &call0_argv
195
};
196
 
1702 cejka 197
/* Data and methods for 'call1' command. */
596 jermar 198
static int cmd_call1(cmd_arg_t *argv);
199
static cmd_arg_t call1_argv[] = {
200
    {
201
        .type = ARG_TYPE_STRING,
202
        .buffer = call0_buf,
203
        .len = sizeof(call0_buf)
204
    },
205
    {
206
        .type = ARG_TYPE_VAR,
207
        .buffer = carg1_buf,
208
        .len = sizeof(carg1_buf)
209
    }
210
};
211
static cmd_info_t call1_info = {
212
    .name = "call1",
213
    .description = "call1 <function> <arg1> -> call function(arg1).",
214
    .func = cmd_call1,
215
    .argc = 2,
216
    .argv = call1_argv
217
};
218
 
1702 cejka 219
/* Data and methods for 'call2' command. */
596 jermar 220
static int cmd_call2(cmd_arg_t *argv);
221
static cmd_arg_t call2_argv[] = {
222
    {
223
        .type = ARG_TYPE_STRING,
224
        .buffer = call0_buf,
225
        .len = sizeof(call0_buf)
226
    },
227
    {
228
        .type = ARG_TYPE_VAR,
229
        .buffer = carg1_buf,
230
        .len = sizeof(carg1_buf)
231
    },
232
    {
233
        .type = ARG_TYPE_VAR,
234
        .buffer = carg2_buf,
235
        .len = sizeof(carg2_buf)
236
    }
237
};
238
static cmd_info_t call2_info = {
239
    .name = "call2",
240
    .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
241
    .func = cmd_call2,
242
    .argc = 3,
243
    .argv = call2_argv
244
};
245
 
1702 cejka 246
/* Data and methods for 'call3' command. */
596 jermar 247
static int cmd_call3(cmd_arg_t *argv);
248
static cmd_arg_t call3_argv[] = {
249
    {
250
        .type = ARG_TYPE_STRING,
251
        .buffer = call0_buf,
252
        .len = sizeof(call0_buf)
253
    },
254
    {
255
        .type = ARG_TYPE_VAR,
256
        .buffer = carg1_buf,
257
        .len = sizeof(carg1_buf)
258
    },
259
    {
260
        .type = ARG_TYPE_VAR,
261
        .buffer = carg2_buf,
262
        .len = sizeof(carg2_buf)
263
    },
264
    {
265
        .type = ARG_TYPE_VAR,
266
        .buffer = carg3_buf,
267
        .len = sizeof(carg3_buf)
268
    }
269
 
270
};
271
static cmd_info_t call3_info = {
272
    .name = "call3",
273
    .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
274
    .func = cmd_call3,
275
    .argc = 4,
276
    .argv = call3_argv
277
};
278
 
1702 cejka 279
/* Data and methods for 'halt' command. */
596 jermar 280
static int cmd_halt(cmd_arg_t *argv);
281
static cmd_info_t halt_info = {
282
    .name = "halt",
283
    .description = "Halt the kernel.",
284
    .func = cmd_halt,
285
    .argc = 0
286
};
287
 
1702 cejka 288
/* Data and methods for 'tlb' command. */
673 jermar 289
static int cmd_tlb(cmd_arg_t *argv);
290
cmd_info_t tlb_info = {
291
    .name = "tlb",
596 jermar 292
    .description = "Print TLB of current processor.",
293
    .help = NULL,
673 jermar 294
    .func = cmd_tlb,
596 jermar 295
    .argc = 0,
296
    .argv = NULL
297
};
298
 
777 palkovsky 299
static int cmd_threads(cmd_arg_t *argv);
300
static cmd_info_t threads_info = {
301
    .name = "threads",
1695 jermar 302
    .description = "List all threads.",
777 palkovsky 303
    .func = cmd_threads,
304
    .argc = 0
305
};
668 bondari 306
 
1060 palkovsky 307
static int cmd_tasks(cmd_arg_t *argv);
308
static cmd_info_t tasks_info = {
309
    .name = "tasks",
1695 jermar 310
    .description = "List all tasks.",
1060 palkovsky 311
    .func = cmd_tasks,
312
    .argc = 0
313
};
777 palkovsky 314
 
1060 palkovsky 315
 
775 palkovsky 316
static int cmd_sched(cmd_arg_t *argv);
317
static cmd_info_t sched_info = {
318
    .name = "scheduler",
1695 jermar 319
    .description = "List all scheduler information.",
775 palkovsky 320
    .func = cmd_sched,
321
    .argc = 0
322
};
323
 
759 palkovsky 324
static int cmd_slabs(cmd_arg_t *argv);
325
static cmd_info_t slabs_info = {
326
    .name = "slabs",
1695 jermar 327
    .description = "List slab caches.",
759 palkovsky 328
    .func = cmd_slabs,
329
    .argc = 0
330
};
331
 
1702 cejka 332
/* Data and methods for 'zones' command */
668 bondari 333
static int cmd_zones(cmd_arg_t *argv);
334
static cmd_info_t zones_info = {
335
    .name = "zones",
336
    .description = "List of memory zones.",
337
    .func = cmd_zones,
338
    .argc = 0
339
};
340
 
1702 cejka 341
/* Data and methods for 'ipc_task' command */
1573 palkovsky 342
static int cmd_ipc_task(cmd_arg_t *argv);
343
static cmd_arg_t ipc_task_argv = {
344
    .type = ARG_TYPE_INT,
345
};
346
static cmd_info_t ipc_task_info = {
347
    .name = "ipc_task",
1695 jermar 348
    .description = "ipc_task <taskid> Show IPC information of given task.",
1573 palkovsky 349
    .func = cmd_ipc_task,
350
    .argc = 1,
351
    .argv = &ipc_task_argv
352
};
353
 
1702 cejka 354
/* Data and methods for 'zone' command */
668 bondari 355
static int cmd_zone(cmd_arg_t *argv);
356
static cmd_arg_t zone_argv = {
357
    .type = ARG_TYPE_INT,
358
};
359
 
360
static cmd_info_t zone_info = {
361
    .name = "zone",
362
    .description = "Show memory zone structure.",
363
    .func = cmd_zone,
364
    .argc = 1,
365
    .argv = &zone_argv
366
};
367
 
1702 cejka 368
/* Data and methods for 'cpus' command. */
673 jermar 369
static int cmd_cpus(cmd_arg_t *argv);
370
cmd_info_t cpus_info = {
371
    .name = "cpus",
372
    .description = "List all processors.",
373
    .help = NULL,
374
    .func = cmd_cpus,
375
    .argc = 0,
376
    .argv = NULL
377
};
668 bondari 378
 
1702 cejka 379
/* Data and methods for 'version' command. */
673 jermar 380
static int cmd_version(cmd_arg_t *argv);
381
cmd_info_t version_info = {
382
    .name = "version",
383
    .description = "Print version information.",
384
    .help = NULL,
385
    .func = cmd_version,
386
    .argc = 0,
387
    .argv = NULL
388
};
668 bondari 389
 
775 palkovsky 390
static cmd_info_t *basic_commands[] = {
391
    &call0_info,
392
    &call1_info,
393
    &call2_info,
394
    &call3_info,
1474 palkovsky 395
    &continue_info,
775 palkovsky 396
    &cpus_info,
397
    &desc_info,
398
    &exit_info,
399
    &halt_info,
400
    &help_info,
1573 palkovsky 401
    &ipc_task_info,
775 palkovsky 402
    &set4_info,
403
    &slabs_info,
404
    &symaddr_info,
405
    &sched_info,
777 palkovsky 406
    &threads_info,
1060 palkovsky 407
    &tasks_info,
775 palkovsky 408
    &tlb_info,
409
    &version_info,
410
    &zones_info,
411
    &zone_info,
2019 decky 412
#ifdef CONFIG_TEST
413
    &tests_info,
414
    &test_info,
415
#endif
775 palkovsky 416
    NULL
417
};
673 jermar 418
 
419
 
596 jermar 420
/** Initialize command info structure.
421
 *
422
 * @param cmd Command info structure.
423
 *
424
 */
425
void cmd_initialize(cmd_info_t *cmd)
426
{
427
    spinlock_initialize(&cmd->lock, "cmd");
428
    link_initialize(&cmd->link);
429
}
430
 
431
/** Initialize and register commands. */
432
void cmd_init(void)
433
{
775 palkovsky 434
    int i;
596 jermar 435
 
775 palkovsky 436
    for (i=0;basic_commands[i]; i++) {
437
        cmd_initialize(basic_commands[i]);
438
        if (!cmd_register(basic_commands[i]))
439
            panic("could not register command %s\n",
440
                  basic_commands[i]->name);
441
    }
596 jermar 442
}
443
 
444
 
445
/** List supported commands.
446
 *
447
 * @param argv Argument vector.
448
 *
449
 * @return 0 on failure, 1 on success.
450
 */
451
int cmd_help(cmd_arg_t *argv)
452
{
453
    link_t *cur;
454
 
455
    spinlock_lock(&cmd_lock);
456
 
457
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
458
        cmd_info_t *hlp;
459
 
460
        hlp = list_get_instance(cur, cmd_info_t, link);
461
        spinlock_lock(&hlp->lock);
462
 
463
        printf("%s - %s\n", hlp->name, hlp->description);
464
 
465
        spinlock_unlock(&hlp->lock);
466
    }
467
 
468
    spinlock_unlock(&cmd_lock);
469
 
470
    return 1;
471
}
472
 
473
/** Describe specified command.
474
 *
475
 * @param argv Argument vector.
476
 *
477
 * @return 0 on failure, 1 on success.
478
 */
479
int cmd_desc(cmd_arg_t *argv)
480
{
481
    link_t *cur;
482
 
483
    spinlock_lock(&cmd_lock);
484
 
485
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
486
        cmd_info_t *hlp;
487
 
488
        hlp = list_get_instance(cur, cmd_info_t, link);
489
        spinlock_lock(&hlp->lock);
490
 
491
        if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
492
            printf("%s - %s\n", hlp->name, hlp->description);
493
            if (hlp->help)
494
                hlp->help();
495
            spinlock_unlock(&hlp->lock);
496
            break;
497
        }
498
 
499
        spinlock_unlock(&hlp->lock);
500
    }
501
 
502
    spinlock_unlock(&cmd_lock);
503
 
504
    return 1;
505
}
506
 
507
/** Search symbol table */
508
int cmd_symaddr(cmd_arg_t *argv)
509
{
510
    symtab_print_search(argv->buffer);
511
 
512
    return 1;
513
}
514
 
515
/** Call function with zero parameters */
516
int cmd_call0(cmd_arg_t *argv)
517
{
1780 jermar 518
    uintptr_t symaddr;
596 jermar 519
    char *symbol;
1780 jermar 520
    unative_t (*f)(void);
1666 palkovsky 521
#ifdef ia64
522
    struct {
1780 jermar 523
        unative_t f;
524
        unative_t gp;
1666 palkovsky 525
    }fptr;
526
#endif
596 jermar 527
 
528
    symaddr = get_symbol_addr(argv->buffer);
529
    if (!symaddr)
530
        printf("Symbol %s not found.\n", argv->buffer);
1780 jermar 531
    else if (symaddr == (uintptr_t) -1) {
596 jermar 532
        symtab_print_search(argv->buffer);
533
        printf("Duplicate symbol, be more specific.\n");
534
    } else {
535
        symbol = get_symtab_entry(symaddr);
1780 jermar 536
        printf("Calling f(): %.*p: %s\n", sizeof(uintptr_t) * 2, symaddr, symbol);
1666 palkovsky 537
#ifdef ia64
538
        fptr.f = symaddr;
1780 jermar 539
        fptr.gp = ((unative_t *)cmd_call2)[1];
540
        f =  (unative_t (*)(void)) &fptr;
1666 palkovsky 541
#else
1780 jermar 542
        f =  (unative_t (*)(void)) symaddr;
1666 palkovsky 543
#endif
1224 cejka 544
        printf("Result: %#zx\n", f());
596 jermar 545
    }
546
 
547
    return 1;
548
}
549
 
550
/** Call function with one parameter */
551
int cmd_call1(cmd_arg_t *argv)
552
{
1780 jermar 553
    uintptr_t symaddr;
596 jermar 554
    char *symbol;
1780 jermar 555
    unative_t (*f)(unative_t,...);
556
    unative_t arg1 = argv[1].intval;
1666 palkovsky 557
#ifdef ia64
558
    struct {
1780 jermar 559
        unative_t f;
560
        unative_t gp;
1666 palkovsky 561
    }fptr;
562
#endif
596 jermar 563
 
564
    symaddr = get_symbol_addr(argv->buffer);
565
    if (!symaddr)
566
        printf("Symbol %s not found.\n", argv->buffer);
1780 jermar 567
    else if (symaddr == (uintptr_t) -1) {
596 jermar 568
        symtab_print_search(argv->buffer);
569
        printf("Duplicate symbol, be more specific.\n");
570
    } else {
571
        symbol = get_symtab_entry(symaddr);
1666 palkovsky 572
 
1780 jermar 573
        printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
1666 palkovsky 574
#ifdef ia64
575
        fptr.f = symaddr;
1780 jermar 576
        fptr.gp = ((unative_t *)cmd_call2)[1];
577
        f =  (unative_t (*)(unative_t,...)) &fptr;
1666 palkovsky 578
#else
1780 jermar 579
        f =  (unative_t (*)(unative_t,...)) symaddr;
1666 palkovsky 580
#endif
1224 cejka 581
        printf("Result: %#zx\n", f(arg1));
596 jermar 582
    }
583
 
584
    return 1;
585
}
586
 
587
/** Call function with two parameters */
588
int cmd_call2(cmd_arg_t *argv)
589
{
1780 jermar 590
    uintptr_t symaddr;
596 jermar 591
    char *symbol;
1780 jermar 592
    unative_t (*f)(unative_t,unative_t,...);
593
    unative_t arg1 = argv[1].intval;
594
    unative_t arg2 = argv[2].intval;
1666 palkovsky 595
#ifdef ia64
596
    struct {
1780 jermar 597
        unative_t f;
598
        unative_t gp;
1666 palkovsky 599
    }fptr;
600
#endif
596 jermar 601
 
602
    symaddr = get_symbol_addr(argv->buffer);
603
    if (!symaddr)
604
        printf("Symbol %s not found.\n", argv->buffer);
1780 jermar 605
    else if (symaddr == (uintptr_t) -1) {
596 jermar 606
        symtab_print_search(argv->buffer);
607
        printf("Duplicate symbol, be more specific.\n");
608
    } else {
609
        symbol = get_symtab_entry(symaddr);
1224 cejka 610
        printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
1780 jermar 611
               arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
1666 palkovsky 612
#ifdef ia64
613
        fptr.f = symaddr;
1780 jermar 614
        fptr.gp = ((unative_t *)cmd_call2)[1];
615
        f =  (unative_t (*)(unative_t,unative_t,...)) &fptr;
1666 palkovsky 616
#else
1780 jermar 617
        f =  (unative_t (*)(unative_t,unative_t,...)) symaddr;
1666 palkovsky 618
#endif
1224 cejka 619
        printf("Result: %#zx\n", f(arg1, arg2));
596 jermar 620
    }
621
 
622
    return 1;
623
}
624
 
625
/** Call function with three parameters */
626
int cmd_call3(cmd_arg_t *argv)
627
{
1780 jermar 628
    uintptr_t symaddr;
596 jermar 629
    char *symbol;
1780 jermar 630
    unative_t (*f)(unative_t,unative_t,unative_t,...);
631
    unative_t arg1 = argv[1].intval;
632
    unative_t arg2 = argv[2].intval;
633
    unative_t arg3 = argv[3].intval;
1666 palkovsky 634
#ifdef ia64
635
    struct {
1780 jermar 636
        unative_t f;
637
        unative_t gp;
1666 palkovsky 638
    }fptr;
639
#endif
596 jermar 640
 
641
    symaddr = get_symbol_addr(argv->buffer);
642
    if (!symaddr)
643
        printf("Symbol %s not found.\n", argv->buffer);
1780 jermar 644
    else if (symaddr == (uintptr_t) -1) {
596 jermar 645
        symtab_print_search(argv->buffer);
646
        printf("Duplicate symbol, be more specific.\n");
647
    } else {
648
        symbol = get_symtab_entry(symaddr);
1224 cejka 649
        printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
1780 jermar 650
               arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
1666 palkovsky 651
#ifdef ia64
652
        fptr.f = symaddr;
1780 jermar 653
        fptr.gp = ((unative_t *)cmd_call2)[1];
654
        f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
1666 palkovsky 655
#else
1780 jermar 656
        f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
1666 palkovsky 657
#endif
1224 cejka 658
        printf("Result: %#zx\n", f(arg1, arg2, arg3));
596 jermar 659
    }
660
 
661
    return 1;
662
}
663
 
664
 
665
/** Print detailed description of 'describe' command. */
666
void desc_help(void)
667
{
668
    printf("Syntax: describe command_name\n");
669
}
670
 
671
/** Halt the kernel.
672
 *
673
 * @param argv Argument vector (ignored).
674
 *
675
 * @return 0 on failure, 1 on success (never returns).
676
 */
677
int cmd_halt(cmd_arg_t *argv)
678
{
679
    halt();
680
    return 1;
681
}
682
 
683
/** Command for printing TLB contents.
684
 *
685
 * @param argv Not used.
686
 *
687
 * @return Always returns 1.
688
 */
673 jermar 689
int cmd_tlb(cmd_arg_t *argv)
596 jermar 690
{
691
    tlb_print();
692
    return 1;
693
}
603 palkovsky 694
 
695
/** Write 4 byte value to address */
696
int cmd_set4(cmd_arg_t *argv)
697
{
1780 jermar 698
    uint32_t *addr ;
699
    uint32_t arg1 = argv[1].intval;
603 palkovsky 700
    bool pointer = false;
701
 
702
    if (((char *)argv->buffer)[0] == '*') {
1780 jermar 703
        addr = (uint32_t *) get_symbol_addr(argv->buffer+1);
603 palkovsky 704
        pointer = true;
705
    } else if (((char *)argv->buffer)[0] >= '0' &&
706
           ((char *)argv->buffer)[0] <= '9')
1780 jermar 707
        addr = (uint32_t *)atoi((char *)argv->buffer);
603 palkovsky 708
    else
1780 jermar 709
        addr = (uint32_t *)get_symbol_addr(argv->buffer);
603 palkovsky 710
 
711
    if (!addr)
712
        printf("Symbol %s not found.\n", argv->buffer);
1780 jermar 713
    else if (addr == (uint32_t *) -1) {
603 palkovsky 714
        symtab_print_search(argv->buffer);
715
        printf("Duplicate symbol, be more specific.\n");
716
    } else {
717
        if (pointer)
1780 jermar 718
            addr = (uint32_t *)(*(unative_t *)addr);
719
        printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
603 palkovsky 720
        *addr = arg1;
721
 
722
    }
723
 
724
    return 1;
725
}
668 bondari 726
 
759 palkovsky 727
/** Command for listings SLAB caches
728
 *
729
 * @param argv Ignores
730
 *
731
 * @return Always 1
732
 */
733
int cmd_slabs(cmd_arg_t * argv) {
734
    slab_print_list();
735
    return 1;
736
}
737
 
777 palkovsky 738
 
775 palkovsky 739
/** Command for listings Thread information
740
 *
741
 * @param argv Ignores
742
 *
743
 * @return Always 1
744
 */
777 palkovsky 745
int cmd_threads(cmd_arg_t * argv) {
746
    thread_print_list();
747
    return 1;
748
}
749
 
1060 palkovsky 750
/** Command for listings Task information
751
 *
752
 * @param argv Ignores
753
 *
754
 * @return Always 1
755
 */
756
int cmd_tasks(cmd_arg_t * argv) {
757
    task_print_list();
758
    return 1;
759
}
760
 
777 palkovsky 761
/** Command for listings Thread information
762
 *
763
 * @param argv Ignores
764
 *
765
 * @return Always 1
766
 */
775 palkovsky 767
int cmd_sched(cmd_arg_t * argv) {
768
    sched_print_list();
769
    return 1;
770
}
771
 
677 bondari 772
/** Command for listing memory zones
773
 *
774
 * @param argv Ignored
775
 *
776
 * return Always 1
777
 */
668 bondari 778
int cmd_zones(cmd_arg_t * argv) {
676 bondari 779
    zone_print_list();
668 bondari 780
    return 1;
781
}
673 jermar 782
 
677 bondari 783
/** Command for memory zone details
784
 *
785
 * @param argv Integer argument from cmdline expected
786
 *
787
 * return Always 1
788
 */
668 bondari 789
int cmd_zone(cmd_arg_t * argv) {
676 bondari 790
    zone_print_one(argv[0].intval);
668 bondari 791
    return 1;
792
}
793
 
1573 palkovsky 794
/** Command for printing task ipc details
795
 *
796
 * @param argv Integer argument from cmdline expected
797
 *
798
 * return Always 1
799
 */
800
int cmd_ipc_task(cmd_arg_t * argv) {
801
    ipc_print_task(argv[0].intval);
802
    return 1;
803
}
804
 
805
 
673 jermar 806
/** Command for listing processors.
807
 *
808
 * @param argv Ignored.
809
 *
810
 * return Always 1.
811
 */
812
int cmd_cpus(cmd_arg_t *argv)
813
{
814
    cpu_list();
815
    return 1;
816
}
817
 
818
/** Command for printing kernel version.
819
 *
820
 * @param argv Ignored.
821
 *
822
 * return Always 1.
823
 */
824
int cmd_version(cmd_arg_t *argv)
825
{
826
    version_print();
827
    return 1;
828
}
1474 palkovsky 829
 
830
/** Command for returning console back to userspace.
831
 *
832
 * @param argv Ignored.
833
 *
834
 * return Always 1.
835
 */
836
int cmd_continue(cmd_arg_t *argv)
837
{
1695 jermar 838
    printf("The kernel will now relinquish the console.\n");
839
    printf("Use userspace controls to redraw the screen.\n");
1474 palkovsky 840
    arch_release_console();
841
    return 1;
842
}
1702 cejka 843
 
2020 decky 844
#ifdef CONFIG_TEST
2019 decky 845
/** Command for printing kernel tests list.
846
 *
847
 * @param argv Ignored.
848
 *
849
 * return Always 1.
850
 */
851
int cmd_tests(cmd_arg_t *argv)
852
{
853
    test_t *test;
854
 
855
    for (test = tests; test->name != NULL; test++)
2020 decky 856
        printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
2019 decky 857
 
2020 decky 858
    printf("*\t\tRun all safe tests\n");
2019 decky 859
    return 1;
860
}
861
 
2039 decky 862
static void test_wrapper(void *arg)
2027 decky 863
{
2039 decky 864
    test_t *test = (test_t *) arg;
2030 decky 865
 
866
    /* Update and read thread accounting
867
       for benchmarking */
868
    ipl_t ipl = interrupts_disable();
2039 decky 869
    spinlock_lock(&TASK->lock);
870
    uint64_t t0 = task_get_accounting(TASK);
871
    spinlock_unlock(&TASK->lock);
2030 decky 872
    interrupts_restore(ipl);
873
 
874
    /* Execute the test */
2027 decky 875
    char * ret = test->entry();
2030 decky 876
 
877
    /* Update and read thread accounting */
878
    ipl = interrupts_disable();
2039 decky 879
    spinlock_lock(&TASK->lock);
880
    uint64_t dt = task_get_accounting(TASK) - t0;
881
    spinlock_unlock(&TASK->lock);
2030 decky 882
    interrupts_restore(ipl);
883
 
2027 decky 884
    printf("Time: %llu cycles\n", dt);
885
 
886
    if (ret == NULL) {
887
        printf("Test passed\n");
2039 decky 888
//      return true;
889
        return;
2027 decky 890
    }
891
 
892
    printf("%s\n", ret);
2039 decky 893
//  return false;
2027 decky 894
}
895
 
2039 decky 896
static bool run_test(const test_t *test)
897
{
898
    printf("%s\t\t%s\n", test->name, test->desc);
899
 
900
    /* Create separate task and thread
901
       for the test */
902
    task_t *ta = task_create(AS_KERNEL, "test");
903
    if (ta == NULL) {
904
        printf("Unable to create test task\n");
905
        return false;
906
    }
907
 
908
    thread_t *t = thread_create(test_wrapper, (void *) test, ta, 0, "test_main");
909
    if (t == NULL) {
910
        printf("Unable to create test main thread\n");
911
        task_destroy(ta);
912
        return false;
913
    }
914
 
915
    /* Run the test */
916
    thread_ready(t);
917
    thread_join(t);
918
    thread_detach(t);
919
 
920
    return true;
921
}
922
 
2019 decky 923
/** Command for returning kernel tests
924
 *
925
 * @param argv Argument vector.
926
 *
927
 * return Always 1.
928
 */
929
int cmd_test(cmd_arg_t *argv)
930
{
931
    test_t *test;
932
 
2020 decky 933
    if (strcmp(argv->buffer, "*") == 0) {
934
        for (test = tests; test->name != NULL; test++) {
935
            if (test->safe) {
2027 decky 936
                printf("\n");
937
                if (!run_test(test))
938
                    break;
2020 decky 939
            }
2019 decky 940
        }
2020 decky 941
    } else {
942
        bool fnd = false;
943
 
944
        for (test = tests; test->name != NULL; test++) {
945
            if (strcmp(test->name, argv->buffer) == 0) {
946
                fnd = true;
2027 decky 947
                run_test(test);
2020 decky 948
                break;
949
            }
950
        }
951
 
952
        if (!fnd)
2027 decky 953
            printf("Unknown test\n");
2019 decky 954
    }
955
 
956
    return 1;
957
}
2020 decky 958
#endif
2019 decky 959
 
1888 jermar 960
/** @}
1702 cejka 961
 */