329fec5de5490955eb883ba9efb43ddd136adf9e
[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 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* PRIVATE FUNCTIONS *********************************************************/
17
18 NTSTATUS
19 NTAPI
20 KdpCopyMemoryChunks(IN ULONG64 Address,
21 IN PVOID Buffer,
22 IN ULONG TotalSize,
23 IN ULONG ChunkSize,
24 IN ULONG Flags,
25 OUT PULONG ActualSize OPTIONAL)
26 {
27 ULONG Length;
28 NTSTATUS Status;
29
30 /* Check if this is physical or virtual copy */
31 if (Flags & MMDBG_COPY_PHYSICAL)
32 {
33 /* Fail physical memory read/write for now */
34 if (Flags & MMDBG_COPY_WRITE)
35 {
36 KdpDprintf("KdpCopyMemoryChunks: Failing write for Physical Address 0x%I64x Length: %x\n",
37 Address,
38 TotalSize);
39 }
40 else
41 {
42 KdpDprintf("KdpCopyMemoryChunks: Failing read for Physical Address 0x%I64x Length: %x\n",
43 Address,
44 TotalSize);
45 }
46
47 /* Return an error */
48 Length = 0;
49 Status = STATUS_UNSUCCESSFUL;
50 }
51 else
52 {
53 /* Protect against NULL */
54 if (!Address)
55 {
56 if (ActualSize) *ActualSize = 0;
57 return STATUS_UNSUCCESSFUL;
58 }
59
60 /* Check if this is read or write */
61 if (Flags & MMDBG_COPY_WRITE)
62 {
63 /* Do the write */
64 RtlCopyMemory((PVOID)(ULONG_PTR)Address,
65 Buffer,
66 TotalSize);
67 }
68 else
69 {
70 /* Do the read */
71 RtlCopyMemory(Buffer,
72 (PVOID)(ULONG_PTR)Address,
73 TotalSize);
74 }
75
76 /* Set size and status */
77 Length = TotalSize;
78 Status = STATUS_SUCCESS;
79 }
80
81 /* Return the actual length if requested */
82 if (ActualSize) *ActualSize = Length;
83
84 /* Return status */
85 return Status;
86 }
87
88 VOID
89 NTAPI
90 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
91 IN PCONTEXT Context)
92 {
93 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
94 STRING Header;
95 NTSTATUS Status = STATUS_SUCCESS;
96
97 /* Validate the address space */
98 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
99 {
100 /* Check if this is process memory */
101 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
102 {
103 /* It is */
104 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
105 }
106 else
107 {
108 /* FIXME: Check if it's session space */
109 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
110 }
111
112 /* Set flags */
113 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
114 DBGKD_QUERY_MEMORY_WRITE |
115 DBGKD_QUERY_MEMORY_EXECUTE;
116 }
117 else
118 {
119 /* Invalid */
120 Status = STATUS_INVALID_PARAMETER;
121 }
122
123 /* Return structure */
124 State->ReturnStatus = Status;
125 Memory->Reserved = 0;
126
127 /* Build header */
128 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
129 Header.Buffer = (PCHAR)State;
130
131 /* Send the packet */
132 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
133 &Header,
134 NULL,
135 &KdpContext);
136 }
137
138 VOID
139 NTAPI
140 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
141 IN PSTRING Data,
142 IN PCONTEXT Context)
143 {
144 /* FIXME: STUB */
145 KdpDprintf("KdpSearchMemory called\n");
146 while (TRUE);
147 }
148
149 VOID
150 NTAPI
151 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
152 IN PSTRING Data,
153 IN PCONTEXT Context)
154 {
155 /* FIXME: STUB */
156 KdpDprintf("KdpFillMemory called\n");
157 while (TRUE);
158 }
159
160 VOID
161 NTAPI
162 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
163 IN PSTRING Data,
164 IN PCONTEXT Context)
165 {
166 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
167 STRING Header;
168
169 /* Build header */
170 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
171 Header.Buffer = (PCHAR)State;
172 ASSERT(Data->Length == 0);
173
174 /* Create the breakpoint */
175 Breakpoint->BreakPointHandle =
176 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
177 if (!Breakpoint->BreakPointHandle)
178 {
179 /* We failed */
180 State->ReturnStatus = STATUS_UNSUCCESSFUL;
181 }
182 else
183 {
184 /* Success! */
185 State->ReturnStatus = STATUS_SUCCESS;
186 }
187
188 /* Send the packet */
189 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
190 &Header,
191 NULL,
192 &KdpContext);
193 }
194
195 VOID
196 NTAPI
197 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
198 IN PSTRING Data,
199 IN PCONTEXT Context)
200 {
201 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
202 STRING Header;
203
204 /* Fill out the header */
205 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
206 Header.Buffer = (PCHAR)State;
207 ASSERT(Data->Length == 0);
208
209 /* Get the version block */
210 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
211 {
212 /* We're all good */
213 State->ReturnStatus = STATUS_SUCCESS;
214 }
215 else
216 {
217 /* We failed */
218 State->ReturnStatus = STATUS_UNSUCCESSFUL;
219 }
220
221 /* Send the packet */
222 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
223 &Header,
224 NULL,
225 &KdpContext);
226 }
227
228 NTSTATUS
229 NTAPI
230 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
231 IN PSTRING Data,
232 IN PCONTEXT Context)
233 {
234 /* FIXME: STUB */
235 KdpDprintf("KdpWriteBreakPointEx called\n");
236 while (TRUE);
237 return STATUS_UNSUCCESSFUL;
238 }
239
240 VOID
241 NTAPI
242 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
243 IN PSTRING Data,
244 IN PCONTEXT Context)
245 {
246 /* FIXME: STUB */
247 KdpDprintf("KdpRestoreBreakPointEx called\n");
248 while (TRUE);
249 }
250
251 VOID
252 NTAPI
253 DumpTraceData(IN PSTRING TraceData)
254 {
255 /* Update the buffer */
256 TraceDataBuffer[0] = TraceDataBufferPosition;
257
258 /* Setup the trace data */
259 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
260 TraceData->Buffer = (PCHAR)TraceDataBuffer;
261
262 /* Reset the buffer location */
263 TraceDataBufferPosition = 1;
264 }
265
266 VOID
267 NTAPI
268 KdpSetCommonState(IN ULONG NewState,
269 IN PCONTEXT Context,
270 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
271 {
272 USHORT InstructionCount;
273 BOOLEAN HadBreakpoints;
274
275 /* Setup common stuff available for all CPU architectures */
276 WaitStateChange->NewState = NewState;
277 WaitStateChange->ProcessorLevel = KeProcessorLevel;
278 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
279 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
280 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
281 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
282
283 /* Zero out the Control Report */
284 RtlZeroMemory(&WaitStateChange->ControlReport,
285 sizeof(DBGKD_CONTROL_REPORT));
286
287 /* Now copy the instruction stream and set the count */
288 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
289 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
290 DBGKD_MAXSTREAM);
291 InstructionCount = DBGKD_MAXSTREAM;
292 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
293
294 /* Clear all the breakpoints in this region */
295 HadBreakpoints =
296 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
297 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
298 WaitStateChange->ControlReport.InstructionCount - 1));
299 if (HadBreakpoints)
300 {
301 /* Copy the instruction stream again, this time without breakpoints */
302 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
303 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
304 WaitStateChange->ControlReport.InstructionCount);
305 }
306 }
307
308 VOID
309 NTAPI
310 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
311 {
312 STRING Header;
313
314 /* Fill out the header */
315 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
316 Header.Buffer = (PCHAR)State;
317
318 /* Get the version block */
319 KdpSysGetVersion(&State->u.GetVersion64);
320
321 /* Fill out the state */
322 State->ApiNumber = DbgKdGetVersionApi;
323 State->ReturnStatus = STATUS_SUCCESS;
324
325 /* Send the packet */
326 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
327 &Header,
328 NULL,
329 &KdpContext);
330 }
331
332 VOID
333 NTAPI
334 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
335 IN PSTRING Data,
336 IN PCONTEXT Context)
337 {
338 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
339 STRING Header;
340 ULONG Length = ReadMemory->TransferCount;
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);
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 }