1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(GD_GPL)
9 */
10
11#include <config.h>
12
13#ifdef CONFIG_DEBUG_BUILD
14#ifndef __API_DEBUG_H
15#define __API_DEBUG_H
16
17#include <benchmark/benchmark_track.h>
18#include <arch/api/syscall.h>
19#include <arch/kernel/vspace.h>
20#include <model/statedata.h>
21#include <kernel/thread.h>
22
23#ifdef CONFIG_PRINTING
24
25static inline void
26debug_printKernelEntryReason(void)
27{
28    printf("\nKernel entry via ");
29    switch (ksKernelEntry.path) {
30    case Entry_Interrupt:
31        printf("Interrupt, irq %lu\n", (unsigned long) ksKernelEntry.word);
32        break;
33    case Entry_UnknownSyscall:
34        printf("Unknown syscall, word: %lu", (unsigned long) ksKernelEntry.word);
35        break;
36    case Entry_VMFault:
37        printf("VM Fault, fault type: %lu\n", (unsigned long) ksKernelEntry.word);
38        break;
39    case Entry_UserLevelFault:
40        printf("User level fault, number: %lu", (unsigned long) ksKernelEntry.word);
41        break;
42#ifdef CONFIG_HARDWARE_DEBUG_API
43    case Entry_DebugFault:
44        printf("Debug fault. Fault Vaddr: 0x%lx", (unsigned long) ksKernelEntry.word);
45        break;
46#endif
47    case Entry_Syscall:
48        printf("Syscall, number: %ld, %s\n", (long) ksKernelEntry.syscall_no, syscall_names[ksKernelEntry.syscall_no]);
49        if (ksKernelEntry.syscall_no == -SysSend ||
50                ksKernelEntry.syscall_no == -SysNBSend ||
51                ksKernelEntry.syscall_no == -SysCall) {
52
53            printf("Cap type: %lu, Invocation tag: %lu\n", (unsigned long) ksKernelEntry.cap_type,
54                   (unsigned long) ksKernelEntry.invocation_tag);
55        }
56        break;
57#ifdef CONFIG_ARCH_ARM
58    case Entry_VCPUFault:
59        printf("VCPUFault\n");
60        break;
61#endif
62#ifdef CONFIG_ARCH_x86
63    case Entry_VMExit:
64        printf("VMExit\n");
65        break;
66#endif
67    default:
68        printf("Unknown\n");
69        break;
70
71    }
72}
73
74/* Prints the user context and stack trace of the current thread */
75static inline void
76debug_printUserState(void)
77{
78    tcb_t *tptr = NODE_STATE(ksCurThread);
79    printf("Current thread: %s\n", tptr->tcbName);
80    printf("Next instruction adress: %lx\n", getRestartPC(tptr));
81    printf("Stack:\n");
82    Arch_userStackTrace(tptr);
83}
84
85static inline void
86debug_printTCB(tcb_t *tcb)
87{
88    printf("%40s\t", tcb->tcbName);
89    char* state;
90    switch (thread_state_get_tsType(tcb->tcbState)) {
91    case ThreadState_Inactive:
92        state = "inactive";
93        break;
94    case ThreadState_Running:
95        state = "running";
96        break;
97    case ThreadState_Restart:
98        state = "restart";
99        break;
100    case ThreadState_BlockedOnReceive:
101        state = "blocked on recv";
102        break;
103    case ThreadState_BlockedOnSend:
104        state = "blocked on send";
105        break;
106    case ThreadState_BlockedOnReply:
107        state = "blocked on reply";
108        break;
109    case ThreadState_BlockedOnNotification:
110        state = "blocked on ntfn";
111        break;
112#ifdef CONFIG_VTX
113    case ThreadState_RunningVM:
114        state = "running VM";
115        break;
116#endif
117    case ThreadState_IdleThreadState:
118        state = "idle";
119        break;
120    default:
121        fail("Unknown thread state");
122    }
123
124    word_t core = SMP_TERNARY(tcb->tcbAffinity, 0);
125    printf("%15s\t%p\t%20lu\t%lu\n", state, (void *) getRestartPC(tcb), tcb->tcbPriority, core);
126}
127
128static inline void
129debug_dumpScheduler(void)
130{
131    printf("Dumping all tcbs!\n");
132    printf("Name                                    \tState          \tIP                  \t Prio \t Core\n");
133    printf("--------------------------------------------------------------------------------------\n");
134    for (tcb_t *curr = NODE_STATE(ksDebugTCBs); curr != NULL; curr = curr->tcbDebugNext) {
135        debug_printTCB(curr);
136    }
137}
138#endif /* CONFIG_PRINTING */
139#endif /* __API_DEBUG_H */
140#endif /* CONFIG_DEBUG_BUILD */
141
142