Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

546 lines
14 KiB

// TITLE("Interprocessor Interrupt support routines")
//++
//
// Copyright (c) 1993 Microsoft Corporation
// Copyright (c) 1993 Digital Equipment Corporation
//
// Module Name:
//
// mpipi.s
//
// Abstract:
//
// This module implements the Alpha AXP specific functions required to
// support multiprocessor systems.
//
// Author:
//
// David N. Cutler (davec) 22-Apr-1993
// Joe Notarangelo 29-Nov-1993
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksalpha.h"
SBTTL("Interprocess Interrupt Processing")
//++
//
// VOID
// KeIpiInterrupt (
// IN PKTRAP_FRAME TrapFrame
// );
//
// Routine Description:
//
// This routine is entered as the result of an interprocessor interrupt.
// It's function is to process all interprocess immediate and packet
// requests.
//
// Arguments:
//
// TrapFrame (fp/s6) - Supplies a pointer to a trap frame.
//
// Return Value:
//
// None.
//
//--
NESTED_ENTRY(KeIpiInterrupt, ExceptionFrameLength, zero)
lda sp, -ExceptionFrameLength(sp) // allocate exception frame
stq ra, ExIntRa(sp) // save return address
PROLOGUE_END
//
// Process all interprocessor requests.
//
bsr ra, KiIpiProcessRequests // process requests
and v0, IPI_FREEZE, t0 // check if freeze is requested
beq t0, 10f // if eq, no freeze requested
//
// Save the volatile floating state, the nonvolatile floating state,
// and the nonvolatile integer state.
//
bsr ra, KiSaveVolatileFloatState // save volatile float in trap
bsr ra, KiSaveNonVolatileFloatState // save nv float in exception
stq s0, ExIntS0(sp) // save nonvolatile integer state
stq s1, ExIntS1(sp) //
stq s2, ExIntS2(sp) //
stq s3, ExIntS3(sp) //
stq s4, ExIntS4(sp) //
stq s5, ExIntS5(sp) //
stq fp, ExIntFp(sp) //
//
// Freeze the execution of the current processor.
//
bis fp, zero, a0 // set address of trap frame
bis sp, zero, a1 // set address of exception frame
bsr ra, KiFreezeTargetExecution // freeze current processor
//
// Restore the volatile floating state, the nonvolatile floating state,
// and the nonvolatile integer state.
//
ldq s0, ExIntS0(sp) // restore nonvolatile integer state
ldq s1, ExIntS1(sp) //
ldq s2, ExIntS2(sp) //
ldq s3, ExIntS3(sp) //
ldq s4, ExIntS4(sp) //
ldq s5, ExIntS5(sp) //
ldq fp, ExIntFp(sp) //
bsr ra, KiRestoreVolatileFloatState // restore volatile float
bsr ra, KiRestoreNonVolatileFloatState // restore nv float state
//
// Cleanup and return to the caller.
//
10:
ldq ra, ExIntRa(sp) // restore return address
lda sp, ExceptionFrameLength(sp) // deallocate exception frame
ret zero, (ra) // return
.end KeIpiInterrupt
SBTTL("Processor Request")
//++
//
// 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.
//
//--
.struct 0
PrS0: .space 8 // saved integer register s0
PrS1: .space 8 // saved integer register s1
.space 8 // fill
PrRa: .space 8 // saved return address
PrFrameLength:
NESTED_ENTRY(KiIpiProcessRequests, PrFrameLength, zero)
lda sp, -PrFrameLength(sp) // allocate stack frame
stq s0, PrS0(sp) // save integer register s0
#if NT_INST
stq s1, PrS1(sp) // save integer register s1
#endif
stq ra, PrRa(sp) // save return address
PROLOGUE_END
//
// Read request summary and write a zero result interlocked.
//
mb // get consistent view of memory
GET_PROCESSOR_CONTROL_REGION_BASE // v0 = Pcr base address
ldl t0, PcPrcb(v0) // get current processor block address
#if NT_INST
ldl s1, PbIpiCounts(t0) // get interrupt count structure
#endif
10:
ldq_l s0, PbRequestSummary(t0) // get request summary and entry address
bis zero, zero, t1 // set zero value for store
stq_c t1, PbRequestSummary(t0) // zero request summary, conditionally
beq t1, 15f // if eq, store conditional failed
sra s0, 32, a0 // shift out entry address
//
// Check for Packet ready.
//
// 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.
//
and s0, IPI_PACKET_READY, t2 // check for packet ready
beq t2, 20f // if eq, no packet ready
ldl t2, PbWorkerRoutine(a0) // get address of worker function
ldl a1, PbCurrentPacket(a0) // get request parameters
ldl a2, PbCurrentPacket +4(a0)
ldl a3, PbCurrentPacket +8(a0)
jsr ra, (t2) // call worker routine
mb
#if NT_INST
ldl t1, IcPacket(s1) // increment number of packet requests
addl t1, 1, t1 //
stl t1, IcPacket(s1) //
#endif
//
// Check for APC interrupt request.
//
// If an APC interrupt is requested, then request a software interrupt at
// APC level on the current processor.
//
20:
and s0, IPI_APC, t1 // check for APC interrupt request
beq t1, 30f // if eq no APC interrupt requested
ldil a0, APC_LEVEL // set interrupt request level
REQUEST_SOFTWARE_INTERRUPT // request APC interrupt
#if NT_INST
ldl t1, IcAPC(s1) // increment number of APC requests
addl t1, 1, t1 //
stl t1, IcAPC(s1) //
#endif
//
// Check for DPC interrupt request.
//
// If a DPC interrupt is requested, then request a software interrupt at
// DPC level on the current processor.
//
30:
and s0, IPI_DPC, t1 // check for DPC interrupt request
beq t1, 40f // if eq, no DPC interrupt requested
ldil a0, DISPATCH_LEVEL // set interrupt request level
REQUEST_SOFTWARE_INTERRUPT
#if NT_INST
ldl t1, IcDPC(s1) // increment number of DPC requests
addl t1, 1, t1 //
stl t1, IcDPC(s1) //
#endif
//
// Set function return value, restore registers, and return.
//
40:
bis s0, zero, v0 // set function return value
ldq s0, PrS0(sp) // restore integer register s0
#if NT_INST
and v0, IPI_FREEZE, t1 // check if freeze requested
beq t1, 50f // if eq, no freeze requested
ldl t1, IcFreeze(s1) // increment number of freeze requests
addl t1, 1, t1 //
stl t1, IcFreeze(s1) //
50:
ldq s1, PrS1(sp) // restore integer register s1
#endif
ldq ra, PrRa(sp) // restore return address
lda sp, PrFrameLength(sp) // deallocate stack frame
ret zero, (ra) // return
15:
br zero, 10b // store conditonal failed, retry
.end KiIpiProcessRequests
SBTTL("Send Interprocess Request")
//++
//
// VOID
// KiIpiSend (
// IN KAFINITY 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.
//
//--
LEAF_ENTRY(KiIpiSend)
#if !defined(NT_UP)
bis a0, zero, t0 // copy target processor set
lda t1, KiProcessorBlock // get processor block array address
10:
blbc t0, 30f // if clear target processor not set
ldl t2, 0(t1) // get target processor block address
//
// Merge the new request into the target processor request summary.
// The store is conditional to ensure that no updates are lost.
//
20:
ldq_l t3, PbRequestSummary(t2) // get target request summary
bis t3, a1, t4 // merge new request with summary
stq_c t4, PbRequestSummary(t2) // set new request summary
beq t4, 25f // if eq, store conditional failed
30:
srl t0, 1, t0 // shift to next target
lda t1, 4(t1) // get next processor block element
bne t0, 10b // if ne, more targets requested
mb
ldl t0, __imp_HalRequestIpi
jmp zero, (t0) // request IPI interrupt on targets
#else
ret zero, (ra) // simply return for uni-processor
#endif
25:
br zero, 20b // store conditional failed, retry
.end KiIpiSend
SBTTL("Send Interprocess Request Packet")
//++
//
// 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 - Supplies arguments for worker.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiIpiSendPacket)
#if !defined(NT_UP)
GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = Prcb base address
bis a0, zero, t1 // copy target processor set
lda t2, KiProcessorBlock // get processor block array address
//
// Store function address and parameters in the packet area of the PRCB on
// the current processor.
//
stl a0, PbTargetSet(v0) // set target processor set
stl a1, PbWorkerRoutine(v0) // set worker function address
stl a2, PbCurrentPacket(v0) // store worker function parameters
stl a3, PbCurrentPacket +4(v0)
stl a4, PbCurrentPacket +8(v0)
//
// Ensure the packet area writes get to memory before any
// request summary is indicated
//
mb
//
// Loop through the target processors and send the packet to the specified
// recipients.
//
10:
blbc t1, 30f // if eq, target not specified
ldl t0, 0(t2) // get target processor block address
sll v0, 32, t3 // shift packet address to upper 32 bits
bis t3, IPI_PACKET_READY, t3 // set packet ready in low 32 bits
20:
ldq_l t4, PbRequestSummary(t0) // get request summary of target
and t4, IPI_PACKET_READY, t6 // check if target packet busy
bne t6, 25f // if ne, target packet busy
bis t4, t3, t4 // set entry address in request summary
stq_c t4, PbRequestSummary(t0) // store request summary and address
beq t4, 20b // if eq, store conditional failed
30:
lda t2, 4(t2) // advance to next array element
srl t1, 1, t1 // shift to next target
bne t1, 10b // if ne, more targets to process
//
// Ensure writes get to memory
//
mb
ldl t0, __imp_HalRequestIpi
jmp zero, (t0) // request IPI interrupt on targets
25:
//
// Packet not ready, spin in cache until it looks available.
//
ldq t4, PbRequestSummary(t0) // get request summary of target
and t4, IPI_PACKET_READY, t6 // check if target packet busy
beq t6, 20b // looks available, try again
br zero, 25b // spin again
#else
ret zero, (ra)
#endif //!NT_UP
.end KiIpiSendPacket
SBTTL("Save Processor Control State")
//++
//
// VOID
// KiSaveProcessorState (
// IN PKPROCESSOR_STATE ProcessorState
// );
//
// Routine Description:
//
// This routine saves the processor's control state for debugger.
//
// Arguments:
//
// ProcessorState (a0) - Pointer to PROCSSOR_STATE
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiSaveProcessorControlState)
ret zero, (ra) // return
.end KiSaveProcessorControlState
#if !defined(NT_UP)
SBTTL("Signal Packet Done")
//++
//
// VOID
// KiIpiSignalPacketDone (
// IN PVOID SignalDone
// );
//
// Routine Description:
//
// This routine signals that a processor has completed a packet by
// clearing the calling processor's set member of the requesting
// processor's packet.
//
// Arguments:
//
// SignalDone (a0) - Supplies a pointer to the processor block of the
// sending processor.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiIpiSignalPacketDone)
GET_PROCESSOR_CONTROL_REGION_BASE
ldl a1, PcSetMember(v0) // get processor set member
mb
10:
ldl_l a2, PbTargetSet(a0) // get request target set
bic a2, a1, a2 // clear processor set member
stl_c a2, PbTargetSet(a0) // store target set
beq a2, 15f // if eq, store conditional failed
ret zero, (ra) // return
15:
br zero, 10b // store conditional failed, retry
.end KiIpiSignalPacketDone
#endif