Release the rmap list lock after cleaning the head entry in MmDeleteAllRmaps. This...
[reactos.git] / reactos / ntoskrnl / kd / kdmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <internal/debug.h>
13
14 /* VARIABLES ***************************************************************/
15
16 BOOLEAN KdDebuggerEnabled = FALSE;
17 BOOLEAN KdEnteredDebugger = FALSE;
18 BOOLEAN KdDebuggerNotPresent = TRUE;
19 BOOLEAN KiEnableTimerWatchdog = FALSE;
20 ULONG KiBugCheckData;
21 BOOLEAN KdpBreakPending;
22 VOID STDCALL PspDumpThreads(BOOLEAN SystemThreads);
23
24 typedef struct
25 {
26 ULONG ComponentId;
27 ULONG Level;
28 } KD_COMPONENT_DATA;
29 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
30 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
31 ULONG KdComponentTableEntries = 0;
32
33 /* PRIVATE FUNCTIONS *********************************************************/
34
35 ULONG
36 STDCALL
37 KdpServiceDispatcher(ULONG Service,
38 PVOID Buffer1,
39 ULONG Buffer1Length)
40 {
41 ULONG Result = 0;
42
43 switch (Service)
44 {
45 case BREAKPOINT_PRINT: /* DbgPrint */
46 Result = KdpPrintString(Buffer1, Buffer1Length);
47 break;
48
49 #ifdef DBG
50 case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
51 {
52 switch ((ULONG)Buffer1)
53 {
54 case DumpNonPagedPool:
55 MiDebugDumpNonPagedPool(FALSE);
56 break;
57
58 case ManualBugCheck:
59 KEBUGCHECK(MANUALLY_INITIATED_CRASH);
60 break;
61
62 case DumpNonPagedPoolStats:
63 MiDebugDumpNonPagedPoolStats(FALSE);
64 break;
65
66 case DumpNewNonPagedPool:
67 MiDebugDumpNonPagedPool(TRUE);
68 break;
69
70 case DumpNewNonPagedPoolStats:
71 MiDebugDumpNonPagedPoolStats(TRUE);
72 break;
73
74 case DumpAllThreads:
75 PspDumpThreads(TRUE);
76 break;
77
78 case DumpUserThreads:
79 PspDumpThreads(FALSE);
80 break;
81
82 case EnterDebugger:
83 DbgBreakPoint();
84 break;
85
86 default:
87 break;
88 }
89 }
90 #endif
91 default:
92 HalDisplayString ("Invalid debug service call!\n");
93 break;
94 }
95
96 return Result;
97 }
98
99 KD_CONTINUE_TYPE
100 STDCALL
101 KdpEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
102 KPROCESSOR_MODE PreviousMode,
103 PCONTEXT Context,
104 PKTRAP_FRAME TrapFrame,
105 BOOLEAN FirstChance,
106 BOOLEAN Gdb)
107 {
108 /* Get out of here if the Debugger isn't enabled */
109 if (!KdDebuggerEnabled) return kdHandleException;
110
111 /* FIXME:
112 * Right now, the GDB wrapper seems to handle exceptions differntly
113 * from KDGB and both are called at different times, while the GDB
114 * one is only called once and that's it. I don't really have the knowledge
115 * to fix the GDB stub, so until then, we'll be using this hack
116 */
117 if (Gdb)
118 {
119 /* Call the registered wrapper */
120 if (WrapperInitRoutine) return WrapperTable.
121 KdpExceptionRoutine(ExceptionRecord,
122 Context,
123 TrapFrame);
124 }
125
126 /* Call KDBG if available */
127 return KdbEnterDebuggerException(ExceptionRecord,
128 PreviousMode,
129 Context,
130 TrapFrame,
131 FirstChance);
132 }
133
134 /* PUBLIC FUNCTIONS *********************************************************/
135
136 /*
137 * @implemented
138 */
139 VOID
140 STDCALL
141 KdDisableDebugger(VOID)
142 {
143 KIRQL OldIrql;
144
145 /* Raise IRQL */
146 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
147
148 /* TODO: Disable any breakpoints */
149
150 /* Disable the Debugger */
151 KdDebuggerEnabled = FALSE;
152
153 /* Lower the IRQL */
154 KeLowerIrql(OldIrql);
155 }
156
157 /*
158 * @implemented
159 */
160 VOID
161 STDCALL
162 KdEnableDebugger(VOID)
163 {
164 KIRQL OldIrql;
165
166 /* Raise IRQL */
167 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
168
169 /* TODO: Re-enable any breakpoints */
170
171 /* Enable the Debugger */
172 KdDebuggerEnabled = TRUE;
173
174 /* Lower the IRQL */
175 KeLowerIrql(OldIrql);
176 }
177
178 /*
179 * @implemented
180 */
181 BOOLEAN
182 STDCALL
183 KdPollBreakIn(VOID)
184 {
185 return KdpBreakPending;
186 }
187
188 /*
189 * @implemented
190 */
191 VOID
192 STDCALL
193 KeEnterKernelDebugger(VOID)
194 {
195 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
196
197 /* Set the Variable */
198 KdEnteredDebugger = TRUE;
199
200 /* Halt the CPU */
201 for (;;) Ke386HaltProcessor();
202 }
203
204 /*
205 * @unimplemented
206 */
207 NTSTATUS
208 STDCALL
209 KdPowerTransition(ULONG PowerState)
210 {
211 UNIMPLEMENTED;
212 return STATUS_NOT_IMPLEMENTED;
213 }
214
215 NTSTATUS
216 STDCALL
217 NtQueryDebugFilterState(IN ULONG ComponentId,
218 IN ULONG Level)
219 {
220 unsigned int i;
221
222 /* convert Level to mask if it isn't already one */
223 if ( Level < 32 )
224 Level = 1 << Level;
225
226 for ( i = 0; i < KdComponentTableEntries; i++ )
227 {
228 if ( ComponentId == KdComponentTable[i].ComponentId )
229 {
230 if ( Level & KdComponentTable[i].Level )
231 return TRUE;
232 break;
233 }
234 }
235 return FALSE;
236 }
237
238 NTSTATUS
239 STDCALL
240 NtSetDebugFilterState(IN ULONG ComponentId,
241 IN ULONG Level,
242 IN BOOLEAN State)
243 {
244 unsigned int i;
245 for ( i = 0; i < KdComponentTableEntries; i++ )
246 {
247 if ( ComponentId == KdComponentTable[i].ComponentId )
248 break;
249 }
250 if ( i == KdComponentTableEntries )
251 {
252 if ( i == MAX_KD_COMPONENT_TABLE_ENTRIES )
253 return STATUS_INVALID_PARAMETER_1;
254 ++KdComponentTableEntries;
255 KdComponentTable[i].ComponentId = ComponentId;
256 KdComponentTable[i].Level = 0;
257 }
258 if ( State )
259 KdComponentTable[i].Level |= Level;
260 else
261 KdComponentTable[i].Level &= ~Level;
262 return STATUS_SUCCESS;
263 }
264
265 /* EOF */