windows-nt/Source/XPSP1/NT/base/ntos/ke/ia64/mpipi.c

417 lines
8.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
mpipi.c
Abstract:
This module implements MIPS specific MP routine.
Author:
Bernard Lint 26-Jun-1996
Environment:
Kernel mode only.
Revision History:
Based on version of David N. Cutler 24-Apr-1993
--*/
#include "ki.h"
VOID
KiSaveHigherFPVolatile (
PFLOAT128 SaveArea
);
VOID
KiRestoreProcessorState (
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame
)
/*++
Routine Description:
This function moves processor register state from the current
processor context structure in the processor block to the
specified trap and exception frames.
Arguments:
TrapFrame - Supplies a pointer to a trap frame.
ExceptionFrame - Supplies a pointer to an exception frame.
Return Value:
None.
--*/
{
#if !defined(NT_UP)
PKPRCB Prcb;
//
// Get the address of the current processor block and move the
// specified register state from the processor context structure
// to the specified trap and exception frames
//
Prcb = KeGetCurrentPrcb();
KeContextToKframes(TrapFrame,
ExceptionFrame,
&Prcb->ProcessorState.ContextFrame,
CONTEXT_FULL,
(KPROCESSOR_MODE)TrapFrame->PreviousMode);
KiRestoreProcessorControlState(&Prcb->ProcessorState);
#endif // !defined(NT_UP)
return;
}
VOID
KiSaveProcessorState (
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame
)
/*++
Routine Description:
This function moves processor register state from the specified trap
and exception frames to the processor context structure in the current
processor block.
Arguments:
TrapFrame - Supplies a pointer to a trap frame.
ExceptionFrame - Supplies a pointer to an exception frame.
Return Value:
None.
--*/
{
#if !defined(NT_UP)
PKPRCB Prcb;
//
// Get the address of the current processor block and move the
// specified register state from specified trap and exception
// frames to the current processor context structure.
//
Prcb = KeGetCurrentPrcb();
if (KeGetCurrentThread()->Teb) {
KiSaveHigherFPVolatile((PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase));
}
Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL;
KeContextFromKframes(TrapFrame,
ExceptionFrame,
&Prcb->ProcessorState.ContextFrame);
//
// Save ISR in special registers
//
Prcb->ProcessorState.SpecialRegisters.StISR = TrapFrame->StISR;
//
// Save the current processor control state.
//
KiSaveProcessorControlState(&Prcb->ProcessorState);
#endif // !defined(NT_UP)
return;
}
BOOLEAN
KiIpiServiceRoutine (
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame
)
/*++
Routine Description:
This function is called at IPI_LEVEL to process any outstanding
interprocess request for the current processor.
Arguments:
TrapFrame - Supplies a pointer to a trap frame.
ExceptionFrame - Supplies a pointer to an exception frame
Return Value:
A value of TRUE is returned, if one of more requests were service.
Otherwise, FALSE is returned.
--*/
{
#if !defined(NT_UP)
ULONG RequestSummary;
//
// Process any outstanding IPI requests
//
RequestSummary = KiIpiProcessRequests();
//
// If freeze is requested, then freeze target execution.
//
if ((RequestSummary & IPI_FREEZE) != 0) {
KiFreezeTargetExecution(TrapFrame, ExceptionFrame);
}
return ((RequestSummary & ~IPI_FREEZE) != 0);
#else
return TRUE;
#endif // !defined(NT_UP)
}
ULONG
KiIpiProcessRequests (
VOID
)
/*++
Routine Description:
This routine processes interprocessor requests and returns a summary
of the requests that were processed.
Arguments:
None.
Return Value:
The request summary is returned as the function value.
--*/
{
#if !defined(NT_UP)
ULONG RequestSummary;
PKPRCB SignalDone;
PKPRCB Prcb = KeGetCurrentPrcb();
RequestSummary = (ULONG)InterlockedExchange((PLONG)&Prcb->RequestSummary, 0);
//
// If a packet is ready, then get the address of the requested function
// and call the function passing the address of the packet address as a
// parameter.
//
SignalDone = (PKPRCB)( (ULONG_PTR)Prcb->SignalDone & ~(ULONG_PTR)1 );
if (SignalDone != 0) {
Prcb->SignalDone = 0;
(*SignalDone->WorkerRoutine) ((PKIPI_CONTEXT)SignalDone,
SignalDone->CurrentPacket[0],
SignalDone->CurrentPacket[1],
SignalDone->CurrentPacket[2]);
}
if ((RequestSummary & IPI_APC) != 0) {
KiRequestSoftwareInterrupt (APC_LEVEL);
} else if ((RequestSummary & IPI_DPC) != 0) {
KiRequestSoftwareInterrupt (DISPATCH_LEVEL);
}
return RequestSummary;
#else
return 0;
#endif // !defined(NT_UP)
}
VOID
KiIpiSend (
IN KAFFINITY TargetProcessors,
IN KIPI_REQUEST IpiRequest
)
/*++
Routine Description:
This routine requests the specified operation on the target set of
processors.
Arguments:
TargetProcessors (a0) - Supplies the set of processors on which the
specified operation is to be executed.
IpiRequest (a1) - Supplies the request operation mask.
Return Value:
None.
--*/
{
#if !defined(NT_UP)
ULONG RequestSummary;
KAFFINITY NextProcessors;
ULONG Next;
//
// Loop through the target processors and send the packet to the specified
// recipients.
//
NextProcessors = TargetProcessors;
Next = 0;
while (NextProcessors != 0) {
if ((NextProcessors & 1) != 0) {
do {
RequestSummary = KiProcessorBlock[Next]->RequestSummary;
} while(InterlockedCompareExchange(
(PLONG) &KiProcessorBlock[Next]->RequestSummary,
(LONG) (RequestSummary | IpiRequest),
(LONG) RequestSummary) != (LONG) RequestSummary);
}
NextProcessors = NextProcessors >> 1;
Next = Next + 1;
}
HalRequestIpi (TargetProcessors);
#endif
return;
}
VOID
KiIpiSendPacket (
IN KAFFINITY TargetProcessors,
IN PKIPI_WORKER WorkerFunction,
IN PVOID Parameter1,
IN PVOID Parameter2,
IN PVOID Parameter3
)
/*++
Routine Description:
This routine executes the specified worker function on the specified
set of processors.
Arguments:
TargetProcessors (a0) - Supplies the set of processors on which the
specified operation is to be executed.
WorkerFunction (a1) - Supplies the address of the worker function.
Parameter1 - Parameter3 (a2, a3, 4 * 4(sp)) - Supplies worker
function specific parameters.
Return Value:
None.
--*/
{
#if !defined(NT_UP)
PKPRCB Prcb;
KAFFINITY NextProcessors;
ULONG Next;
Prcb = KeGetCurrentPrcb();
Prcb->TargetSet = TargetProcessors;
Prcb->WorkerRoutine = WorkerFunction;
Prcb->CurrentPacket[0] = Parameter1;
Prcb->CurrentPacket[1] = Parameter2;
Prcb->CurrentPacket[2] = Parameter3;
//
// synchronize memory access
//
__mf();
//
// The low order bit of the packet address is set if there is
// exactly one target recipient. Otherwise, the low order bit
// of the packet address is clear.
//
if (((TargetProcessors) & ((TargetProcessors) - 1)) == 0) {
(ULONG_PTR) Prcb |= 0x1;
} else {
Prcb->PacketBarrier = 1;
}
//
// Loop through the target processors and send the packet to the specified
// recipients.
//
NextProcessors = TargetProcessors;
Next = 0;
while (NextProcessors != 0) {
if ((NextProcessors & 1) != 0) {
while(InterlockedCompareExchangePointer(
(PVOID)&KiProcessorBlock[Next]->SignalDone,
(PVOID)Prcb,
(PVOID)0) != (PVOID)0);
}
NextProcessors = NextProcessors >> 1;
Next = Next + 1;
}
HalRequestIpi (TargetProcessors);
#endif
}