mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 17:14:41 +00:00
[HAL] Implement IPI support functions
This commit is contained in:
parent
4bccb6e6c9
commit
40b6b1dab3
7 changed files with 270 additions and 11 deletions
|
@ -41,8 +41,8 @@
|
||||||
@ stdcall HalRequestIpi(long)
|
@ stdcall HalRequestIpi(long)
|
||||||
@ fastcall HalRequestSoftwareInterrupt(long)
|
@ fastcall HalRequestSoftwareInterrupt(long)
|
||||||
@ stdcall HalReturnToFirmware(long)
|
@ stdcall HalReturnToFirmware(long)
|
||||||
;@ stdcall -arch=x86_64 HalSendNMI()
|
@ stdcall -arch=x86_64 HalSendNMI(int64)
|
||||||
;@ stdcall -arch=x86_64 HalSendSoftwareInterrupt()
|
@ stdcall -arch=x86_64 HalSendSoftwareInterrupt(int64 long)
|
||||||
@ stdcall HalSetBusData(long long long ptr long)
|
@ stdcall HalSetBusData(long long long ptr long)
|
||||||
@ stdcall HalSetBusDataByOffset(long long long ptr long long)
|
@ stdcall HalSetBusDataByOffset(long long long ptr long long)
|
||||||
@ stdcall HalSetDisplayParameters(long long)
|
@ stdcall HalSetDisplayParameters(long long)
|
||||||
|
|
|
@ -151,7 +151,7 @@ typedef enum _APIC_DSH
|
||||||
APIC_DSH_Destination,
|
APIC_DSH_Destination,
|
||||||
APIC_DSH_Self,
|
APIC_DSH_Self,
|
||||||
APIC_DSH_AllIncludingSelf,
|
APIC_DSH_AllIncludingSelf,
|
||||||
APIC_DSH_AllExclusingSelf
|
APIC_DSH_AllExcludingSelf
|
||||||
} APIC_DSH;
|
} APIC_DSH;
|
||||||
|
|
||||||
/* Write Constants */
|
/* Write Constants */
|
||||||
|
|
|
@ -106,14 +106,6 @@ ApicRequestGlobalInterrupt(
|
||||||
|
|
||||||
/* SMP SUPPORT FUNCTIONS ******************************************************/
|
/* SMP SUPPORT FUNCTIONS ******************************************************/
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
HalpRequestIpi(_In_ KAFFINITY TargetProcessors)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
__debugbreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
ApicStartApplicationProcessor(
|
ApicStartApplicationProcessor(
|
||||||
_In_ ULONG NTProcessorNumber,
|
_In_ ULONG NTProcessorNumber,
|
||||||
|
@ -138,3 +130,172 @@ ApicStartApplicationProcessor(
|
||||||
ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, (StartupLoc.LowPart) >> 12,
|
ApicRequestGlobalInterrupt(HalpProcessorIdentity[NTProcessorNumber].LapicId, (StartupLoc.LowPart) >> 12,
|
||||||
APIC_MT_Startup, APIC_TGM_Edge, APIC_DSH_Destination);
|
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 */
|
/* Always return false on UP systems */
|
||||||
return FALSE;
|
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
|
#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 */
|
/* This table is filled for each physical processor on system */
|
||||||
typedef struct _PROCESSOR_IDENTITY
|
typedef struct _PROCESSOR_IDENTITY
|
||||||
{
|
{
|
||||||
|
@ -53,3 +62,32 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
HalpRequestIpi(
|
HalpRequestIpi(
|
||||||
_In_ KAFFINITY TargetProcessors);
|
_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);
|
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
|
_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
|
NTHALAPI
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
Loading…
Reference in a new issue