|
|
/*++
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
}
|