ReactOS 0.4.16-dev-125-g798ea90
freeze.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Processor freeze support for x64
5 * COPYRIGHT: Copyright 2023 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <ntoskrnl.h>
11#define NDEBUG
12#include <debug.h>
13
14/* NOT INCLUDES ANYMORE ******************************************************/
15
17
18/* FUNCTIONS *****************************************************************/
19
22 _In_ PKTRAP_FRAME TrapFrame,
23 _In_ PKEXCEPTION_FRAME ExceptionFrame)
24{
25 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
26
27 /* Make sure this is a freeze request */
28 if (CurrentPrcb->IpiFrozen != IPI_FROZEN_STATE_TARGET_FREEZE)
29 {
30 /* Not a freeze request, return FALSE to signal it is unhandled */
31 return FALSE;
32 }
33
34 /* We are frozen now */
36
37 /* Save the processor state */
38 KiSaveProcessorState(TrapFrame, ExceptionFrame);
39
40 /* Wait for the freeze owner to release us */
41 while (CurrentPrcb->IpiFrozen != IPI_FROZEN_STATE_THAW)
42 {
43 /* Check for Kd processor switch */
44 if (CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE)
45 {
46 KCONTINUE_STATUS ContinueStatus;
47
48 /* Enter the debugger */
49 ContinueStatus = KdReportProcessorChange();
50
51 /* Set the state back to frozen */
53
54 /* If the status is ContinueSuccess, we need to release the freeze owner */
55 if (ContinueStatus == ContinueSuccess)
56 {
57 /* Release the freeze owner */
59 }
60 }
61
64 }
65
66 /* Restore the processor state */
67 KiRestoreProcessorState(TrapFrame, ExceptionFrame);
68
69 /* We are running again now */
71
72 /* Return TRUE to signal that we handled the freeze */
73 return TRUE;
74}
75
76VOID
79 VOID)
80{
81 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
82
83 /* Avoid blocking on recursive debug action */
84 if (KiFreezeOwner == CurrentPrcb)
85 {
86 return;
87 }
88
89 /* Try to acquire the freeze owner */
91 {
92 /* Someone else was faster. We expect an NMI to freeze any time.
93 Spin here until the freeze owner is available. */
94 while (KiFreezeOwner != NULL)
95 {
98 }
99 }
100
101 /* We are the owner now */
102 CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
103
104 /* Loop all processors */
105 for (ULONG i = 0; i < KeNumberProcessors; i++)
106 {
107 PKPRCB TargetPrcb = KiProcessorBlock[i];
108 if (TargetPrcb != CurrentPrcb)
109 {
110 /* Nobody else is allowed to change IpiFrozen, except the freeze owner */
112
113 /* Request target to freeze */
115 }
116 }
117
118 /* Send the freeze IPI */
120
121 /* Wait for all targets to be frozen */
122 for (ULONG i = 0; i < KeNumberProcessors; i++)
123 {
124 PKPRCB TargetPrcb = KiProcessorBlock[i];
125 if (TargetPrcb != CurrentPrcb)
126 {
127 /* Wait for the target to be frozen */
128 while (TargetPrcb->IpiFrozen != IPI_FROZEN_STATE_FROZEN)
129 {
132 }
133 }
134 }
135
136 /* All targets are frozen, we can continue */
137}
138
139VOID
140NTAPI
142 VOID)
143{
144 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
145
146 /* Loop all processors */
147 for (ULONG i = 0; i < KeNumberProcessors; i++)
148 {
149 PKPRCB TargetPrcb = KiProcessorBlock[i];
150 if (TargetPrcb != CurrentPrcb)
151 {
152 /* Make sure they are still frozen */
154
155 /* Request target to thaw */
156 TargetPrcb->IpiFrozen = IPI_FROZEN_STATE_THAW;
157 }
158 }
159
160 /* Wait for all targets to be running */
161 for (ULONG i = 0; i < KeNumberProcessors; i++)
162 {
163 PKPRCB TargetPrcb = KiProcessorBlock[i];
164 if (TargetPrcb != CurrentPrcb)
165 {
166 /* Wait for the target to be running again */
167 while (TargetPrcb->IpiFrozen != IPI_FROZEN_STATE_RUNNING)
168 {
171 }
172 }
173 }
174
175 /* We are running again now */
176 CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_RUNNING;
177
178 /* Release the freeze owner */
180}
181
183NTAPI
185 _In_ ULONG ProcessorIndex)
186{
187 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
188 PKPRCB TargetPrcb;
189
190 /* Make sure that the processor index is valid */
191 ASSERT(ProcessorIndex < KeNumberProcessors);
192
193 /* Inform the target processor that it's his turn now */
194 TargetPrcb = KiProcessorBlock[ProcessorIndex];
195 TargetPrcb->IpiFrozen |= IPI_FROZEN_FLAG_ACTIVE;
196
197 /* If we are not the freeze owner, we return back to the freeze loop */
198 if (KiFreezeOwner != CurrentPrcb)
199 {
201 }
202
203 /* Loop until it's our turn again */
204 while (CurrentPrcb->IpiFrozen == IPI_FROZEN_STATE_OWNER)
205 {
208 }
209
210 /* Check if we have been thawed */
211 if (CurrentPrcb->IpiFrozen == IPI_FROZEN_STATE_THAW)
212 {
213 /* Another CPU has completed, we can leave the debugger now */
214 KdpDprintf("[%u] KxSwitchKdProcessor: ContinueSuccess\n", KeGetCurrentProcessorNumber());
215 CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
216 return ContinueSuccess;
217 }
218
219 /* We have been reselected, return to Kd to continue in the debugger */
220 CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
221
223}
unsigned char BOOLEAN
PKPRCB KiFreezeOwner
Definition: freeze.c:16
VOID NTAPI KxThawExecution(VOID)
Definition: freeze.c:141
KCONTINUE_STATUS NTAPI KxSwitchKdProcessor(_In_ ULONG ProcessorIndex)
Definition: freeze.c:184
BOOLEAN KiProcessorFreezeHandler(_In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: freeze.c:21
VOID NTAPI KxFreezeExecution(VOID)
Definition: freeze.c:78
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
KCONTINUE_STATUS NTAPI KdReportProcessorChange(VOID)
Definition: kdapi.c:1810
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define KdpDprintf(...)
Definition: mmdbg.c:19
#define ASSERT(a)
Definition: mode.c:44
#define _In_
Definition: ms_sal.h:308
#define IPI_FROZEN_STATE_TARGET_FREEZE
Definition: ketypes.h:315
#define IPI_FROZEN_FLAG_ACTIVE
Definition: ketypes.h:316
#define IPI_FROZEN_STATE_RUNNING
Definition: ketypes.h:311
#define IPI_FREEZE
Definition: ketypes.h:299
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define IPI_FROZEN_STATE_OWNER
Definition: ketypes.h:314
#define IPI_FROZEN_STATE_THAW
Definition: ketypes.h:313
#define IPI_FROZEN_STATE_FROZEN
Definition: ketypes.h:312
enum _KCONTINUE_STATUS KCONTINUE_STATUS
@ ContinueNextProcessor
Definition: ketypes.h:452
@ ContinueProcessorReselected
Definition: ketypes.h:451
@ ContinueSuccess
Definition: ketypes.h:450
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:32
KAFFINITY KeActiveProcessors
Definition: krnlinit.c:23
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
VOID NTAPI KiSaveProcessorState(_In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: cpu.c:617
VOID NTAPI KiRestoreProcessorState(_Out_ PKTRAP_FRAME TrapFrame, _Out_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: cpu.c:633
#define YieldProcessor
Definition: ke.h:48
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341
FORCEINLINE VOID KeMemoryBarrier(VOID)
Definition: ke.h:58
ULONG IpiFrozen
Definition: ketypes.h:755
UINT64 SetMember
Definition: ketypes.h:662
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59