mirror of
https://github.com/reactos/reactos.git
synced 2024-11-23 03:23:34 +08:00
[HAL] Implement IPI support functions
This commit is contained in:
parent
4bccb6e6c9
commit
40b6b1dab3
@ -41,8 +41,8 @@
|
||||
@ stdcall HalRequestIpi(long)
|
||||
@ fastcall HalRequestSoftwareInterrupt(long)
|
||||
@ stdcall HalReturnToFirmware(long)
|
||||
;@ stdcall -arch=x86_64 HalSendNMI()
|
||||
;@ stdcall -arch=x86_64 HalSendSoftwareInterrupt()
|
||||
@ stdcall -arch=x86_64 HalSendNMI(int64)
|
||||
@ stdcall -arch=x86_64 HalSendSoftwareInterrupt(int64 long)
|
||||
@ stdcall HalSetBusData(long long long ptr long)
|
||||
@ stdcall HalSetBusDataByOffset(long long long ptr long long)
|
||||
@ stdcall HalSetDisplayParameters(long long)
|
||||
|
@ -151,7 +151,7 @@ typedef enum _APIC_DSH
|
||||
APIC_DSH_Destination,
|
||||
APIC_DSH_Self,
|
||||
APIC_DSH_AllIncludingSelf,
|
||||
APIC_DSH_AllExclusingSelf
|
||||
APIC_DSH_AllExcludingSelf
|
||||
} APIC_DSH;
|
||||
|
||||
/* Write Constants */
|
||||
|
@ -106,14 +106,6 @@ ApicRequestGlobalInterrupt(
|
||||
|
||||
/* SMP SUPPORT FUNCTIONS ******************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpRequestIpi(_In_ KAFFINITY TargetProcessors)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
VOID
|
||||
ApicStartApplicationProcessor(
|
||||
_In_ ULONG NTProcessorNumber,
|
||||
@ -138,3 +130,172 @@ ApicStartApplicationProcessor(
|
||||
ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, (StartupLoc.LowPart) >> 12,
|
||||
APIC_MT_Startup, APIC_TGM_Edge, APIC_DSH_Destination);
|
||||
}
|
||||
|
||||
/* HAL IPI FUNCTIONS **********************************************************/
|
||||
|
||||
/*!
|
||||
* \brief Broadcasts an IPI with a specified vector to all processors.
|
||||
*
|
||||
* \param Vector - Specifies the interrupt vector to be delivered.
|
||||
* \param IncludeSelf - Specifies whether to include the current processor.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalpBroadcastIpiSpecifyVector(
|
||||
_In_ UCHAR Vector,
|
||||
_In_ BOOLEAN IncludeSelf)
|
||||
{
|
||||
APIC_DSH DestinationShortHand = IncludeSelf ?
|
||||
APIC_DSH_AllIncludingSelf : APIC_DSH_AllExcludingSelf;
|
||||
|
||||
/* Request the interrupt targeted at all processors */
|
||||
ApicRequestGlobalInterrupt(0, // Ignored
|
||||
Vector,
|
||||
APIC_MT_Fixed,
|
||||
APIC_TGM_Edge,
|
||||
DestinationShortHand);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Requests an IPI with a specified vector on the specified processors.
|
||||
*
|
||||
* \param TargetSet - Specifies the set of processors to send the IPI to.
|
||||
* \param Vector - Specifies the interrupt vector to be delivered.
|
||||
*
|
||||
* \remarks This function is exported on Windows 10.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalRequestIpiSpecifyVector(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ UCHAR Vector)
|
||||
{
|
||||
KAFFINITY ActiveProcessors = KeQueryActiveProcessors();
|
||||
KAFFINITY RemainingSet, SetMember;
|
||||
ULONG ProcessorIndex;
|
||||
ULONG LApicId;
|
||||
|
||||
/* Sanitize the target set */
|
||||
TargetSet &= ActiveProcessors;
|
||||
|
||||
/* Check if all processors are requested */
|
||||
if (TargetSet == ActiveProcessors)
|
||||
{
|
||||
/* Send an IPI to all processors, including this processor */
|
||||
HalpBroadcastIpiSpecifyVector(Vector, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if all processors except the current one are requested */
|
||||
if (TargetSet == (ActiveProcessors & ~KeGetCurrentPrcb()->SetMember))
|
||||
{
|
||||
/* Send an IPI to all processors, excluding this processor */
|
||||
HalpBroadcastIpiSpecifyVector(Vector, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Loop while we have more processors */
|
||||
RemainingSet = TargetSet;
|
||||
while (RemainingSet != 0)
|
||||
{
|
||||
NT_VERIFY(BitScanForwardAffinity(&ProcessorIndex, RemainingSet) != 0);
|
||||
ASSERT(ProcessorIndex < KeNumberProcessors);
|
||||
SetMember = AFFINITY_MASK(ProcessorIndex);
|
||||
RemainingSet &= ~SetMember;
|
||||
|
||||
/* Send the interrupt to the target processor */
|
||||
LApicId = HalpProcessorIdentity[ProcessorIndex].LapicId;
|
||||
ApicRequestGlobalInterrupt(LApicId,
|
||||
Vector,
|
||||
APIC_MT_Fixed,
|
||||
APIC_TGM_Edge,
|
||||
APIC_DSH_Destination);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Requests an IPI interrupt on the specified processors.
|
||||
*
|
||||
* \param TargetSet - Specifies the set of processors to send the IPI to.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalpRequestIpi(
|
||||
_In_ KAFFINITY TargetSet)
|
||||
{
|
||||
/* Request the IPI vector */
|
||||
HalRequestIpiSpecifyVector(TargetSet, APIC_IPI_VECTOR);
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
/*!
|
||||
* \brief Requests a software interrupt on the specified processors.
|
||||
*
|
||||
* \param TargetSet - Specifies the set of processors to send the IPI to.
|
||||
* \param Irql - Specifies the IRQL of the software interrupt.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalpSendSoftwareInterrupt(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ KIRQL Irql)
|
||||
{
|
||||
UCHAR Vector;
|
||||
|
||||
/* Get the vector for the requested IRQL */
|
||||
if (Irql == APC_LEVEL)
|
||||
{
|
||||
Vector = APC_VECTOR;
|
||||
}
|
||||
else if (Irql == DISPATCH_LEVEL)
|
||||
{
|
||||
Vector = DISPATCH_VECTOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Request the IPI with the specified vector */
|
||||
HalRequestIpiSpecifyVector(TargetSet, Vector);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Requests an NMI interrupt on the specified processors.
|
||||
*
|
||||
* \param TargetSet - Specifies the set of processors to send the IPI to.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
HalpSendNMI(
|
||||
_In_ KAFFINITY TargetSet)
|
||||
{
|
||||
KAFFINITY RemainingSet, SetMember;
|
||||
ULONG ProcessorIndex;
|
||||
ULONG LApicId;
|
||||
|
||||
/* Make sure we do not send an NMI to ourselves */
|
||||
ASSERT((TargetSet & ~KeGetCurrentPrcb()->SetMember) == 0);
|
||||
|
||||
/* Loop while we have more processors */
|
||||
RemainingSet = TargetSet;
|
||||
while (RemainingSet != 0)
|
||||
{
|
||||
NT_VERIFY(BitScanForwardAffinity(&ProcessorIndex, RemainingSet) != 0);
|
||||
ASSERT(ProcessorIndex < KeNumberProcessors);
|
||||
SetMember = AFFINITY_MASK(ProcessorIndex);
|
||||
RemainingSet &= ~SetMember;
|
||||
|
||||
/* Send and NMI to the target processor */
|
||||
LApicId = HalpProcessorIdentity[ProcessorIndex].LapicId;
|
||||
ApicRequestGlobalInterrupt(LApicId,
|
||||
0,
|
||||
APIC_MT_NMI,
|
||||
APIC_TGM_Edge,
|
||||
APIC_DSH_Destination);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _M_AMD64
|
||||
|
@ -32,3 +32,22 @@ HalStartNextProcessor(
|
||||
/* Always return false on UP systems */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendNMI(
|
||||
_In_ KAFFINITY TargetSet)
|
||||
{
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendSoftwareInterrupt(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ KIRQL Irql)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // _M_AMD64
|
||||
|
@ -7,6 +7,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AFFINITY_MASK(Id) ((KAFFINITY)1 << (Id))
|
||||
|
||||
/* Helper to find the lowest CPU in a KAFFINITY */
|
||||
#ifdef _WIN64
|
||||
#define BitScanForwardAffinity BitScanForward64
|
||||
#else
|
||||
#define BitScanForwardAffinity BitScanForward
|
||||
#endif
|
||||
|
||||
/* This table is filled for each physical processor on system */
|
||||
typedef struct _PROCESSOR_IDENTITY
|
||||
{
|
||||
@ -53,3 +62,32 @@ VOID
|
||||
NTAPI
|
||||
HalpRequestIpi(
|
||||
_In_ KAFFINITY TargetProcessors);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpBroadcastIpiSpecifyVector(
|
||||
_In_ UCHAR Vector,
|
||||
_In_ BOOLEAN IncludeSelf);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalRequestIpiSpecifyVector(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ UCHAR Vector);
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
NTHALAPI
|
||||
VOID
|
||||
NTAPI
|
||||
HalpSendNMI(
|
||||
_In_ KAFFINITY TargetSet);
|
||||
|
||||
NTHALAPI
|
||||
VOID
|
||||
NTAPI
|
||||
HalpSendSoftwareInterrupt(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ KIRQL Irql);
|
||||
|
||||
#endif // _M_AMD64
|
||||
|
@ -22,3 +22,27 @@ HalRequestIpi(
|
||||
{
|
||||
HalpRequestIpi(TargetProcessors);
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendNMI(
|
||||
_In_ KAFFINITY TargetSet)
|
||||
{
|
||||
HalpSendNMI(TargetSet);
|
||||
}
|
||||
|
||||
// See:
|
||||
// - https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h#L53
|
||||
// https://github.com/mirror/vbox/blob/b9657cd5351cf17432b664009cc25bb480dc64c1/src/VBox/Runtime/r0drv/nt/mp-r0drv-nt.cpp#L683
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendSoftwareInterrupt(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ KIRQL Irql)
|
||||
{
|
||||
HalpSendSoftwareInterrupt(TargetSet, Irql);
|
||||
}
|
||||
|
||||
#endif // _M_AMD64
|
||||
|
@ -192,6 +192,23 @@ HalRequestSoftwareInterrupt(
|
||||
_In_ KIRQL SoftwareInterruptRequested
|
||||
);
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
NTHALAPI
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendNMI(
|
||||
_In_ KAFFINITY TargetSet);
|
||||
|
||||
NTHALAPI
|
||||
VOID
|
||||
NTAPI
|
||||
HalSendSoftwareInterrupt(
|
||||
_In_ KAFFINITY TargetSet,
|
||||
_In_ KIRQL Irql);
|
||||
|
||||
#endif // _M_AMD64
|
||||
|
||||
NTHALAPI
|
||||
VOID
|
||||
NTAPI
|
||||
|
Loading…
Reference in New Issue
Block a user