6efa5f3f03ca1de9c39cb79641493f5afd9ec869
[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_ANY_WAIT_STATE_CHANGE 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 entire Control Report */
284 RtlZeroMemory(&WaitStateChange->AnyControlReport,
285 sizeof(DBGKD_ANY_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_ANY_WAIT_STATE_CHANGE 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_ANY_WAIT_STATE_CHANGE);
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_ANY_WAIT_STATE_CHANGE 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 #if !defined(_WIN64)
1370 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
1371 &WaitStateChange.u.Exception.ExceptionRecord);
1372 #else
1373 RtlCopyMemory(&WaitStateChange.u.Exception.ExceptionRecord,
1374 ExceptionRecord,
1375 sizeof(EXCEPTION_RECORD));
1376 #endif
1377 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1378
1379 /* Now finish creating the structure */
1380 KdpSetContextState(&WaitStateChange, Context);
1381
1382 /* Setup the actual header to send to KD */
1383 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1384 Header.Buffer = (PCHAR)&WaitStateChange;
1385
1386 /* Setup the trace data */
1387 DumpTraceData(&Data);
1388
1389 /* Send State Change packet and wait for a reply */
1390 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1391 &Header,
1392 &Data,
1393 Context);
1394 } while (Status == ContinueProcessorReselected);
1395
1396 /* Return */
1397 return Status;
1398 }
1399
1400 VOID
1401 NTAPI
1402 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1403 IN PVOID DeferredContext,
1404 IN PVOID SystemArgument1,
1405 IN PVOID SystemArgument2)
1406 {
1407 LONG OldSlip, NewSlip, PendingSlip;
1408
1409 /* Get the current pending slip */
1410 PendingSlip = KdpTimeSlipPending;
1411 do
1412 {
1413 /* Save the old value and either disable or enable it now. */
1414 OldSlip = PendingSlip;
1415 NewSlip = OldSlip > 1 ? 1 : 0;
1416
1417 /* Try to change the value */
1418 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1419 NewSlip,
1420 OldSlip) != OldSlip);
1421
1422 /* If the New Slip value is 1, then do the Time Slipping */
1423 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1424 }
1425
1426 VOID
1427 NTAPI
1428 KdpTimeSlipWork(IN PVOID Context)
1429 {
1430 KIRQL OldIrql;
1431 LARGE_INTEGER DueTime;
1432
1433 /* Update the System time from the CMOS */
1434 ExAcquireTimeRefreshLock(FALSE);
1435 ExUpdateSystemTimeFromCmos(FALSE, 0);
1436 ExReleaseTimeRefreshLock();
1437
1438 /* Check if we have a registered Time Slip Event and signal it */
1439 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1440 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1441 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1442
1443 /* Delay the DPC until it runs next time */
1444 DueTime.QuadPart = -1800000000;
1445 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1446 }
1447
1448 BOOLEAN
1449 NTAPI
1450 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1451 IN OUT PCONTEXT ContextRecord,
1452 IN BOOLEAN SecondChanceException)
1453 {
1454 BOOLEAN Status;
1455
1456 /* Save the port data */
1457 KdSave(FALSE);
1458
1459 /* Report a state change */
1460 Status = KdpReportExceptionStateChange(ExceptionRecord,
1461 ContextRecord,
1462 SecondChanceException);
1463
1464 /* Restore the port data and return */
1465 KdRestore(FALSE);
1466 return Status;
1467 }
1468
1469 LARGE_INTEGER
1470 NTAPI
1471 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1472 {
1473 LARGE_INTEGER Null = {{0}};
1474
1475 /* Check if interrupts were disabled */
1476 if (!KeGetTrapFrameInterruptState(TrapFrame))
1477 {
1478 /* Nothing to return */
1479 return Null;
1480 }
1481
1482 /* Otherwise, do the call */
1483 return KeQueryPerformanceCounter(NULL);
1484 }
1485
1486 NTSTATUS
1487 NTAPI
1488 KdpAllowDisable(VOID)
1489 {
1490 /* Check if we are on MP */
1491 if (KeNumberProcessors > 1)
1492 {
1493 /* TODO */
1494 KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
1495 while (TRUE);
1496 }
1497
1498 /* Allow disable */
1499 return STATUS_SUCCESS;
1500 }
1501
1502 BOOLEAN
1503 NTAPI
1504 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1505 IN PKEXCEPTION_FRAME ExceptionFrame)
1506 {
1507 BOOLEAN Entered;
1508
1509 /* Check if we have a trap frame */
1510 if (TrapFrame)
1511 {
1512 /* Calculate the time difference for the enter */
1513 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1514 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1515 KdTimerStart.QuadPart;
1516 }
1517 else
1518 {
1519 /* No trap frame, so can't calculate */
1520 KdTimerStop.QuadPart = 0;
1521 }
1522
1523 /* Save the current IRQL */
1524 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1525
1526 /* Freeze all CPUs */
1527 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1528
1529 /* Lock the port, save the state and set debugger entered */
1530 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1531 KdSave(FALSE);
1532 KdEnteredDebugger = TRUE;
1533
1534 /* Check freeze flag */
1535 if (KiFreezeFlag & 1)
1536 {
1537 /* Print out errror */
1538 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1539 }
1540
1541 /* Check processor state */
1542 if (KiFreezeFlag & 2)
1543 {
1544 /* Print out errror */
1545 KdpDprintf("Some processors not frozen in debugger!\n");
1546 }
1547
1548 /* Make sure we acquired the port */
1549 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1550
1551 /* Return enter state */
1552 return Entered;
1553 }
1554
1555 VOID
1556 NTAPI
1557 KdExitDebugger(IN BOOLEAN Entered)
1558 {
1559 ULONG TimeSlip;
1560
1561 /* Restore the state and unlock the port */
1562 KdRestore(FALSE);
1563 if (KdpPortLocked) KdpPortUnlock();
1564
1565 /* Unfreeze the CPUs */
1566 KeThawExecution(Entered);
1567
1568 /* Compare time with the one from KdEnterDebugger */
1569 if (!KdTimerStop.QuadPart)
1570 {
1571 /* We didn't get a trap frame earlier in so never got the time */
1572 KdTimerStart = KdTimerStop;
1573 }
1574 else
1575 {
1576 /* Query the timer */
1577 KdTimerStart = KeQueryPerformanceCounter(NULL);
1578 }
1579
1580 /* Check if a Time Slip was on queue */
1581 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1582 if (TimeSlip == 1)
1583 {
1584 /* Queue a DPC for the time slip */
1585 InterlockedIncrement(&KdpTimeSlipPending);
1586 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1587 }
1588 }
1589
1590 NTSTATUS
1591 NTAPI
1592 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1593 {
1594 KIRQL OldIrql;
1595
1596 #if defined(__GNUC__)
1597 /* Make gcc happy */
1598 OldIrql = PASSIVE_LEVEL;
1599 #endif
1600
1601 /* Check if enabling the debugger is blocked */
1602 if (KdBlockEnable)
1603 {
1604 /* It is, fail the enable */
1605 return STATUS_ACCESS_DENIED;
1606 }
1607
1608 /* Check if we need to acquire the lock */
1609 if (NeedLock)
1610 {
1611 /* Lock the port */
1612 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1613 KdpPortLock();
1614 }
1615
1616 /* Check if we're not disabled */
1617 if (!KdDisableCount)
1618 {
1619 /* Check if we had locked the port before */
1620 if (NeedLock)
1621 {
1622 /* Do the unlock */
1623 KeLowerIrql(OldIrql);
1624 KdpPortUnlock();
1625
1626 /* Fail: We're already enabled */
1627 return STATUS_INVALID_PARAMETER;
1628 }
1629 else
1630 {
1631 /*
1632 * This can only happen if we are called from a bugcheck
1633 * and were never initialized, so initialize the debugger now.
1634 */
1635 KdInitSystem(0, NULL);
1636
1637 /* Return success since we initialized */
1638 return STATUS_SUCCESS;
1639 }
1640 }
1641
1642 /* Decrease the disable count */
1643 if (!(--KdDisableCount))
1644 {
1645 /* We're now enabled again! Were we enabled before, too? */
1646 if (KdPreviouslyEnabled)
1647 {
1648 /* Reinitialize the Debugger */
1649 KdInitSystem(0, NULL) ;
1650 KdpRestoreAllBreakpoints();
1651 }
1652 }
1653
1654 /* Check if we had locked the port before */
1655 if (NeedLock)
1656 {
1657 /* Yes, now unlock it */
1658 KeLowerIrql(OldIrql);
1659 KdpPortUnlock();
1660 }
1661
1662 /* We're done */
1663 return STATUS_SUCCESS;
1664 }
1665
1666 NTSTATUS
1667 NTAPI
1668 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
1669 {
1670 KIRQL OldIrql;
1671 NTSTATUS Status;
1672
1673 #if defined(__GNUC__)
1674 /* Make gcc happy */
1675 OldIrql = PASSIVE_LEVEL;
1676 #endif
1677
1678 /*
1679 * If enabling the debugger is blocked
1680 * then there is nothing to disable (duh)
1681 */
1682 if (KdBlockEnable)
1683 {
1684 /* Fail */
1685 return STATUS_ACCESS_DENIED;
1686 }
1687
1688 /* Check if we need to acquire the lock */
1689 if (NeedLock)
1690 {
1691 /* Lock the port */
1692 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1693 KdpPortLock();
1694 }
1695
1696 /* Check if we're not disabled */
1697 if (!KdDisableCount)
1698 {
1699 /* Check if the debugger was never actually initialized */
1700 if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
1701 {
1702 /* It wasn't, so don't re-enable it later */
1703 KdPreviouslyEnabled = FALSE;
1704 }
1705 else
1706 {
1707 /* It was, so we will re-enable it later */
1708 KdPreviouslyEnabled = TRUE;
1709 }
1710
1711 /* Check if we were called from the exported API and are enabled */
1712 if ((NeedLock) && (KdPreviouslyEnabled))
1713 {
1714 /* Check if it is safe to disable the debugger */
1715 Status = KdpAllowDisable();
1716 if (!NT_SUCCESS(Status))
1717 {
1718 /* Release the lock and fail */
1719 KeLowerIrql(OldIrql);
1720 KdpPortUnlock();
1721 return Status;
1722 }
1723 }
1724
1725 /* Only disable the debugger if it is enabled */
1726 if (KdDebuggerEnabled)
1727 {
1728 /*
1729 * Disable the debugger; suspend breakpoints
1730 * and reset the debug stub
1731 */
1732 KdpSuspendAllBreakPoints();
1733 KiDebugRoutine = KdpStub;
1734
1735 /* We are disabled now */
1736 KdDebuggerEnabled = FALSE;
1737 #undef KdDebuggerEnabled
1738 SharedUserData->KdDebuggerEnabled = FALSE;
1739 #define KdDebuggerEnabled _KdDebuggerEnabled
1740 }
1741 }
1742
1743 /* Increment the disable count */
1744 KdDisableCount++;
1745
1746 /* Check if we had locked the port before */
1747 if (NeedLock)
1748 {
1749 /* Yes, now unlock it */
1750 KeLowerIrql(OldIrql);
1751 KdpPortUnlock();
1752 }
1753
1754 /* We're done */
1755 return STATUS_SUCCESS;
1756 }
1757
1758 /* PUBLIC FUNCTIONS **********************************************************/
1759
1760 /*
1761 * @implemented
1762 */
1763 NTSTATUS
1764 NTAPI
1765 KdEnableDebugger(VOID)
1766 {
1767 /* Use the internal routine */
1768 return KdEnableDebuggerWithLock(TRUE);
1769 }
1770
1771 /*
1772 * @implemented
1773 */
1774 NTSTATUS
1775 NTAPI
1776 KdDisableDebugger(VOID)
1777 {
1778 /* Use the internal routine */
1779 return KdDisableDebuggerWithLock(TRUE);
1780 }
1781
1782 /*
1783 * @unimplemented
1784 */
1785 NTSTATUS
1786 NTAPI
1787 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1788 IN PVOID InputBuffer,
1789 IN ULONG InputBufferLength,
1790 OUT PVOID OutputBuffer,
1791 IN ULONG OutputBufferLength,
1792 IN OUT PULONG ReturnLength,
1793 IN KPROCESSOR_MODE PreviousMode)
1794 {
1795 /* HACK */
1796 return STATUS_SUCCESS;
1797 }
1798
1799 /*
1800 * @unimplemented
1801 */
1802 NTSTATUS
1803 NTAPI
1804 KdChangeOption(IN KD_OPTION Option,
1805 IN ULONG InBufferBytes OPTIONAL,
1806 IN PVOID InBuffer,
1807 IN ULONG OutBufferBytes OPTIONAL,
1808 OUT PVOID OutBuffer,
1809 OUT PULONG OutBufferNeeded OPTIONAL)
1810 {
1811 /* HACK */
1812 return STATUS_SUCCESS;
1813 }
1814
1815 /*
1816 * @unimplemented
1817 */
1818 NTSTATUS
1819 NTAPI
1820 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1821 {
1822 /* HACK */
1823 return STATUS_SUCCESS;
1824 }
1825
1826 /*
1827 * @unimplemented
1828 */
1829 BOOLEAN
1830 NTAPI
1831 KdRefreshDebuggerNotPresent(VOID)
1832 {
1833 /* HACK */
1834 return KdDebuggerNotPresent;
1835 }
1836
1837 /*
1838 * @unimplemented
1839 */
1840 NTSTATUS
1841 NTAPI
1842 NtQueryDebugFilterState(IN ULONG ComponentId,
1843 IN ULONG Level)
1844 {
1845 /* HACK */
1846 return STATUS_SUCCESS;
1847 }
1848
1849 /*
1850 * @unimplemented
1851 */
1852 NTSTATUS
1853 NTAPI
1854 NtSetDebugFilterState(IN ULONG ComponentId,
1855 IN ULONG Level,
1856 IN BOOLEAN State)
1857 {
1858 /* HACK */
1859 return STATUS_SUCCESS;
1860 }