diff --git a/ntoskrnl/include/internal/kd64.h b/ntoskrnl/include/internal/kd64.h index cf46bc2a3b6..bc28eb48cc9 100644 --- a/ntoskrnl/include/internal/kd64.h +++ b/ntoskrnl/include/internal/kd64.h @@ -72,14 +72,6 @@ BOOLEAN IN BOOLEAN SecondChance ); -typedef -BOOLEAN -(NTAPI *PKDEBUG_SWITCH_ROUTINE)( - IN PEXCEPTION_RECORD ExceptionRecord, - IN PCONTEXT Context, - IN BOOLEAN SecondChance -); - // // Initialization Routines // @@ -110,13 +102,10 @@ KdIsThisAKdTrap( // // Multi-Processor Switch Support // -BOOLEAN +KCONTINUE_STATUS NTAPI -KdpSwitchProcessor( - IN PEXCEPTION_RECORD ExceptionRecord, - IN OUT PCONTEXT ContextRecord, - IN BOOLEAN SecondChanceException -); +KdReportProcessorChange( + VOID); // // Time Slip Support @@ -540,7 +529,6 @@ extern LARGE_INTEGER KdTimerStart; extern ULONG KdDisableCount; extern KD_CONTEXT KdpContext; extern PKDEBUG_ROUTINE KiDebugRoutine; -extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; extern BOOLEAN KdBreakAfterSymbolLoad; extern BOOLEAN KdPitchDebugger; extern BOOLEAN KdAutoEnableOnEvent; diff --git a/ntoskrnl/include/internal/ke.h b/ntoskrnl/include/internal/ke.h index 9c19f4ef6e5..aaff743134e 100644 --- a/ntoskrnl/include/internal/ke.h +++ b/ntoskrnl/include/internal/ke.h @@ -1001,6 +1001,11 @@ VOID NTAPI KeThawExecution(IN BOOLEAN Enable); +KCONTINUE_STATUS +NTAPI +KxSwitchKdProcessor( + _In_ ULONG ProcessorIndex); + _IRQL_requires_min_(DISPATCH_LEVEL) _Acquires_nonreentrant_lock_(*LockHandle->Lock) _Acquires_exclusive_lock_(*LockHandle->Lock) diff --git a/ntoskrnl/kd64/kdapi.c b/ntoskrnl/kd64/kdapi.c index 3295d3b256c..089af9c5f86 100644 --- a/ntoskrnl/kd64/kdapi.c +++ b/ntoskrnl/kd64/kdapi.c @@ -1260,6 +1260,28 @@ KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State) &KdpContext); } +static +KCONTINUE_STATUS +KdpSwitchProcessor( + _In_ USHORT ProcessorIndex) +{ + /* Make sure that the processor index is valid */ + if (ProcessorIndex >= KeNumberProcessors) + { + KdpDprintf("%u is not a valid processor number\n", ProcessorIndex); + return ContinueProcessorReselected; + } + + /* If the new processor is the current one, there is nothing to do */ + if (ProcessorIndex == KeGetCurrentProcessorNumber()) + { + return ContinueProcessorReselected; + } + + /* Call the architecture specific Ke routine */ + return KxSwitchKdProcessor(ProcessorIndex); +} + KCONTINUE_STATUS NTAPI KdpSendWaitContinue(IN ULONG PacketType, @@ -1470,10 +1492,8 @@ SendPacket: case DbgKdSwitchProcessor: - /* TODO */ - KdpDprintf("Processor Switch support is unimplemented!\n"); - KdpNotSupported(&ManipulateState); - break; + /* Switch the processor and return */ + return KdpSwitchProcessor(ManipulateState.Processor); case DbgKdPageInApi: @@ -1785,6 +1805,33 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, return Status; } +KCONTINUE_STATUS +NTAPI +KdReportProcessorChange( + VOID) +{ + PKPRCB CurrentPrcb = KeGetCurrentPrcb(); + PCONTEXT ContextRecord = &CurrentPrcb->ProcessorState.ContextFrame; + EXCEPTION_RECORD ExceptionRecord = {0}; + KCONTINUE_STATUS Status; + + /* Save the port data */ + KdSave(FALSE); + + ExceptionRecord.ExceptionAddress = (PVOID)KeGetContextPc(ContextRecord); + ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER; + + /* Report the new state */ + Status = KdpReportExceptionStateChange(&ExceptionRecord, + ContextRecord, + FALSE); + + /* Restore the port data */ + KdRestore(FALSE); + + return Status; +} + VOID NTAPI KdpTimeSlipDpcRoutine(IN PKDPC Dpc, @@ -1833,27 +1880,6 @@ KdpTimeSlipWork(IN PVOID Context) KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc); } -BOOLEAN -NTAPI -KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord, - IN OUT PCONTEXT ContextRecord, - IN BOOLEAN SecondChanceException) -{ - BOOLEAN Status; - - /* Save the port data */ - KdSave(FALSE); - - /* Report a state change */ - Status = KdpReportExceptionStateChange(ExceptionRecord, - ContextRecord, - SecondChanceException); - - /* Restore the port data and return */ - KdRestore(FALSE); - return Status; -} - LARGE_INTEGER NTAPI KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) diff --git a/ntoskrnl/kd64/kddata.c b/ntoskrnl/kd64/kddata.c index dbe56351db1..c94e9427bca 100644 --- a/ntoskrnl/kd64/kddata.c +++ b/ntoskrnl/kd64/kddata.c @@ -72,7 +72,6 @@ BOOLEAN KdpContextSent; // Debug Trap Handlers // PKDEBUG_ROUTINE KiDebugRoutine = KdpStub; -PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; // // Debugger Configuration Settings diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c index 8ce9ba72ce7..4f49b48ef28 100644 --- a/ntoskrnl/kd64/kdinit.c +++ b/ntoskrnl/kd64/kdinit.c @@ -360,9 +360,8 @@ KdInitSystem( /* Check if we've already initialized our structures */ if (!KdpDebuggerStructuresInitialized) { - /* Set the Debug Switch Routine and Retries */ + /* Set Retries */ KdpContext.KdpDefaultRetries = 20; - KiDebugSwitchRoutine = KdpSwitchProcessor; /* Initialize breakpoints owed flag and table */ KdpOweBreakpoint = FALSE; diff --git a/ntoskrnl/ke/amd64/freeze.c b/ntoskrnl/ke/amd64/freeze.c index d0b5cee3098..5cf53f3f27f 100644 --- a/ntoskrnl/ke/amd64/freeze.c +++ b/ntoskrnl/ke/amd64/freeze.c @@ -40,6 +40,25 @@ KiProcessorFreezeHandler( /* Wait for the freeze owner to release us */ while (CurrentPrcb->IpiFrozen != IPI_FROZEN_STATE_THAW) { + /* Check for Kd processor switch */ + if (CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE) + { + KCONTINUE_STATUS ContinueStatus; + + /* Enter the debugger */ + ContinueStatus = KdReportProcessorChange(); + + /* Set the state back to frozen */ + CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_FROZEN; + + /* If the status is ContinueSuccess, we need to release the freeze owner */ + if (ContinueStatus == ContinueSuccess) + { + /* Release the freeze owner */ + KiFreezeOwner->IpiFrozen = IPI_FROZEN_STATE_THAW; + } + } + YieldProcessor(); KeMemoryBarrier(); } @@ -159,3 +178,46 @@ KxThawExecution( /* Release the freeze owner */ InterlockedExchangePointer(&KiFreezeOwner, NULL); } + +KCONTINUE_STATUS +NTAPI +KxSwitchKdProcessor( + _In_ ULONG ProcessorIndex) +{ + PKPRCB CurrentPrcb = KeGetCurrentPrcb(); + PKPRCB TargetPrcb; + + /* Make sure that the processor index is valid */ + ASSERT(ProcessorIndex < KeNumberProcessors); + + /* Inform the target processor that it's his turn now */ + TargetPrcb = KiProcessorBlock[ProcessorIndex]; + TargetPrcb->IpiFrozen |= IPI_FROZEN_FLAG_ACTIVE; + + /* If we are not the freeze owner, we return back to the freeze loop */ + if (KiFreezeOwner != CurrentPrcb) + { + return ContinueNextProcessor; + } + + /* Loop until it's our turn again */ + while (CurrentPrcb->IpiFrozen == IPI_FROZEN_STATE_OWNER) + { + YieldProcessor(); + KeMemoryBarrier(); + } + + /* Check if we have been thawed */ + if (CurrentPrcb->IpiFrozen == IPI_FROZEN_STATE_THAW) + { + /* Another CPU has completed, we can leave the debugger now */ + KdpDprintf("[%u] KxSwitchKdProcessor: ContinueSuccess\n", KeGetCurrentProcessorNumber()); + CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER; + return ContinueSuccess; + } + + /* We have been reselected, return to Kd to continue in the debugger */ + CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER; + + return ContinueProcessorReselected; +} diff --git a/ntoskrnl/ke/i386/freeze.c b/ntoskrnl/ke/i386/freeze.c index 176aa70e08e..e1c27214e46 100644 --- a/ntoskrnl/ke/i386/freeze.c +++ b/ntoskrnl/ke/i386/freeze.c @@ -26,3 +26,12 @@ KxThawExecution( { UNIMPLEMENTED; } + +KCONTINUE_STATUS +NTAPI +KxSwitchKdProcessor( + _In_ ULONG ProcessorIndex) +{ + UNIMPLEMENTED; + return ContinueError; +}