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