Skip to content

Commit

Permalink
[NTOS:KE/x64] Improve freeze code
Browse files Browse the repository at this point in the history
- Set ACTIVE flag on freeze owner like on Windows
- Add a nice state graph
- Change license to MIT
  • Loading branch information
tkreuzer committed Jan 19, 2025
1 parent dc25409 commit 1711359
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions ntoskrnl/ke/amd64/freeze.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Processor freeze support for x64
* COPYRIGHT: Copyright 2023 Timo Kreuzer <[email protected]>
* COPYRIGHT: Copyright 2023-2024 Timo Kreuzer <[email protected]>
*/

/*
IpiFrozen state graph (based on Windows behavior):
+-----------------+ Freeze request +-----------------+
| RUNNING |------------------------>| TARGET_FREEZE |
+-----------------+<--------- +-----------------+
|^ | Resume |
Freeze || Thaw +-----------+ Thaw request | Freeze IPI
v| | THAW |<-----------\ v
+-----------------+ +-----------+ +-----------------+
| OWNER + ACTIVE | ^ | FROZEN |
+-----------------+ | +-----------------+
^ | ^
| Kd proc switch | | Kd proc switch
v | v
+-----------------+ | +-----------------+
| OWNER |---------+ | FROZEN + ACTIVE |
+-----------------+ Thaw request +-----------------+
*/

/* INCLUDES *******************************************************************/
Expand Down Expand Up @@ -98,16 +120,16 @@ KxFreezeExecution(
}
}

/* We are the owner now */
CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
/* We are the owner now and active */
CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER | IPI_FROZEN_FLAG_ACTIVE;

/* Loop all processors */
for (ULONG i = 0; i < KeNumberProcessors; i++)
{
PKPRCB TargetPrcb = KiProcessorBlock[i];
if (TargetPrcb != CurrentPrcb)
{
/* Nobody else is allowed to change IpiFrozen, except the freeze owner */
/* Only the active processor is allowed to change IpiFrozen */
ASSERT(TargetPrcb->IpiFrozen == IPI_FROZEN_STATE_RUNNING);

/* Request target to freeze */
Expand Down Expand Up @@ -142,6 +164,7 @@ KxThawExecution(
VOID)
{
PKPRCB CurrentPrcb = KeGetCurrentPrcb();
ASSERT(CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE);

/* Loop all processors */
for (ULONG i = 0; i < KeNumberProcessors; i++)
Expand Down Expand Up @@ -190,6 +213,10 @@ KxSwitchKdProcessor(
/* Make sure that the processor index is valid */
ASSERT(ProcessorIndex < KeNumberProcessors);

/* We are no longer active */
ASSERT(CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE);
CurrentPrcb->IpiFrozen &= ~IPI_FROZEN_FLAG_ACTIVE;

/* Inform the target processor that it's his turn now */
TargetPrcb = KiProcessorBlock[ProcessorIndex];
TargetPrcb->IpiFrozen |= IPI_FROZEN_FLAG_ACTIVE;
Expand All @@ -212,12 +239,12 @@ KxSwitchKdProcessor(
{
/* Another CPU has completed, we can leave the debugger now */
KdpDprintf("[%u] KxSwitchKdProcessor: ContinueSuccess\n", KeGetCurrentProcessorNumber());
CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER | IPI_FROZEN_FLAG_ACTIVE;
return ContinueSuccess;
}

/* We have been reselected, return to Kd to continue in the debugger */
CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
ASSERT(CurrentPrcb->IpiFrozen == (IPI_FROZEN_STATE_OWNER | IPI_FROZEN_FLAG_ACTIVE));

return ContinueProcessorReselected;
}

0 comments on commit 1711359

Please sign in to comment.