3d3ff38c3b27ccf06b0d834f966bb9d7f461173c
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdapi.c
5 * PURPOSE: KD64 Public Routines and Internal Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 NTSTATUS
18 NTAPI
19 KdpCopyMemoryChunks(IN ULONG64 Address,
20 IN PVOID Buffer,
21 IN ULONG TotalSize,
22 IN ULONG ChunkSize,
23 IN ULONG Flags,
24 OUT PULONG ActualSize OPTIONAL)
25 {
26 ULONG Length;
27 NTSTATUS Status;
28
29 /* Check if this is physical or virtual copy */
30 if (Flags & MMDBG_COPY_PHYSICAL)
31 {
32 /* Fail physical memory read/write for now */
33 if (Flags & MMDBG_COPY_WRITE)
34 {
35 KdpDprintf("KdpCopyMemoryChunks: Failing write for Physical Address 0x%I64x Length: %x\n",
36 Address,
37 TotalSize);
38 }
39 else
40 {
41 KdpDprintf("KdpCopyMemoryChunks: Failing read for Physical Address 0x%I64x Length: %x\n",
42 Address,
43 TotalSize);
44 }
45
46 /* Return an error */
47 Length = 0;
48 Status = STATUS_UNSUCCESSFUL;
49 }
50 else
51 {
52 /* Protect against NULL */
53 if (!Address)
54 {
55 if (ActualSize) *ActualSize = 0;
56 return STATUS_UNSUCCESSFUL;
57 }
58
59 /* Check if this is read or write */
60 if (Flags & MMDBG_COPY_WRITE)
61 {
62 /* Do the write */
63 RtlCopyMemory((PVOID)(ULONG_PTR)Address,
64 Buffer,
65 TotalSize);
66 }
67 else
68 {
69 /* Do the read */
70 RtlCopyMemory(Buffer,
71 (PVOID)(ULONG_PTR)Address,
72 TotalSize);
73 }
74
75 /* Set size and status */
76 Length = TotalSize;
77 Status = STATUS_SUCCESS;
78 }
79
80 /* Return the actual length if requested */
81 if (ActualSize) *ActualSize = Length;
82
83 /* Return status */
84 return Status;
85 }
86
87 VOID
88 NTAPI
89 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
90 IN PCONTEXT Context)
91 {
92 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
93 STRING Header;
94 NTSTATUS Status = STATUS_SUCCESS;
95
96 /* Validate the address space */
97 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
98 {
99 /* Check if this is process memory */
100 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
101 {
102 /* It is */
103 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
104 }
105 else
106 {
107 /* FIXME: Check if it's session space */
108 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
109 }
110
111 /* Set flags */
112 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
113 DBGKD_QUERY_MEMORY_WRITE |
114 DBGKD_QUERY_MEMORY_EXECUTE;
115 }
116 else
117 {
118 /* Invalid */
119 Status = STATUS_INVALID_PARAMETER;
120 }
121
122 /* Return structure */
123 State->ReturnStatus = Status;
124 Memory->Reserved = 0;
125
126 /* Build header */
127 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
128 Header.Buffer = (PCHAR)State;
129
130 /* Send the packet */
131 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
132 &Header,
133 NULL,
134 &KdpContext);
135 }
136
137 VOID
138 NTAPI
139 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
140 IN PSTRING Data,
141 IN PCONTEXT Context)
142 {
143 /* FIXME: STUB */
144 KdpDprintf("KdpSearchMemory called\n");
145 while (TRUE);
146 }
147
148 VOID
149 NTAPI
150 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
151 IN PSTRING Data,
152 IN PCONTEXT Context)
153 {
154 /* FIXME: STUB */
155 KdpDprintf("KdpFillMemory called\n");
156 while (TRUE);
157 }
158
159 VOID
160 NTAPI
161 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
162 IN PSTRING Data,
163 IN PCONTEXT Context)
164 {
165 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
166 STRING Header;
167
168 /* Build header */
169 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
170 Header.Buffer = (PCHAR)State;
171 ASSERT(Data->Length == 0);
172
173 /* Create the breakpoint */
174 Breakpoint->BreakPointHandle =
175 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
176 if (!Breakpoint->BreakPointHandle)
177 {
178 /* We failed */
179 State->ReturnStatus = STATUS_UNSUCCESSFUL;
180 }
181 else
182 {
183 /* Success! */
184 State->ReturnStatus = STATUS_SUCCESS;
185 }
186
187 /* Send the packet */
188 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
189 &Header,
190 NULL,
191 &KdpContext);
192 }
193
194 VOID
195 NTAPI
196 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
197 IN PSTRING Data,
198 IN PCONTEXT Context)
199 {
200 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
201 STRING Header;
202
203 /* Fill out the header */
204 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
205 Header.Buffer = (PCHAR)State;
206 ASSERT(Data->Length == 0);
207
208 /* Get the version block */
209 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
210 {
211 /* We're all good */
212 State->ReturnStatus = STATUS_SUCCESS;
213 }
214 else
215 {
216 /* We failed */
217 State->ReturnStatus = STATUS_UNSUCCESSFUL;
218 }
219
220 /* Send the packet */
221 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
222 &Header,
223 NULL,
224 &KdpContext);
225 }
226
227 NTSTATUS
228 NTAPI
229 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
230 IN PSTRING Data,
231 IN PCONTEXT Context)
232 {
233 /* FIXME: STUB */
234 KdpDprintf("KdpWriteBreakPointEx called\n");
235 while (TRUE);
236 return STATUS_UNSUCCESSFUL;
237 }
238
239 VOID
240 NTAPI
241 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
242 IN PSTRING Data,
243 IN PCONTEXT Context)
244 {
245 /* FIXME: STUB */
246 KdpDprintf("KdpRestoreBreakPointEx called\n");
247 while (TRUE);
248 }
249
250 VOID
251 NTAPI
252 DumpTraceData(OUT PSTRING TraceData)
253 {
254 /* Update the buffer */
255 TraceDataBuffer[0] = TraceDataBufferPosition;
256
257 /* Setup the trace data */
258 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
259 TraceData->Buffer = (PCHAR)TraceDataBuffer;
260
261 /* Reset the buffer location */
262 TraceDataBufferPosition = 1;
263 }
264
265 VOID
266 NTAPI
267 KdpSetCommonState(IN ULONG NewState,
268 IN PCONTEXT Context,
269 OUT PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
270 {
271 USHORT InstructionCount;
272 BOOLEAN HadBreakpoints;
273
274 /* Setup common stuff available for all CPU architectures */
275 WaitStateChange->NewState = NewState;
276 WaitStateChange->ProcessorLevel = KeProcessorLevel;
277 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
278 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
279 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
280 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
281
282 /* Zero out the Control Report */
283 RtlZeroMemory(&WaitStateChange->ControlReport,
284 sizeof(DBGKD_CONTROL_REPORT));
285
286 /* Now copy the instruction stream and set the count */
287 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
288 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
289 DBGKD_MAXSTREAM);
290 InstructionCount = DBGKD_MAXSTREAM;
291 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
292
293 /* Clear all the breakpoints in this region */
294 HadBreakpoints =
295 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
296 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
297 WaitStateChange->ControlReport.InstructionCount - 1));
298 if (HadBreakpoints)
299 {
300 /* Copy the instruction stream again, this time without breakpoints */
301 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
302 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
303 WaitStateChange->ControlReport.InstructionCount);
304 }
305 }
306
307 VOID
308 NTAPI
309 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
310 {
311 STRING Header;
312
313 /* Fill out the header */
314 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
315 Header.Buffer = (PCHAR)State;
316
317 /* Get the version block */
318 KdpSysGetVersion(&State->u.GetVersion64);
319
320 /* Fill out the state */
321 State->ApiNumber = DbgKdGetVersionApi;
322 State->ReturnStatus = STATUS_SUCCESS;
323
324 /* Send the packet */
325 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
326 &Header,
327 NULL,
328 &KdpContext);
329 }
330
331 VOID
332 NTAPI
333 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
334 IN PSTRING Data,
335 IN PCONTEXT Context)
336 {
337 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
338 STRING Header;
339 ULONG Length = ReadMemory->TransferCount;
340 ULONG64 TargetBaseAddress = State->u.ReadMemory.TargetBaseAddress;
341
342 /* Setup the header */
343 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
344 Header.Buffer = (PCHAR)State;
345 ASSERT(Data->Length == 0);
346
347 /* Validate length */
348 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
349 {
350 /* Overflow, set it to maximum possible */
351 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
352 }
353
354 /* Do the read */
355 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
356 Data->Buffer,
357 Length,
358 0,
359 MMDBG_COPY_UNSAFE,
360 &Length);
361
362 /* Return the actual length read */
363 Data->Length = ReadMemory->ActualBytesRead = Length;
364
365 /* Send the packet */
366 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
367 &Header,
368 Data,
369 &KdpContext);
370 }
371
372 VOID
373 NTAPI
374 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
375 IN PSTRING Data,
376 IN PCONTEXT Context)
377 {
378 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
379 STRING Header;
380
381 /* Setup the header */
382 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
383 Header.Buffer = (PCHAR)State;
384
385 /* Do the write */
386 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
387 Data->Buffer,
388 Data->Length,
389 0,
390 MMDBG_COPY_UNSAFE |
391 MMDBG_COPY_WRITE,
392 &WriteMemory->ActualBytesWritten);
393
394 /* Send the packet */
395 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
396 &Header,
397 NULL,
398 &KdpContext);
399 }
400
401 VOID
402 NTAPI
403 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
404 IN PSTRING Data,
405 IN PCONTEXT Context)
406 {
407 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
408 STRING Header;
409 ULONG Length = ReadMemory->TransferCount;
410 ULONG Flags, CacheFlags;
411
412 /* Setup the header */
413 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
414 Header.Buffer = (PCHAR)State;
415 ASSERT(Data->Length == 0);
416
417 /* Validate length */
418 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
419 {
420 /* Overflow, set it to maximum possible */
421 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
422 }
423
424 /* Start with the default flags */
425 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL;
426
427 /* Get the caching flags and check if a type is specified */
428 CacheFlags = ReadMemory->ActualBytesRead;
429 if (CacheFlags == DBGKD_CACHING_CACHED)
430 {
431 /* Cached */
432 Flags |= MMDBG_COPY_CACHED;
433 }
434 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
435 {
436 /* Uncached */
437 Flags |= MMDBG_COPY_UNCACHED;
438 }
439 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
440 {
441 /* Write Combined */
442 Flags |= DBGKD_CACHING_WRITE_COMBINED;
443 }
444
445 /* Do the read */
446 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
447 Data->Buffer,
448 Length,
449 0,
450 Flags,
451 &Length);
452
453 /* Return the actual length read */
454 Data->Length = ReadMemory->ActualBytesRead = Length;
455
456 /* Send the packet */
457 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
458 &Header,
459 Data,
460 &KdpContext);
461 }
462
463 VOID
464 NTAPI
465 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
466 IN PSTRING Data,
467 IN PCONTEXT Context)
468 {
469 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
470 STRING Header;
471 ULONG Flags, CacheFlags;
472
473 /* Setup the header */
474 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
475 Header.Buffer = (PCHAR)State;
476
477 /* Start with the default flags */
478 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL;
479
480 /* Get the caching flags and check if a type is specified */
481 CacheFlags = WriteMemory->ActualBytesWritten;
482 if (CacheFlags == DBGKD_CACHING_CACHED)
483 {
484 /* Cached */
485 Flags |= MMDBG_COPY_CACHED;
486 }
487 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
488 {
489 /* Uncached */
490 Flags |= MMDBG_COPY_UNCACHED;
491 }
492 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
493 {
494 /* Write Combined */
495 Flags |= DBGKD_CACHING_WRITE_COMBINED;
496 }
497
498 /* Do the write */
499 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
500 Data->Buffer,
501 Data->Length,
502 0,
503 Flags,
504 &WriteMemory->ActualBytesWritten);
505
506 /* Send the packet */
507 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
508 &Header,
509 NULL,
510 &KdpContext);
511 }
512
513 VOID
514 NTAPI
515 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
516 IN PSTRING Data,
517 IN PCONTEXT Context)
518 {
519 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
520 STRING Header;
521 ULONG Length;
522
523 /* Setup the header */
524 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
525 Header.Buffer = (PCHAR)State;
526 ASSERT(Data->Length == 0);
527
528 /* Check the length requested */
529 Length = ReadMemory->TransferCount;
530 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
531 {
532 /* Use maximum allowed */
533 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
534 }
535
536 /* Call the internal routine */
537 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
538 ReadMemory->TargetBaseAddress,
539 Data->Buffer,
540 Length,
541 &Length);
542
543 /* Return the actual length read */
544 Data->Length = ReadMemory->ActualBytesRead = Length;
545
546 /* Send the reply */
547 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
548 &Header,
549 Data,
550 &KdpContext);
551 }
552
553 VOID
554 NTAPI
555 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
556 IN PSTRING Data,
557 IN PCONTEXT Context)
558 {
559 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
560 STRING Header;
561
562 /* Setup the header */
563 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
564 Header.Buffer = (PCHAR)State;
565
566 /* Call the internal routine */
567 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
568 WriteMemory->TargetBaseAddress,
569 Data->Buffer,
570 Data->Length,
571 &WriteMemory->ActualBytesWritten);
572
573 /* Send the reply */
574 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
575 &Header,
576 Data,
577 &KdpContext);
578 }
579
580 VOID
581 NTAPI
582 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
583 IN PSTRING Data,
584 IN PCONTEXT Context)
585 {
586 STRING Header;
587 PVOID ControlStart;
588
589 /* Setup the header */
590 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
591 Header.Buffer = (PCHAR)State;
592 ASSERT(Data->Length == 0);
593
594 /* Make sure that this is a valid request */
595 if (State->Processor < KeNumberProcessors)
596 {
597 /* Check if the request is for this CPU */
598 if (State->Processor == KeGetCurrentPrcb()->Number)
599 {
600 /* We're just copying our own context */
601 ControlStart = Context;
602 }
603 else
604 {
605 /* SMP not yet handled */
606 KdpDprintf("KdpGetContext: SMP UNHANDLED\n");
607 ControlStart = NULL;
608 while (TRUE);
609 }
610
611 /* Copy the memory */
612 RtlCopyMemory(Data->Buffer, ControlStart, sizeof(CONTEXT));
613 Data->Length = sizeof(CONTEXT);
614
615 /* Finish up */
616 State->ReturnStatus = STATUS_SUCCESS;
617 }
618 else
619 {
620 /* Invalid request */
621 State->ReturnStatus = STATUS_UNSUCCESSFUL;
622 }
623
624 /* Send the reply */
625 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
626 &Header,
627 Data,
628 &KdpContext);
629 }
630
631 VOID
632 NTAPI
633 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
634 IN PSTRING Data,
635 IN PCONTEXT Context)
636 {
637 STRING Header;
638 PVOID ControlStart;
639
640 /* Setup the header */
641 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
642 Header.Buffer = (PCHAR)State;
643 ASSERT(Data->Length == sizeof(CONTEXT));
644
645 /* Make sure that this is a valid request */
646 if (State->Processor < KeNumberProcessors)
647 {
648 /* Check if the request is for this CPU */
649 if (State->Processor == KeGetCurrentPrcb()->Number)
650 {
651 /* We're just copying our own context */
652 ControlStart = Context;
653 }
654 else
655 {
656 /* SMP not yet handled */
657 KdpDprintf("KdpSetContext: SMP UNHANDLED\n");
658 ControlStart = NULL;
659 while (TRUE);
660 }
661
662 /* Copy the memory */
663 RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));
664
665 /* Finish up */
666 State->ReturnStatus = STATUS_SUCCESS;
667 }
668 else
669 {
670 /* Invalid request */
671 State->ReturnStatus = STATUS_UNSUCCESSFUL;
672 }
673
674 /* Send the reply */
675 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
676 &Header,
677 Data,
678 &KdpContext);
679 }
680
681 VOID
682 NTAPI
683 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
684 {
685 /* Crash with the special code */
686 KeBugCheck(MANUALLY_INITIATED_CRASH);
687 }
688
689 VOID
690 NTAPI
691 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
692 IN PSTRING Data,
693 IN PCONTEXT Context)
694 {
695 STRING Header;
696 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
697 LARGE_INTEGER MsrValue;
698
699 /* Setup the header */
700 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
701 Header.Buffer = (PCHAR)State;
702 ASSERT(Data->Length == 0);
703
704 /* Call the internal routine */
705 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr,
706 &MsrValue);
707
708 /* Return the data */
709 ReadMsr->DataValueLow = MsrValue.LowPart;
710 ReadMsr->DataValueHigh = MsrValue.HighPart;
711
712 /* Send the reply */
713 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
714 &Header,
715 NULL,
716 &KdpContext);
717 }
718
719 VOID
720 NTAPI
721 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
722 IN PSTRING Data,
723 IN PCONTEXT Context)
724 {
725 STRING Header;
726 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
727 LARGE_INTEGER MsrValue;
728
729 /* Setup the header */
730 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
731 Header.Buffer = (PCHAR)State;
732 ASSERT(Data->Length == 0);
733
734 /* Call the internal routine */
735 MsrValue.LowPart = WriteMsr->DataValueLow;
736 MsrValue.HighPart = WriteMsr->DataValueHigh;
737 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr,
738 &MsrValue);
739
740 /* Send the reply */
741 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
742 &Header,
743 NULL,
744 &KdpContext);
745 }
746
747 VOID
748 NTAPI
749 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
750 IN PSTRING Data,
751 IN PCONTEXT Context)
752 {
753 STRING Header;
754 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
755 ULONG Length;
756
757 /* Setup the header */
758 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
759 Header.Buffer = (PCHAR)State;
760 ASSERT(Data->Length == 0);
761
762 /* Check the length requested */
763 Length = GetBusData->Length;
764 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
765 {
766 /* Use maximum allowed */
767 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
768 }
769
770 /* Call the internal routine */
771 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
772 GetBusData->BusNumber,
773 GetBusData->SlotNumber,
774 GetBusData->Offset,
775 Data->Buffer,
776 Length,
777 &Length);
778
779 /* Return the actual length read */
780 Data->Length = GetBusData->Length = Length;
781
782 /* Send the reply */
783 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
784 &Header,
785 Data,
786 &KdpContext);
787 }
788
789 VOID
790 NTAPI
791 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
792 IN PSTRING Data,
793 IN PCONTEXT Context)
794 {
795 STRING Header;
796 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
797 ULONG Length;
798
799 /* Setup the header */
800 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
801 Header.Buffer = (PCHAR)State;
802
803 /* Call the internal routine */
804 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
805 SetBusData->BusNumber,
806 SetBusData->SlotNumber,
807 SetBusData->Offset,
808 Data->Buffer,
809 SetBusData->Length,
810 &Length);
811
812 /* Return the actual length written */
813 SetBusData->Length = Length;
814
815 /* Send the reply */
816 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
817 &Header,
818 Data,
819 &KdpContext);
820 }
821
822 VOID
823 NTAPI
824 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
825 IN PSTRING Data,
826 IN PCONTEXT Context)
827 {
828 STRING Header;
829 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
830
831 /* Setup the header */
832 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
833 Header.Buffer = (PCHAR)State;
834 ASSERT(Data->Length == 0);
835
836 /*
837 * Clear the value so 1 or 2 byte reads
838 * don't leave the higher bits unmodified
839 */
840 ReadIo->DataValue = 0;
841
842 /* Call the internal routine */
843 State->ReturnStatus = KdpSysReadIoSpace(Isa,
844 0,
845 1,
846 ReadIo->IoAddress,
847 &ReadIo->DataValue,
848 ReadIo->DataSize,
849 &ReadIo->DataSize);
850
851 /* Send the reply */
852 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
853 &Header,
854 NULL,
855 &KdpContext);
856 }
857
858 VOID
859 NTAPI
860 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
861 IN PSTRING Data,
862 IN PCONTEXT Context)
863 {
864 STRING Header;
865 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
866
867 /* Setup the header */
868 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
869 Header.Buffer = (PCHAR)State;
870 ASSERT(Data->Length == 0);
871
872 /* Call the internal routine */
873 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
874 0,
875 1,
876 WriteIo->IoAddress,
877 &WriteIo->DataValue,
878 WriteIo->DataSize,
879 &WriteIo->DataSize);
880
881 /* Send the reply */
882 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
883 &Header,
884 NULL,
885 &KdpContext);
886 }
887
888 VOID
889 NTAPI
890 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
891 IN PSTRING Data,
892 IN PCONTEXT Context)
893 {
894 STRING Header;
895 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
896 ReadWriteIoExtended;
897
898 /* Setup the header */
899 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
900 Header.Buffer = (PCHAR)State;
901 ASSERT(Data->Length == 0);
902
903 /*
904 * Clear the value so 1 or 2 byte reads
905 * don't leave the higher bits unmodified
906 */
907 ReadIoExtended->DataValue = 0;
908
909 /* Call the internal routine */
910 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
911 ReadIoExtended->BusNumber,
912 ReadIoExtended->AddressSpace,
913 ReadIoExtended->IoAddress,
914 &ReadIoExtended->DataValue,
915 ReadIoExtended->DataSize,
916 &ReadIoExtended->DataSize);
917
918 /* Send the reply */
919 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
920 &Header,
921 NULL,
922 &KdpContext);
923 }
924
925 VOID
926 NTAPI
927 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
928 IN PSTRING Data,
929 IN PCONTEXT Context)
930 {
931 STRING Header;
932 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
933 ReadWriteIoExtended;
934
935 /* Setup the header */
936 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
937 Header.Buffer = (PCHAR)State;
938 ASSERT(Data->Length == 0);
939
940 /* Call the internal routine */
941 State->ReturnStatus = KdpSysReadIoSpace(WriteIoExtended->InterfaceType,
942 WriteIoExtended->BusNumber,
943 WriteIoExtended->AddressSpace,
944 WriteIoExtended->IoAddress,
945 &WriteIoExtended->DataValue,
946 WriteIoExtended->DataSize,
947 &WriteIoExtended->DataSize);
948
949 /* Send the reply */
950 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
951 &Header,
952 NULL,
953 &KdpContext);
954 }
955
956 VOID
957 NTAPI
958 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
959 {
960 STRING Header;
961
962 /* Setup the header */
963 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
964 Header.Buffer = (PCHAR)State;
965
966 /* Call the internal routine */
967 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE);
968
969 /* Send the reply */
970 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
971 &Header,
972 NULL,
973 &KdpContext);
974 }
975
976 KCONTINUE_STATUS
977 NTAPI
978 KdpSendWaitContinue(IN ULONG PacketType,
979 IN PSTRING SendHeader,
980 IN PSTRING SendData OPTIONAL,
981 IN OUT PCONTEXT Context)
982 {
983 STRING Data, Header;
984 DBGKD_MANIPULATE_STATE64 ManipulateState;
985 ULONG Length;
986 KDSTATUS RecvCode;
987
988 /* Setup the Manipulate State structure */
989 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
990 Header.Buffer = (PCHAR)&ManipulateState;
991 Data.MaximumLength = sizeof(KdpMessageBuffer);
992 Data.Buffer = KdpMessageBuffer;
993 //KdpContextSent = FALSE;
994
995 SendPacket:
996 /* Send the Packet */
997 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
998
999 /* If the debugger isn't present anymore, just return success */
1000 if (KdDebuggerNotPresent) return ContinueSuccess;
1001
1002 /* Main processing Loop */
1003 for (;;)
1004 {
1005 /* Receive Loop */
1006 do
1007 {
1008 /* Wait to get a reply to our packet */
1009 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1010 &Header,
1011 &Data,
1012 &Length,
1013 &KdpContext);
1014
1015 /* If we got a resend request, do it */
1016 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
1017 } while (RecvCode == KdPacketTimedOut);
1018
1019 /* Now check what API we got */
1020 switch (ManipulateState.ApiNumber)
1021 {
1022 case DbgKdReadVirtualMemoryApi:
1023
1024 /* Read virtual memory */
1025 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
1026 break;
1027
1028 case DbgKdWriteVirtualMemoryApi:
1029
1030 /* Write virtual memory */
1031 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
1032 break;
1033
1034 case DbgKdGetContextApi:
1035
1036 /* Get the current context */
1037 KdpGetContext(&ManipulateState, &Data, Context);
1038 break;
1039
1040 case DbgKdSetContextApi:
1041
1042 /* Set a new context */
1043 KdpSetContext(&ManipulateState, &Data, Context);
1044 break;
1045
1046 case DbgKdWriteBreakPointApi:
1047
1048 /* Write the breakpoint */
1049 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
1050 break;
1051
1052 case DbgKdRestoreBreakPointApi:
1053
1054 /* Restore the breakpoint */
1055 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
1056 break;
1057
1058 case DbgKdContinueApi:
1059
1060 /* Simply continue */
1061 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
1062
1063 case DbgKdReadControlSpaceApi:
1064
1065 /* Read control space */
1066 KdpReadControlSpace(&ManipulateState, &Data, Context);
1067 break;
1068
1069 case DbgKdWriteControlSpaceApi:
1070
1071 /* Write control space */
1072 KdpWriteControlSpace(&ManipulateState, &Data, Context);
1073 break;
1074
1075 case DbgKdReadIoSpaceApi:
1076
1077 /* Read I/O Space */
1078 KdpReadIoSpace(&ManipulateState, &Data, Context);
1079 break;
1080
1081 case DbgKdWriteIoSpaceApi:
1082
1083 /* Write I/O Space */
1084 KdpWriteIoSpace(&ManipulateState, &Data, Context);
1085 break;
1086
1087 case DbgKdRebootApi:
1088
1089 /* Reboot the system */
1090 HalReturnToFirmware(HalRebootRoutine);
1091 break;
1092
1093 case DbgKdContinueApi2:
1094
1095 /* Check if caller reports success */
1096 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
1097 {
1098 /* Update the state */
1099 KdpGetStateChange(&ManipulateState, Context);
1100 return ContinueSuccess;
1101 }
1102 else
1103 {
1104 /* Return an error */
1105 return ContinueError;
1106 }
1107
1108 case DbgKdReadPhysicalMemoryApi:
1109
1110 /* Read physical memory */
1111 KdpReadPhysicalmemory(&ManipulateState, &Data, Context);
1112 break;
1113
1114 case DbgKdWritePhysicalMemoryApi:
1115
1116 /* Write physical memory */
1117 KdpWritePhysicalmemory(&ManipulateState, &Data, Context);
1118 break;
1119
1120 case DbgKdQuerySpecialCallsApi:
1121
1122 /* FIXME: TODO */
1123 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
1124 while (TRUE);
1125 break;
1126
1127 case DbgKdSetSpecialCallApi:
1128
1129 /* FIXME: TODO */
1130 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1131 while (TRUE);
1132 break;
1133
1134 case DbgKdClearSpecialCallsApi:
1135
1136 /* FIXME: TODO */
1137 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1138 while (TRUE);
1139 break;
1140
1141 case DbgKdSetInternalBreakPointApi:
1142
1143 /* FIXME: TODO */
1144 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1145 while (TRUE);
1146 break;
1147
1148 case DbgKdGetInternalBreakPointApi:
1149
1150 /* FIXME: TODO */
1151 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1152 while (TRUE);
1153 break;
1154
1155 case DbgKdReadIoSpaceExtendedApi:
1156
1157 /* Read I/O Space */
1158 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1159 break;
1160
1161 case DbgKdWriteIoSpaceExtendedApi:
1162
1163 /* Write I/O Space */
1164 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1165 break;
1166
1167 case DbgKdGetVersionApi:
1168
1169 /* Get version data */
1170 KdpGetVersion(&ManipulateState);
1171 break;
1172
1173 case DbgKdWriteBreakPointExApi:
1174
1175 /* Write the breakpoint and check if it failed */
1176 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1177 &Data,
1178 Context)))
1179 {
1180 /* Return an error */
1181 return ContinueError;
1182 }
1183 break;
1184
1185 case DbgKdRestoreBreakPointExApi:
1186
1187 /* Restore the breakpoint */
1188 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1189 break;
1190
1191 case DbgKdCauseBugCheckApi:
1192
1193 /* Crash the system */
1194 KdpCauseBugCheck(&ManipulateState);
1195 break;
1196
1197 case DbgKdSwitchProcessor:
1198
1199 /* FIXME: TODO */
1200 KdpDprintf("DbgKdSwitchProcessor called\n");
1201 while (TRUE);
1202 break;
1203
1204 case DbgKdPageInApi:
1205
1206 /* FIXME: TODO */
1207 KdpDprintf("DbgKdPageInApi called\n");
1208 while (TRUE);
1209 break;
1210
1211 case DbgKdReadMachineSpecificRegister:
1212
1213 /* Read from the specified MSR */
1214 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1215 break;
1216
1217 case DbgKdWriteMachineSpecificRegister:
1218
1219 /* Write to the specified MSR */
1220 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1221 break;
1222
1223 case DbgKdSearchMemoryApi:
1224
1225 /* Search memory */
1226 KdpSearchMemory(&ManipulateState, &Data, Context);
1227 break;
1228
1229 case DbgKdGetBusDataApi:
1230
1231 /* Read from the bus */
1232 KdpGetBusData(&ManipulateState, &Data, Context);
1233 break;
1234
1235 case DbgKdSetBusDataApi:
1236
1237 /* Write to the bus */
1238 KdpSetBusData(&ManipulateState, &Data, Context);
1239 break;
1240
1241 case DbgKdCheckLowMemoryApi:
1242
1243 /* Check for memory corruption in the lower 4 GB */
1244 KdpCheckLowMemory(&ManipulateState);
1245 break;
1246
1247 case DbgKdClearAllInternalBreakpointsApi:
1248
1249 /* Just clear the counter */
1250 KdpNumInternalBreakpoints = 0;
1251 break;
1252
1253 case DbgKdFillMemoryApi:
1254
1255 /* Fill memory */
1256 KdpFillMemory(&ManipulateState, &Data, Context);
1257 break;
1258
1259 case DbgKdQueryMemoryApi:
1260
1261 /* Query memory */
1262 KdpQueryMemory(&ManipulateState, Context);
1263 break;
1264
1265 case DbgKdSwitchPartition:
1266
1267 /* FIXME: TODO */
1268 KdpDprintf("DbgKdSwitchPartition called\n");
1269 while (TRUE);
1270 break;
1271
1272 /* Unsupported Message */
1273 default:
1274
1275 /* Setup an empty message, with failure */
1276 KdpDprintf("Received Unhandled API %lx\n", ManipulateState.ApiNumber);
1277 Data.Length = 0;
1278 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1279
1280 /* Send it */
1281 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1282 &Header,
1283 &Data,
1284 &KdpContext);
1285 break;
1286 }
1287 }
1288 }
1289
1290 BOOLEAN
1291 NTAPI
1292 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1293 IN PKD_SYMBOLS_INFO SymbolInfo,
1294 IN BOOLEAN Unload,
1295 IN OUT PCONTEXT Context)
1296 {
1297 PSTRING ExtraData;
1298 STRING Data, Header;
1299 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1300 KCONTINUE_STATUS Status;
1301
1302 /* Start wait loop */
1303 do
1304 {
1305 /* Build the architecture common parts of the message */
1306 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1307 Context,
1308 &WaitStateChange);
1309
1310 /* Now finish creating the structure */
1311 KdpSetContextState(&WaitStateChange, Context);
1312
1313 /* Fill out load data */
1314 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1315 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1316 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1317 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1318 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1319
1320 /* Check if we have a symbol name */
1321 if (PathName)
1322 {
1323 /* Setup the information */
1324 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
1325 RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);
1326 Data.Buffer = KdpPathBuffer;
1327 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
1328 ExtraData = &Data;
1329 }
1330 else
1331 {
1332 /* No name */
1333 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1334 ExtraData = NULL;
1335 }
1336
1337 /* Setup the header */
1338 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
1339 Header.Buffer = (PCHAR)&WaitStateChange;
1340
1341 /* Send the packet */
1342 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1343 &Header,
1344 ExtraData,
1345 Context);
1346 } while (Status == ContinueProcessorReselected);
1347
1348 /* Return status */
1349 return Status;
1350 }
1351
1352 BOOLEAN
1353 NTAPI
1354 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1355 IN OUT PCONTEXT Context,
1356 IN BOOLEAN SecondChanceException)
1357 {
1358 STRING Header, Data;
1359 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1360 KCONTINUE_STATUS Status;
1361
1362 /* Start report loop */
1363 do
1364 {
1365 /* Build the architecture common parts of the message */
1366 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1367
1368 /* Copy the Exception Record and set First Chance flag */
1369 CopyExceptionRecord(ExceptionRecord,
1370 &WaitStateChange.u.Exception.ExceptionRecord);
1371 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1372
1373 /* Now finish creating the structure */
1374 KdpSetContextState(&WaitStateChange, Context);
1375
1376 /* Setup the actual header to send to KD */
1377 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64) - sizeof(CONTEXT);
1378 Header.Buffer = (PCHAR)&WaitStateChange;
1379
1380 /* Setup the trace data */
1381 DumpTraceData(&Data);
1382
1383 /* Send State Change packet and wait for a reply */
1384 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1385 &Header,
1386 &Data,
1387 Context);
1388 } while (Status == ContinueProcessorReselected);
1389
1390 /* Return */
1391 return Status;
1392 }
1393
1394 VOID
1395 NTAPI
1396 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1397 IN PVOID DeferredContext,
1398 IN PVOID SystemArgument1,
1399 IN PVOID SystemArgument2)
1400 {
1401 LONG OldSlip, NewSlip, PendingSlip;
1402
1403 /* Get the current pending slip */
1404 PendingSlip = KdpTimeSlipPending;
1405 do
1406 {
1407 /* Save the old value and either disable or enable it now. */
1408 OldSlip = PendingSlip;
1409 NewSlip = OldSlip > 1 ? 1 : 0;
1410
1411 /* Try to change the value */
1412 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1413 NewSlip,
1414 OldSlip) != OldSlip);
1415
1416 /* If the New Slip value is 1, then do the Time Slipping */
1417 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1418 }
1419
1420 VOID
1421 NTAPI
1422 KdpTimeSlipWork(IN PVOID Context)
1423 {
1424 KIRQL OldIrql;
1425 LARGE_INTEGER DueTime;
1426
1427 /* Update the System time from the CMOS */
1428 ExAcquireTimeRefreshLock(FALSE);
1429 ExUpdateSystemTimeFromCmos(FALSE, 0);
1430 ExReleaseTimeRefreshLock();
1431
1432 /* Check if we have a registered Time Slip Event and signal it */
1433 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1434 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1435 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1436
1437 /* Delay the DPC until it runs next time */
1438 DueTime.QuadPart = -1800000000;
1439 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1440 }
1441
1442 BOOLEAN
1443 NTAPI
1444 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1445 IN OUT PCONTEXT ContextRecord,
1446 IN BOOLEAN SecondChanceException)
1447 {
1448 BOOLEAN Status;
1449
1450 /* Save the port data */
1451 KdSave(FALSE);
1452
1453 /* Report a state change */
1454 Status = KdpReportExceptionStateChange(ExceptionRecord,
1455 ContextRecord,
1456 SecondChanceException);
1457
1458 /* Restore the port data and return */
1459 KdRestore(FALSE);
1460 return Status;
1461 }
1462
1463 LARGE_INTEGER
1464 NTAPI
1465 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1466 {
1467 LARGE_INTEGER Null = {{0}};
1468
1469 /* Check if interrupts were disabled */
1470 if (!KeGetTrapFrameInterruptState(TrapFrame))
1471 {
1472 /* Nothing to return */
1473 return Null;
1474 }
1475
1476 /* Otherwise, do the call */
1477 return KeQueryPerformanceCounter(NULL);
1478 }
1479
1480 NTSTATUS
1481 NTAPI
1482 KdpAllowDisable(VOID)
1483 {
1484 /* Check if we are on MP */
1485 if (KeNumberProcessors > 1)
1486 {
1487 /* TODO */
1488 KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
1489 while (TRUE);
1490 }
1491
1492 /* Allow disable */
1493 return STATUS_SUCCESS;
1494 }
1495
1496 BOOLEAN
1497 NTAPI
1498 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1499 IN PKEXCEPTION_FRAME ExceptionFrame)
1500 {
1501 BOOLEAN Entered;
1502
1503 /* Check if we have a trap frame */
1504 if (TrapFrame)
1505 {
1506 /* Calculate the time difference for the enter */
1507 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1508 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1509 KdTimerStart.QuadPart;
1510 }
1511 else
1512 {
1513 /* No trap frame, so can't calculate */
1514 KdTimerStop.QuadPart = 0;
1515 }
1516
1517 /* Save the current IRQL */
1518 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1519
1520 /* Freeze all CPUs */
1521 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1522
1523 /* Lock the port, save the state and set debugger entered */
1524 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1525 KdSave(FALSE);
1526 KdEnteredDebugger = TRUE;
1527
1528 /* Check freeze flag */
1529 if (KiFreezeFlag & 1)
1530 {
1531 /* Print out errror */
1532 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1533 }
1534
1535 /* Check processor state */
1536 if (KiFreezeFlag & 2)
1537 {
1538 /* Print out errror */
1539 KdpDprintf("Some processors not frozen in debugger!\n");
1540 }
1541
1542 /* Make sure we acquired the port */
1543 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1544
1545 /* Return enter state */
1546 return Entered;
1547 }
1548
1549 VOID
1550 NTAPI
1551 KdExitDebugger(IN BOOLEAN Entered)
1552 {
1553 ULONG TimeSlip;
1554
1555 /* Restore the state and unlock the port */
1556 KdRestore(FALSE);
1557 if (KdpPortLocked) KdpPortUnlock();
1558
1559 /* Unfreeze the CPUs */
1560 KeThawExecution(Entered);
1561
1562 /* Compare time with the one from KdEnterDebugger */
1563 if (!KdTimerStop.QuadPart)
1564 {
1565 /* We didn't get a trap frame earlier in so never got the time */
1566 KdTimerStart = KdTimerStop;
1567 }
1568 else
1569 {
1570 /* Query the timer */
1571 KdTimerStart = KeQueryPerformanceCounter(NULL);
1572 }
1573
1574 /* Check if a Time Slip was on queue */
1575 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1576 if (TimeSlip == 1)
1577 {
1578 /* Queue a DPC for the time slip */
1579 InterlockedIncrement(&KdpTimeSlipPending);
1580 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1581 }
1582 }
1583
1584 NTSTATUS
1585 NTAPI
1586 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1587 {
1588 KIRQL OldIrql;
1589
1590 #if defined(__GNUC__)
1591 /* Make gcc happy */
1592 OldIrql = PASSIVE_LEVEL;
1593 #endif
1594
1595 /* Check if enabling the debugger is blocked */
1596 if (KdBlockEnable)
1597 {
1598 /* It is, fail the enable */
1599 return STATUS_ACCESS_DENIED;
1600 }
1601
1602 /* Check if we need to acquire the lock */
1603 if (NeedLock)
1604 {
1605 /* Lock the port */
1606 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1607 KdpPortLock();
1608 }
1609
1610 /* Check if we're not disabled */
1611 if (!KdDisableCount)
1612 {
1613 /* Check if we had locked the port before */
1614 if (NeedLock)
1615 {
1616 /* Do the unlock */
1617 KeLowerIrql(OldIrql);
1618 KdpPortUnlock();
1619
1620 /* Fail: We're already enabled */
1621 return STATUS_INVALID_PARAMETER;
1622 }
1623 else
1624 {
1625 /*
1626 * This can only happen if we are called from a bugcheck
1627 * and were never initialized, so initialize the debugger now.
1628 */
1629 KdInitSystem(0, NULL);
1630
1631 /* Return success since we initialized */
1632 return STATUS_SUCCESS;
1633 }
1634 }
1635
1636 /* Decrease the disable count */
1637 if (!(--KdDisableCount))
1638 {
1639 /* We're now enabled again! Were we enabled before, too? */
1640 if (KdPreviouslyEnabled)
1641 {
1642 /* Reinitialize the Debugger */
1643 KdInitSystem(0, NULL) ;
1644 KdpRestoreAllBreakpoints();
1645 }
1646 }
1647
1648 /* Check if we had locked the port before */
1649 if (NeedLock)
1650 {
1651 /* Yes, now unlock it */
1652 KeLowerIrql(OldIrql);
1653 KdpPortUnlock();
1654 }
1655
1656 /* We're done */
1657 return STATUS_SUCCESS;
1658 }
1659
1660 NTSTATUS
1661 NTAPI
1662 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
1663 {
1664 KIRQL OldIrql;
1665 NTSTATUS Status;
1666
1667 #if defined(__GNUC__)
1668 /* Make gcc happy */
1669 OldIrql = PASSIVE_LEVEL;
1670 #endif
1671
1672 /*
1673 * If enabling the debugger is blocked
1674 * then there is nothing to disable (duh)
1675 */
1676 if (KdBlockEnable)
1677 {
1678 /* Fail */
1679 return STATUS_ACCESS_DENIED;
1680 }
1681
1682 /* Check if we need to acquire the lock */
1683 if (NeedLock)
1684 {
1685 /* Lock the port */
1686 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1687 KdpPortLock();
1688 }
1689
1690 /* Check if we're not disabled */
1691 if (!KdDisableCount)
1692 {
1693 /* Check if the debugger was never actually initialized */
1694 if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
1695 {
1696 /* It wasn't, so don't re-enable it later */
1697 KdPreviouslyEnabled = FALSE;
1698 }
1699 else
1700 {
1701 /* It was, so we will re-enable it later */
1702 KdPreviouslyEnabled = TRUE;
1703 }
1704
1705 /* Check if we were called from the exported API and are enabled */
1706 if ((NeedLock) && (KdPreviouslyEnabled))
1707 {
1708 /* Check if it is safe to disable the debugger */
1709 Status = KdpAllowDisable();
1710 if (!NT_SUCCESS(Status))
1711 {
1712 /* Release the lock and fail */
1713 KeLowerIrql(OldIrql);
1714 KdpPortUnlock();
1715 return Status;
1716 }
1717 }
1718
1719 /* Only disable the debugger if it is enabled */
1720 if (KdDebuggerEnabled)
1721 {
1722 /*
1723 * Disable the debugger; suspend breakpoints
1724 * and reset the debug stub
1725 */
1726 KdpSuspendAllBreakPoints();
1727 KiDebugRoutine = KdpStub;
1728
1729 /* We are disabled now */
1730 KdDebuggerEnabled = FALSE;
1731 #undef KdDebuggerEnabled
1732 SharedUserData->KdDebuggerEnabled = FALSE;
1733 #define KdDebuggerEnabled _KdDebuggerEnabled
1734 }
1735 }
1736
1737 /* Increment the disable count */
1738 KdDisableCount++;
1739
1740 /* Check if we had locked the port before */
1741 if (NeedLock)
1742 {
1743 /* Yes, now unlock it */
1744 KeLowerIrql(OldIrql);
1745 KdpPortUnlock();
1746 }
1747
1748 /* We're done */
1749 return STATUS_SUCCESS;
1750 }
1751
1752 /* PUBLIC FUNCTIONS **********************************************************/
1753
1754 /*
1755 * @implemented
1756 */
1757 NTSTATUS
1758 NTAPI
1759 KdEnableDebugger(VOID)
1760 {
1761 /* Use the internal routine */
1762 return KdEnableDebuggerWithLock(TRUE);
1763 }
1764
1765 /*
1766 * @implemented
1767 */
1768 NTSTATUS
1769 NTAPI
1770 KdDisableDebugger(VOID)
1771 {
1772 /* Use the internal routine */
1773 return KdDisableDebuggerWithLock(TRUE);
1774 }
1775
1776 /*
1777 * @unimplemented
1778 */
1779 NTSTATUS
1780 NTAPI
1781 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1782 IN PVOID InputBuffer,
1783 IN ULONG InputBufferLength,
1784 OUT PVOID OutputBuffer,
1785 IN ULONG OutputBufferLength,
1786 IN OUT PULONG ReturnLength,
1787 IN KPROCESSOR_MODE PreviousMode)
1788 {
1789 /* HACK */
1790 return STATUS_SUCCESS;
1791 }
1792
1793 /*
1794 * @unimplemented
1795 */
1796 NTSTATUS
1797 NTAPI
1798 KdChangeOption(IN KD_OPTION Option,
1799 IN ULONG InBufferBytes OPTIONAL,
1800 IN PVOID InBuffer,
1801 IN ULONG OutBufferBytes OPTIONAL,
1802 OUT PVOID OutBuffer,
1803 OUT PULONG OutBufferNeeded OPTIONAL)
1804 {
1805 /* HACK */
1806 return STATUS_SUCCESS;
1807 }
1808
1809 /*
1810 * @unimplemented
1811 */
1812 NTSTATUS
1813 NTAPI
1814 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1815 {
1816 /* HACK */
1817 return STATUS_SUCCESS;
1818 }
1819
1820 /*
1821 * @unimplemented
1822 */
1823 BOOLEAN
1824 NTAPI
1825 KdRefreshDebuggerNotPresent(VOID)
1826 {
1827 /* HACK */
1828 return KdDebuggerNotPresent;
1829 }
1830
1831 NTSTATUS
1832 NTAPI
1833 NtQueryDebugFilterState(ULONG ComponentId,
1834 ULONG Level)
1835 {
1836 /* HACK */
1837 return STATUS_SUCCESS;
1838 }
1839
1840 NTSTATUS
1841 NTAPI
1842 NtSetDebugFilterState(ULONG ComponentId,
1843 ULONG Level,
1844 BOOLEAN State)
1845 {
1846 /* HACK */
1847 return STATUS_SUCCESS;
1848 }