ReactOS 0.4.17-dev-966-gf06eace
apicsmp.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: SMP specific APIC code
5 * COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreuzer@reactos.org>
6 * Copyright 2023 Justin Miller <justin.miller@reactos.org>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <hal.h>
12#include "apicp.h"
13#include <smp.h>
14
15#define NDEBUG
16#include <debug.h>
17
18/* INTERNAL FUNCTIONS *********************************************************/
19
59VOID
61 _In_ UCHAR DestinationProcessor,
63 _In_ APIC_MT MessageType,
64 _In_ APIC_TGM TriggerMode,
65 _In_ APIC_DSH DestinationShortHand)
66{
69
70 /* Disable interrupts so that we can change IRR without being interrupted */
72 _disable();
73
74 /* Wait for the APIC to be idle */
75 do
76 {
78 } while (Icr.DeliveryStatus);
79
80 /* Setup the command register */
81 Icr.LongLong = 0;
82 Icr.Vector = Vector;
83 Icr.MessageType = MessageType;
85 Icr.DeliveryStatus = 0;
86 Icr.Level = 0;
87 Icr.TriggerMode = TriggerMode;
88 Icr.RemoteReadStatus = 0;
89 Icr.DestinationShortHand = DestinationShortHand;
90 Icr.Destination = DestinationProcessor;
91
92 /* Write the low dword last to send the interrupt */
95
96 /* Finally, restore the original interrupt state */
98 {
99 _enable();
100 }
101}
102
103
104/* SMP SUPPORT FUNCTIONS ******************************************************/
105
106VOID
108 _In_ ULONG NTProcessorNumber,
109 _In_ PHYSICAL_ADDRESS StartupLoc)
110{
112
113 ASSERT(StartupLoc.HighPart == 0);
114 ASSERT((StartupLoc.QuadPart & 0xFFF) == 0);
115 ASSERT((StartupLoc.QuadPart & 0xFFF00FFF) == 0);
116
117 /* Init IPI */
118 ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, 0,
120
121 /* De-Assert Init IPI */
122 ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, 0,
124
125 /* Give the APIC time to latch INIT before the first SIPI: MPS Spec - B.4 */
127
128 /* 82489DX APICs don't support the STARTUP IPI: MPS Spec - B.4 */
130 if (ApicVersion.Version >= 0x10)
131 {
132 /* First Startup IPI */
133 ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, (StartupLoc.LowPart) >> 12,
135
136 /* Stall between SIPIs: MPS Spec - B.4 */
138
139 /* Second Startup IPI, required unconditionally by the MP Spec */
140 ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, (StartupLoc.LowPart) >> 12,
142
143 /* Give the AP time to come up before returning */
145 }
146}
147
148/* HAL IPI FUNCTIONS **********************************************************/
149
156VOID
157NTAPI
160 _In_ BOOLEAN IncludeSelf)
161{
162 APIC_DSH DestinationShortHand = IncludeSelf ?
164
165 /* Request the interrupt targeted at all processors */
166 ApicRequestGlobalInterrupt(0, // Ignored
167 Vector,
170 DestinationShortHand);
171}
172
181VOID
182NTAPI
184 _In_ KAFFINITY TargetSet,
186{
187 KAFFINITY ActiveProcessors = HalpActiveProcessors;
188 KAFFINITY RemainingSet, SetMember;
189 ULONG ProcessorIndex;
190 ULONG LApicId;
191
192 /* Sanitize the target set */
193 TargetSet &= ActiveProcessors;
194
195 /* Check if all processors are requested */
196 if (TargetSet == ActiveProcessors)
197 {
198 /* Send an IPI to all processors, including this processor */
200 return;
201 }
202
203 /* Check if all processors except the current one are requested */
204 if (TargetSet == (ActiveProcessors & ~KeGetCurrentPrcb()->SetMember))
205 {
206 /* Send an IPI to all processors, excluding this processor */
208 return;
209 }
210
211 /* Loop while we have more processors */
212 RemainingSet = TargetSet;
213 while (RemainingSet != 0)
214 {
215 NT_VERIFY(BitScanForwardAffinity(&ProcessorIndex, RemainingSet) != 0);
216 ASSERT(ProcessorIndex < KeNumberProcessors);
217 SetMember = AFFINITY_MASK(ProcessorIndex);
218 RemainingSet &= ~SetMember;
219
220 /* Send the interrupt to the target processor */
221 LApicId = HalpProcessorIdentity[ProcessorIndex].LapicId;
223 Vector,
227 }
228}
229
235VOID
236NTAPI
238 _In_ KAFFINITY TargetSet)
239{
240 /* Request the IPI vector */
242}
243
244#ifdef _M_AMD64
245
252VOID
253NTAPI
254HalpSendSoftwareInterrupt(
255 _In_ KAFFINITY TargetSet,
257{
259
260 /* Get the vector for the requested IRQL */
261 if (Irql == APC_LEVEL)
262 {
264 }
265 else if (Irql == DISPATCH_LEVEL)
266 {
268 }
269 else
270 {
271 ASSERT(FALSE);
272 return;
273 }
274
275 /* Request the IPI with the specified vector */
277}
278
284VOID
285NTAPI
286HalpSendNMI(
287 _In_ KAFFINITY TargetSet)
288{
289 KAFFINITY RemainingSet, SetMember;
290 ULONG ProcessorIndex;
291 ULONG LApicId;
292
293 /* Make sure we do not send an NMI to ourselves */
294 ASSERT((TargetSet & KeGetCurrentPrcb()->SetMember) == 0);
295
296 /* Loop while we have more processors */
297 RemainingSet = TargetSet;
298 while (RemainingSet != 0)
299 {
300 NT_VERIFY(BitScanForwardAffinity(&ProcessorIndex, RemainingSet) != 0);
301 ASSERT(ProcessorIndex < KeNumberProcessors);
302 SetMember = AFFINITY_MASK(ProcessorIndex);
303 RemainingSet &= ~SetMember;
304
305 /* Send and NMI to the target processor */
306 LApicId = HalpProcessorIdentity[ProcessorIndex].LapicId;
308 0,
312 }
313}
314
315#endif // _M_AMD64
#define EFLAGS_INTERRUPT_MASK
unsigned char BOOLEAN
Definition: actypes.h:127
ULONG ApicVersion
Definition: apic.c:27
@ APIC_DM_Physical
Definition: apicp.h:147
#define APC_VECTOR
Definition: apicp.h:42
@ APIC_DSH_AllIncludingSelf
Definition: apicp.h:156
@ APIC_DSH_Destination
Definition: apicp.h:154
@ APIC_DSH_AllExcludingSelf
Definition: apicp.h:157
@ APIC_MT_INIT
Definition: apicp.h:132
@ APIC_MT_Fixed
Definition: apicp.h:127
@ APIC_MT_NMI
Definition: apicp.h:131
@ APIC_MT_Startup
Definition: apicp.h:133
#define APIC_IPI_VECTOR
Definition: apicp.h:48
enum _APIC_MT APIC_MT
#define DISPATCH_VECTOR
Definition: apicp.h:43
FORCEINLINE ULONG ApicRead(APIC_REGISTER Register)
Definition: apicp.h:318
FORCEINLINE VOID ApicWrite(APIC_REGISTER Register, ULONG Value)
Definition: apicp.h:325
enum _APIC_TGM APIC_TGM
@ APIC_ICR0
Definition: apicp.h:96
@ APIC_VER
Definition: apicp.h:83
@ APIC_ICR1
Definition: apicp.h:97
enum _APIC_DSH APIC_DSH
@ APIC_TGM_Level
Definition: apicp.h:141
@ APIC_TGM_Edge
Definition: apicp.h:140
FORCEINLINE VOID ApicRequestGlobalInterrupt(_In_ UCHAR DestinationProcessor, _In_ UCHAR Vector, _In_ APIC_MT MessageType, _In_ APIC_TGM TriggerMode, _In_ APIC_DSH DestinationShortHand)
Definition: apicsmp.c:60
VOID ApicStartApplicationProcessor(_In_ ULONG NTProcessorNumber, _In_ PHYSICAL_ADDRESS StartupLoc)
Definition: apicsmp.c:107
VOID NTAPI HalpRequestIpi(_In_ KAFFINITY TargetSet)
Requests an IPI interrupt on the specified processors.
Definition: apicsmp.c:237
VOID NTAPI HalRequestIpiSpecifyVector(_In_ KAFFINITY TargetSet, _In_ UCHAR Vector)
Requests an IPI with a specified vector on the specified processors.
Definition: apicsmp.c:183
VOID NTAPI HalpBroadcastIpiSpecifyVector(_In_ UCHAR Vector, _In_ BOOLEAN IncludeSelf)
Broadcasts an IPI with a specified vector to all processors.
Definition: apicsmp.c:158
_Out_ PKIRQL Irql
Definition: csq.h:179
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ULONG_PTR KAFFINITY
Definition: compat.h:85
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
KAFFINITY HalpActiveProcessors
Definition: processor.c:17
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1706
PROCESSOR_IDENTITY HalpProcessorIdentity[MAXIMUM_PROCESSORS]
Definition: madt.c:24
#define ASSERT(a)
Definition: mode.c:44
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1197
FORCEINLINE KAFFINITY AFFINITY_MASK(ULONG Index)
Definition: kefuncs.h:39
FORCEINLINE BOOLEAN BitScanForwardAffinity(PULONG Index, KAFFINITY Mask)
Definition: kefuncs.h:45
#define _In_
Definition: no_sal2.h:158
CCHAR KeNumberProcessors
Definition: processor.c:19
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
ULONG LapicId
Definition: smp.h:14
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3311