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