- Add a bunch of hacks to KdpReadVirtualMemory to make it work for now.
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdapi.c
5 * PURPOSE: KD64 Public Routines and Internal Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 VOID
18 NTAPI
19 KdpSetCommonState(IN ULONG NewState,
20 IN PCONTEXT Context,
21 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
22 {
23 USHORT InstructionCount;
24 BOOLEAN HadBreakpoints;
25
26 /* Setup common stuff available for all CPU architectures */
27 WaitStateChange->NewState = NewState;
28 WaitStateChange->ProcessorLevel = KeProcessorLevel;
29 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
30 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
31 WaitStateChange->Thread = (ULONG)KeGetCurrentThread();
32 WaitStateChange->ProgramCounter = (ULONG64)Context->Eip;
33
34 /* Zero out the Control Report */
35 RtlZeroMemory(&WaitStateChange->ControlReport,
36 sizeof(DBGKD_CONTROL_REPORT));
37
38 /* Now copy the instruction stream and set the count */
39 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
40 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
41 DBGKD_MAXSTREAM);
42 InstructionCount = DBGKD_MAXSTREAM;
43 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
44
45 /* Clear all the breakpoints in this region */
46 HadBreakpoints = FALSE;
47 #if 0
48 KdpDeleteBreakpointRange((PVOID)WaitStateChange->ProgramCounter,
49 (PVOID)(WaitStateChange->ProgramCounter +
50 WaitStateChange->ControlReport.
51 InstructionCount - 1));
52 #endif
53 if (HadBreakpoints)
54 {
55 /* Copy the instruction stream again, this time without breakpoints */
56 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
57 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
58 WaitStateChange->ControlReport.InstructionCount);
59 }
60 }
61
62 VOID
63 NTAPI
64 KdpSetContextState(IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange,
65 IN PCONTEXT Context)
66 {
67 PKPRCB Prcb = KeGetCurrentPrcb();
68
69 /* Copy i386 specific debug registers */
70 WaitStateChange->ControlReport.Dr6 = Prcb->ProcessorState.SpecialRegisters.
71 KernelDr6;
72 WaitStateChange->ControlReport.Dr7 = Prcb->ProcessorState.SpecialRegisters.
73 KernelDr7;
74
75 /* Copy i386 specific segments */
76 WaitStateChange->ControlReport.SegCs = (USHORT)Context->SegCs;
77 WaitStateChange->ControlReport.SegDs = (USHORT)Context->SegDs;
78 WaitStateChange->ControlReport.SegEs = (USHORT)Context->SegEs;
79 WaitStateChange->ControlReport.SegFs = (USHORT)Context->SegFs;
80
81 /* Copy EFlags */
82 WaitStateChange->ControlReport.EFlags = Context->EFlags;
83
84 /* Set Report Flags */
85 WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS;
86 if (WaitStateChange->ControlReport.SegCs == KGDT_R0_CODE)
87 {
88 WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_CS;
89 }
90 }
91
92 VOID
93 NTAPI
94 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
95 {
96 /* Copy the version block */
97 RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64));
98 }
99
100 VOID
101 NTAPI
102 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
103 {
104 STRING Header;
105
106 /* Fill out the header */
107 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
108 Header.Buffer = (PCHAR)State;
109
110 /* Get the version block */
111 KdpSysGetVersion(&State->u.GetVersion64);
112
113 /* Fill out the state */
114 State->ApiNumber = DbgKdGetVersionApi;
115 State->ReturnStatus = STATUS_SUCCESS;
116
117 /* Send the packet */
118 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
119 &Header,
120 NULL,
121 &KdpContext);
122 }
123
124
125 BOOLEAN VirtCalled = FALSE;
126
127 VOID
128 NTAPI
129 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
130 IN PSTRING Data,
131 IN PCONTEXT Context)
132 {
133 STRING Header;
134 ULONG Length = State->u.ReadMemory.TransferCount;
135 NTSTATUS Status = STATUS_SUCCESS;
136
137 /* Validate length */
138 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
139 {
140 /* Overflow, set it to maximum possible */
141 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
142 }
143
144 #if 0
145 if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))
146 {
147 Ke386SetCr2(State->u.ReadMemory.TargetBaseAddress);
148 while (TRUE);
149 }
150 #endif
151
152 if ((ULONG_PTR)State->u.ReadMemory.TargetBaseAddress < KSEG0_BASE)
153 {
154 Length = 0;
155 Status = STATUS_UNSUCCESSFUL;
156 }
157 else if ((ULONG_PTR)State->u.ReadMemory.TargetBaseAddress >= (ULONG_PTR)SharedUserData)
158 {
159 Length = 0;
160 Status = STATUS_UNSUCCESSFUL;
161 }
162 else
163 {
164 RtlCopyMemory(Data->Buffer,
165 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
166 Length);
167 }
168
169 /* Fill out the header */
170 Data->Length = Length;
171 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
172 Header.Buffer = (PCHAR)State;
173
174 /* Fill out the state */
175 State->ReturnStatus = Status;
176 State->u.ReadMemory.ActualBytesRead = Length;
177
178 /* Send the packet */
179 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
180 &Header,
181 Data,
182 &KdpContext);
183 }
184
185 VOID
186 NTAPI
187 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
188 IN PSTRING Data,
189 IN PCONTEXT Context)
190 {
191 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
192 STRING Header;
193 ULONG Length, RealLength;
194 PVOID ControlStart;
195
196 /* Setup the header */
197 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
198 Header.Buffer = (PCHAR)State;
199 ASSERT(Data->Length == 0);
200
201 /* Check the length requested */
202 Length = ReadMemory->TransferCount;
203 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
204 {
205 /* Use maximum allowed */
206 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
207 }
208
209 /* Make sure that this is a valid request */
210 if (((ULONG)ReadMemory->TargetBaseAddress < sizeof(KPROCESSOR_STATE)) &&
211 (State->Processor < KeNumberProcessors))
212 {
213 /* Get the actual length */
214 RealLength = sizeof(KPROCESSOR_STATE) -
215 (ULONG_PTR)ReadMemory->TargetBaseAddress;
216 if (RealLength < Length) Length = RealLength;
217
218 /* Set the proper address */
219 ControlStart = (PVOID)((ULONG_PTR)ReadMemory->TargetBaseAddress +
220 (ULONG_PTR)&KiProcessorBlock[State->Processor]->
221 ProcessorState);
222
223 /* Copy the memory */
224 RtlCopyMemory(Data->Buffer, ControlStart, Length);
225 Data->Length = Length;
226
227 /* Finish up */
228 State->ReturnStatus = STATUS_SUCCESS;
229 ReadMemory->ActualBytesRead = Data->Length;
230 }
231 else
232 {
233 /* Invalid request */
234 Data->Length = 0;
235 State->ReturnStatus = STATUS_UNSUCCESSFUL;
236 ReadMemory->ActualBytesRead = 0;
237 }
238
239 /* Send the reply */
240 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
241 &Header,
242 Data,
243 &KdpContext);
244 }
245
246 KCONTINUE_STATUS
247 NTAPI
248 KdpSendWaitContinue(IN ULONG PacketType,
249 IN PSTRING SendHeader,
250 IN PSTRING SendData OPTIONAL,
251 IN OUT PCONTEXT Context)
252 {
253 STRING Data, Header;
254 DBGKD_MANIPULATE_STATE64 ManipulateState;
255 ULONG Length;
256 KDSTATUS RecvCode;
257
258 /* Setup the Manipulate State structure */
259 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
260 Header.Buffer = (PCHAR)&ManipulateState;
261 Data.MaximumLength = sizeof(KdpMessageBuffer);
262 Data.Buffer = KdpMessageBuffer;
263 //KdpContextSent = FALSE;
264
265 SendPacket:
266 /* Send the Packet */
267 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
268
269 /* If the debugger isn't present anymore, just return success */
270 if (KdDebuggerNotPresent) return ContinueSuccess;
271
272 /* Main processing Loop */
273 for (;;)
274 {
275 /* Receive Loop */
276 do
277 {
278 /* Wait to get a reply to our packet */
279 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
280 &Header,
281 &Data,
282 &Length,
283 &KdpContext);
284
285 /* If we got a resend request, do it */
286 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
287 } while (RecvCode == KdPacketTimedOut);
288
289 /* Now check what API we got */
290 switch (ManipulateState.ApiNumber)
291 {
292 case DbgKdReadVirtualMemoryApi:
293
294 /* Read virtual memory */
295 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
296 VirtCalled = TRUE;
297 break;
298
299 case DbgKdWriteVirtualMemoryApi:
300
301 /* FIXME: TODO */
302 Ke386SetCr2(DbgKdWriteVirtualMemoryApi);
303 while (TRUE);
304 break;
305
306 case DbgKdGetContextApi:
307
308 /* FIXME: TODO */
309 Ke386SetCr2(DbgKdGetContextApi);
310 while (TRUE);
311 break;
312
313 case DbgKdSetContextApi:
314
315 /* FIXME: TODO */
316 Ke386SetCr2(DbgKdSetContextApi);
317 while (TRUE);
318 break;
319
320 case DbgKdWriteBreakPointApi:
321
322 /* FIXME: TODO */
323 Ke386SetCr2(DbgKdWriteBreakPointApi);
324 while (TRUE);
325 break;
326
327 case DbgKdRestoreBreakPointApi:
328
329 /* FIXME: TODO */
330 Ke386SetCr2(DbgKdRestoreBreakPointApi);
331 while (TRUE);
332 break;
333
334 case DbgKdContinueApi:
335
336 /* FIXME: TODO */
337 Ke386SetCr2(DbgKdContinueApi);
338 while (TRUE);
339 break;
340
341 case DbgKdReadControlSpaceApi:
342
343 /* Read control space */
344 KdpReadControlSpace(&ManipulateState, &Data, Context);
345 break;
346
347 case DbgKdWriteControlSpaceApi:
348
349 /* FIXME: TODO */
350 Ke386SetCr2(DbgKdWriteControlSpaceApi);
351 while (TRUE);
352 break;
353
354 case DbgKdReadIoSpaceApi:
355
356 /* FIXME: TODO */
357 Ke386SetCr2(DbgKdReadIoSpaceApi);
358 while (TRUE);
359 break;
360
361 case DbgKdWriteIoSpaceApi:
362
363 /* FIXME: TODO */
364 Ke386SetCr2(DbgKdWriteIoSpaceApi);
365 while (TRUE);
366 break;
367
368 case DbgKdRebootApi:
369
370 /* FIXME: TODO */
371 Ke386SetCr2(DbgKdRebootApi);
372 while (TRUE);
373 break;
374
375 case DbgKdContinueApi2:
376
377 /* FIXME: TODO */
378 Ke386SetCr2(DbgKdContinueApi2);
379 while (TRUE);
380 break;
381
382 case DbgKdReadPhysicalMemoryApi:
383
384 /* FIXME: TODO */
385 Ke386SetCr2(DbgKdReadPhysicalMemoryApi);
386 while (TRUE);
387 break;
388
389 case DbgKdWritePhysicalMemoryApi:
390
391 /* FIXME: TODO */
392 Ke386SetCr2(DbgKdWritePhysicalMemoryApi);
393 while (TRUE);
394 break;
395
396 case DbgKdQuerySpecialCallsApi:
397
398 /* FIXME: TODO */
399 Ke386SetCr2(DbgKdQuerySpecialCallsApi);
400 while (TRUE);
401 break;
402
403 case DbgKdSetSpecialCallApi:
404
405 /* FIXME: TODO */
406 Ke386SetCr2(DbgKdSetSpecialCallApi);
407 while (TRUE);
408 break;
409
410 case DbgKdClearSpecialCallsApi:
411
412 /* FIXME: TODO */
413 Ke386SetCr2(DbgKdClearSpecialCallsApi);
414 while (TRUE);
415 break;
416
417 case DbgKdSetInternalBreakPointApi:
418
419 /* FIXME: TODO */
420 Ke386SetCr2(DbgKdSetInternalBreakPointApi);
421 while (TRUE);
422 break;
423
424 case DbgKdGetInternalBreakPointApi:
425
426 /* FIXME: TODO */
427 Ke386SetCr2(DbgKdGetInternalBreakPointApi);
428 while (TRUE);
429 break;
430
431 case DbgKdReadIoSpaceExtendedApi:
432
433 /* FIXME: TODO */
434 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi);
435 while (TRUE);
436 break;
437
438 case DbgKdWriteIoSpaceExtendedApi:
439
440 /* FIXME: TODO */
441 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi);
442 while (TRUE);
443 break;
444
445 case DbgKdGetVersionApi:
446
447 /* Get version data */
448 KdpGetVersion(&ManipulateState);
449 break;
450
451 case DbgKdWriteBreakPointExApi:
452
453 /* FIXME: TODO */
454 Ke386SetCr2(DbgKdWriteBreakPointExApi);
455 while (TRUE);
456 break;
457
458 case DbgKdRestoreBreakPointExApi:
459
460 /* FIXME: TODO */
461 Ke386SetCr2(DbgKdRestoreBreakPointExApi);
462 while (TRUE);
463 break;
464
465 case DbgKdCauseBugCheckApi:
466
467 /* FIXME: TODO */
468 Ke386SetCr2(DbgKdCauseBugCheckApi);
469 while (TRUE);
470 break;
471
472 case DbgKdSwitchProcessor:
473
474 /* FIXME: TODO */
475 Ke386SetCr2(DbgKdSwitchProcessor);
476 while (TRUE);
477 break;
478
479 case DbgKdPageInApi:
480
481 /* FIXME: TODO */
482 Ke386SetCr2(DbgKdPageInApi);
483 while (TRUE);
484 break;
485
486 case DbgKdReadMachineSpecificRegister:
487
488 /* FIXME: TODO */
489 Ke386SetCr2(DbgKdReadMachineSpecificRegister);
490 while (TRUE);
491 break;
492
493 case DbgKdWriteMachineSpecificRegister:
494
495 /* FIXME: TODO */
496 Ke386SetCr2(DbgKdWriteMachineSpecificRegister);
497 while (TRUE);
498 break;
499
500 case OldVlm1:
501
502 /* FIXME: TODO */
503 Ke386SetCr2(OldVlm1);
504 while (TRUE);
505 break;
506
507 case OldVlm2:
508
509 /* FIXME: TODO */
510 Ke386SetCr2(OldVlm2);
511 while (TRUE);
512 break;
513
514 case DbgKdSearchMemoryApi:
515
516 /* FIXME: TODO */
517 Ke386SetCr2(DbgKdSearchMemoryApi);
518 while (TRUE);
519 break;
520
521 case DbgKdGetBusDataApi:
522
523 /* FIXME: TODO */
524 Ke386SetCr2(DbgKdGetBusDataApi);
525 while (TRUE);
526 break;
527
528 case DbgKdSetBusDataApi:
529
530 /* FIXME: TODO */
531 Ke386SetCr2(DbgKdSetBusDataApi);
532 while (TRUE);
533 break;
534
535 case DbgKdCheckLowMemoryApi:
536
537 /* FIXME: TODO */
538 Ke386SetCr2(DbgKdCheckLowMemoryApi);
539 while (TRUE);
540 break;
541
542 case DbgKdClearAllInternalBreakpointsApi:
543
544 /* FIXME: TODO */
545 Ke386SetCr2(DbgKdClearAllInternalBreakpointsApi);
546 while (TRUE);
547 break;
548
549 case DbgKdFillMemoryApi:
550
551 /* FIXME: TODO */
552 Ke386SetCr2(DbgKdFillMemoryApi);
553 while (TRUE);
554 break;
555
556 case DbgKdQueryMemoryApi:
557
558 /* FIXME: TODO */
559 Ke386SetCr2(DbgKdQueryMemoryApi);
560 while (TRUE);
561 break;
562
563 case DbgKdSwitchPartition:
564
565 /* FIXME: TODO */
566 Ke386SetCr2(DbgKdSwitchPartition);
567 while (TRUE);
568 break;
569
570 /* Unsupported Message */
571 default:
572
573 /* Setup an empty message, with failure */
574 while (TRUE);
575 Data.Length = 0;
576 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
577
578 /* Send it */
579 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
580 &Header,
581 &Data,
582 &KdpContext);
583 break;
584 }
585 }
586 }
587
588 BOOLEAN
589 NTAPI
590 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
591 IN PKD_SYMBOLS_INFO SymbolInfo,
592 IN BOOLEAN Unload,
593 IN OUT PCONTEXT Context)
594 {
595 PSTRING ExtraData;
596 STRING Data, Header;
597 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
598 KCONTINUE_STATUS Status;
599
600 /* Start wait loop */
601 do
602 {
603 /* Build the architecture common parts of the message */
604 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
605 Context,
606 &WaitStateChange);
607
608 /* Now finish creating the structure */
609 KdpSetContextState(&WaitStateChange, Context);
610
611 /* Fill out load data */
612 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
613 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG)SymbolInfo->BaseOfDll;
614 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
615 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
616 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
617
618 /* Check if we have a symbol name */
619 if (PathName)
620 {
621 /* Setup the information */
622 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
623 Data.Buffer = KdpPathBuffer;
624 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
625 ExtraData = &Data;
626 }
627 else
628 {
629 /* No name */
630 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
631 ExtraData = NULL;
632 }
633
634 /* Setup the header */
635 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
636 Header.Buffer = (PCHAR)&WaitStateChange;
637
638 /* Send the packet */
639 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
640 &Header,
641 ExtraData,
642 Context);
643 } while(Status == ContinueProcessorReselected);
644
645 /* Return status */
646 while (TRUE);
647 return Status;
648 }
649
650 VOID
651 NTAPI
652 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
653 IN PVOID DeferredContext,
654 IN PVOID SystemArgument1,
655 IN PVOID SystemArgument2)
656 {
657 LONG OldSlip, NewSlip, PendingSlip;
658
659 /* Get the current pending slip */
660 PendingSlip = KdpTimeSlipPending;
661 do
662 {
663 /* Save the old value and either disable or enable it now. */
664 OldSlip = PendingSlip;
665 NewSlip = OldSlip > 1 ? 1 : 0;
666
667 /* Try to change the value */
668 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
669 NewSlip,
670 OldSlip) != OldSlip);
671
672 /* If the New Slip value is 1, then do the Time Slipping */
673 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
674 }
675
676 VOID
677 NTAPI
678 KdpTimeSlipWork(IN PVOID Context)
679 {
680 KIRQL OldIrql;
681 LARGE_INTEGER DueTime;
682
683 /* Update the System time from the CMOS */
684 ExAcquireTimeRefreshLock(FALSE);
685 ExUpdateSystemTimeFromCmos(FALSE, 0);
686 ExReleaseTimeRefreshLock();
687
688 /* Check if we have a registered Time Slip Event and signal it */
689 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
690 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
691 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
692
693 /* Delay the DPC until it runs next time */
694 DueTime.QuadPart = -1800000000;
695 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
696 }
697
698 BOOLEAN
699 NTAPI
700 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
701 IN OUT PCONTEXT ContextRecord,
702 IN BOOLEAN SecondChanceException)
703 {
704 BOOLEAN Status;
705
706 /* Save the port data */
707 KdSave(FALSE);
708
709 /* Report a state change */
710 #if 0
711 Status = KdpReportExceptionStateChange(ExceptionRecord,
712 ContextRecord,
713 SecondChanceException);
714 #else
715 Status = FALSE;
716 #endif
717
718 /* Restore the port data and return */
719 KdRestore(FALSE);
720 return Status;
721 }
722
723 LARGE_INTEGER
724 NTAPI
725 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
726 {
727 LARGE_INTEGER Null = {{0}};
728
729 /* Check if interrupts were disabled */
730 if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
731 {
732 /* Nothing to return */
733 return Null;
734 }
735
736 /* Otherwise, do the call */
737 return KeQueryPerformanceCounter(NULL);
738 }
739
740 BOOLEAN
741 NTAPI
742 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
743 IN PKEXCEPTION_FRAME ExceptionFrame)
744 {
745 BOOLEAN Entered;
746
747 /* Check if we have a trap frame */
748 if (TrapFrame)
749 {
750 /* Calculate the time difference for the enter */
751 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
752 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
753 KdTimerStart.QuadPart;
754 }
755 else
756 {
757 /* No trap frame, so can't calculate */
758 KdTimerStop.QuadPart = 0;
759 }
760
761 /* Save the current IRQL */
762 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
763
764 /* Freeze all CPUs */
765 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
766
767 /* Lock the port, save the state and set debugger entered */
768 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
769 KdSave(FALSE);
770 KdEnteredDebugger = TRUE;
771
772 /* Check freeze flag */
773 if (KiFreezeFlag & 1)
774 {
775 /* Print out errror */
776 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
777 }
778
779 /* Check processor state */
780 if (KiFreezeFlag & 2)
781 {
782 /* Print out errror */
783 DbgPrint("Some processors not frozen in debugger!\n");
784 }
785
786 /* Make sure we acquired the port */
787 if (!KdpPortLocked) DbgPrint("Port lock was not acquired!\n");
788
789 /* Return enter state */
790 return Entered;
791 }
792
793 VOID
794 NTAPI
795 KdExitDebugger(IN BOOLEAN Entered)
796 {
797 ULONG TimeSlip;
798
799 /* Restore the state and unlock the port */
800 KdRestore(FALSE);
801 if (KdpPortLocked) KdpPortUnlock();
802
803 /* Unfreeze the CPUs */
804 KeThawExecution(Entered);
805
806 /* Compare time with the one from KdEnterDebugger */
807 if (!KdTimerStop.QuadPart)
808 {
809 /* We didn't get a trap frame earlier in so never got the time */
810 KdTimerStart = KdTimerStop;
811 }
812 else
813 {
814 /* Query the timer */
815 KdTimerStart = KeQueryPerformanceCounter(NULL);
816 }
817
818 /* Check if a Time Slip was on queue */
819 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
820 if (TimeSlip == 1)
821 {
822 /* Queue a DPC for the time slip */
823 InterlockedIncrement(&KdpTimeSlipPending);
824 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
825 }
826 }
827
828 NTSTATUS
829 NTAPI
830 KdEnableDebuggerWithLock(BOOLEAN NeedLock)
831 {
832 KIRQL OldIrql;
833
834 /* Check if we need to acquire the lock */
835 if (NeedLock)
836 {
837 /* Lock the port */
838 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
839 KdpPortLock();
840 }
841
842 /* Check if we're not disabled */
843 if (!KdDisableCount)
844 {
845 /* Check if we had locked the port before */
846 if (NeedLock)
847 {
848 /* Do the unlock */
849 KeLowerIrql(OldIrql);
850 KdpPortUnlock();
851 }
852
853 /* Fail: We're already enabled */
854 return STATUS_INVALID_PARAMETER;
855 }
856
857 /* Decrease the disable count */
858 if (!(--KdDisableCount))
859 {
860 /* We're now enabled again! Were we enabled before, too? */
861 if (KdPreviouslyEnabled)
862 {
863 /* Reinitialize the Debugger */
864 KdInitSystem(0, NULL) ;
865 //KdpRestoreAllBreakpoints();
866 }
867 }
868
869 /* Check if we had locked the port before */
870 if (NeedLock)
871 {
872 /* Yes, now unlock it */
873 KeLowerIrql(OldIrql);
874 KdpPortUnlock();
875 }
876
877 /* We're done */
878 return STATUS_SUCCESS;
879 }
880
881 /* PUBLIC FUNCTIONS **********************************************************/
882
883 /*
884 * @implemented
885 */
886 NTSTATUS
887 NTAPI
888 KdEnableDebugger(VOID)
889 {
890 /* Use the internal routine */
891 while (TRUE);
892 return KdEnableDebuggerWithLock(TRUE);
893 }
894