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