[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
);
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;

View file

@ -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)

View file

@ -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)

View file

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

View file

@ -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;

View file

@ -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;
}

View file

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