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