You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
437 lines
9.3 KiB
437 lines
9.3 KiB
/*++
|
|
|
|
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);
|
|
#else
|
|
UNREFERENCED_PARAMETER (TrapFrame);
|
|
UNREFERENCED_PARAMETER (ExceptionFrame);
|
|
#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);
|
|
#else
|
|
UNREFERENCED_PARAMETER (TrapFrame);
|
|
UNREFERENCED_PARAMETER (ExceptionFrame);
|
|
#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 ? TRUE : FALSE);
|
|
|
|
#else
|
|
UNREFERENCED_PARAMETER (TrapFrame);
|
|
UNREFERENCED_PARAMETER (ExceptionFrame);
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
#else
|
|
UNREFERENCED_PARAMETER (TargetProcessors);
|
|
UNREFERENCED_PARAMETER (IpiRequest);
|
|
#endif // !defined(NT_UP)
|
|
|
|
|
|
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) {
|
|
Prcb = (PKPRCB)((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);
|
|
#else
|
|
UNREFERENCED_PARAMETER (TargetProcessors);
|
|
UNREFERENCED_PARAMETER (WorkerFunction);
|
|
UNREFERENCED_PARAMETER (Parameter1);
|
|
UNREFERENCED_PARAMETER (Parameter2);
|
|
UNREFERENCED_PARAMETER (Parameter3);
|
|
#endif
|
|
}
|