[NTOS:KE/x64] Implement Kd processor switching

This commit is contained in:
Timo Kreuzer 2023-12-07 21:27:44 +02:00
parent 9229709312
commit 72fd54a7f4
7 changed files with 131 additions and 43 deletions

View file

@ -72,14 +72,6 @@ BOOLEAN
IN BOOLEAN SecondChance IN BOOLEAN SecondChance
); );
typedef
BOOLEAN
(NTAPI *PKDEBUG_SWITCH_ROUTINE)(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOLEAN SecondChance
);
// //
// Initialization Routines // Initialization Routines
// //
@ -110,13 +102,10 @@ KdIsThisAKdTrap(
// //
// Multi-Processor Switch Support // Multi-Processor Switch Support
// //
BOOLEAN KCONTINUE_STATUS
NTAPI NTAPI
KdpSwitchProcessor( KdReportProcessorChange(
IN PEXCEPTION_RECORD ExceptionRecord, VOID);
IN OUT PCONTEXT ContextRecord,
IN BOOLEAN SecondChanceException
);
// //
// Time Slip Support // Time Slip Support
@ -540,7 +529,6 @@ extern LARGE_INTEGER KdTimerStart;
extern ULONG KdDisableCount; extern ULONG KdDisableCount;
extern KD_CONTEXT KdpContext; extern KD_CONTEXT KdpContext;
extern PKDEBUG_ROUTINE KiDebugRoutine; extern PKDEBUG_ROUTINE KiDebugRoutine;
extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
extern BOOLEAN KdBreakAfterSymbolLoad; extern BOOLEAN KdBreakAfterSymbolLoad;
extern BOOLEAN KdPitchDebugger; extern BOOLEAN KdPitchDebugger;
extern BOOLEAN KdAutoEnableOnEvent; extern BOOLEAN KdAutoEnableOnEvent;

View file

@ -1001,6 +1001,11 @@ VOID
NTAPI NTAPI
KeThawExecution(IN BOOLEAN Enable); KeThawExecution(IN BOOLEAN Enable);
KCONTINUE_STATUS
NTAPI
KxSwitchKdProcessor(
_In_ ULONG ProcessorIndex);
_IRQL_requires_min_(DISPATCH_LEVEL) _IRQL_requires_min_(DISPATCH_LEVEL)
_Acquires_nonreentrant_lock_(*LockHandle->Lock) _Acquires_nonreentrant_lock_(*LockHandle->Lock)
_Acquires_exclusive_lock_(*LockHandle->Lock) _Acquires_exclusive_lock_(*LockHandle->Lock)

View file

@ -1260,6 +1260,28 @@ KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)
&KdpContext); &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 KCONTINUE_STATUS
NTAPI NTAPI
KdpSendWaitContinue(IN ULONG PacketType, KdpSendWaitContinue(IN ULONG PacketType,
@ -1470,10 +1492,8 @@ SendPacket:
case DbgKdSwitchProcessor: case DbgKdSwitchProcessor:
/* TODO */ /* Switch the processor and return */
KdpDprintf("Processor Switch support is unimplemented!\n"); return KdpSwitchProcessor(ManipulateState.Processor);
KdpNotSupported(&ManipulateState);
break;
case DbgKdPageInApi: case DbgKdPageInApi:
@ -1785,6 +1805,33 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
return Status; 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 VOID
NTAPI NTAPI
KdpTimeSlipDpcRoutine(IN PKDPC Dpc, KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
@ -1833,27 +1880,6 @@ KdpTimeSlipWork(IN PVOID Context)
KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc); 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 LARGE_INTEGER
NTAPI NTAPI
KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)

View file

@ -72,7 +72,6 @@ BOOLEAN KdpContextSent;
// Debug Trap Handlers // Debug Trap Handlers
// //
PKDEBUG_ROUTINE KiDebugRoutine = KdpStub; PKDEBUG_ROUTINE KiDebugRoutine = KdpStub;
PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
// //
// Debugger Configuration Settings // Debugger Configuration Settings

View file

@ -360,9 +360,8 @@ KdInitSystem(
/* Check if we've already initialized our structures */ /* Check if we've already initialized our structures */
if (!KdpDebuggerStructuresInitialized) if (!KdpDebuggerStructuresInitialized)
{ {
/* Set the Debug Switch Routine and Retries */ /* Set Retries */
KdpContext.KdpDefaultRetries = 20; KdpContext.KdpDefaultRetries = 20;
KiDebugSwitchRoutine = KdpSwitchProcessor;
/* Initialize breakpoints owed flag and table */ /* Initialize breakpoints owed flag and table */
KdpOweBreakpoint = FALSE; KdpOweBreakpoint = FALSE;

View file

@ -40,6 +40,25 @@ KiProcessorFreezeHandler(
/* Wait for the freeze owner to release us */ /* Wait for the freeze owner to release us */
while (CurrentPrcb->IpiFrozen != IPI_FROZEN_STATE_THAW) 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(); YieldProcessor();
KeMemoryBarrier(); KeMemoryBarrier();
} }
@ -159,3 +178,46 @@ KxThawExecution(
/* Release the freeze owner */ /* Release the freeze owner */
InterlockedExchangePointer(&KiFreezeOwner, NULL); 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;
}

View file

@ -26,3 +26,12 @@ KxThawExecution(
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
KCONTINUE_STATUS
NTAPI
KxSwitchKdProcessor(
_In_ ULONG ProcessorIndex)
{
UNIMPLEMENTED;
return ContinueError;
}