windows-nt/Source/XPSP1/NT/base/ntos/ke/alpha/mpipi.s
2020-09-26 16:20:57 +08:00

630 lines
17 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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_BLOCK_BASE // get current prcb address
#if NT_INST
LDP s1, PbIpiCounts(v0) // get interrupt count structure address
#endif
10: ldq_l s0, PbRequestSummary(v0) // get request summary and entry address
bis zero, zero, t1 // set zero value for store
stq_c t1, PbRequestSummary(v0) // zero request summary, conditionally
beq t1, 15f // if eq, store conditional failed
sra s0, 16, 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
bic a0, 1, v0 // clear low order packet address bit
LDP t2, PbWorkerRoutine(v0) // get address of worker function
LDP a1, PbCurrentPacket(v0) // get request parameters
#if defined(_AXP64_)
ldq a2, PbCurrentPacket + 8(v0) //
ldq a3, PbCurrentPacket + 16(v0) //
#else
ldl a2, PbCurrentPacket + 4(v0) //
ldl a3, PbCurrentPacket + 8(v0) //
#endif
jsr ra, (t2) // call worker routine
mb // synchronize memory access
#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 // request DPC 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
//
// Conditional store failed.
//
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 lbc, target processor not set
LDP 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
#if defined(_AXP64_)
lda t1, 8(t1) // get next processor block element
#else
lda t1, 4(t1) // get next processor block element
#endif
bne t0, 10b // if ne, more targets requested
mb // synchronize memory access
LDP t0, __imp_HalRequestIpi // request IPI interrupt on targets
jmp zero, (t0) //
#else
ret zero, (ra) // simply return for uni-processor
#endif
//
// Conditional store failed.
//
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 // get current prcb 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
STP a1, PbWorkerRoutine(v0) // set worker function address
STP a2, PbCurrentPacket(v0) // store worker function parameters
#if defined(_AXP64_)
stq a3, PbCurrentPacket + 8(v0) //
stq a4, PbCurrentPacket + 16(v0) //
#else
stl a3, PbCurrentPacket + 4(v0) //
stl a4, PbCurrentPacket + 8(v0) //
#endif
subl a0, 1, a1 // compute target set - 1
and a1, a0, a1 // and target set with target set - 1
zapnot a1, 0xf, a1 // clear upper 32 bits
cmpeq a1, zero, a1 // compare if result is zero
bne a1, 5f // if ne, one and only one bit set
stl a0, PbPacketBarrier(v0) // set packet barrier
5: mb // synchronize memory access
ADDP v0, a1, v0 // set low bit if appropriate
//
// Loop through the target processors and send the packet to the specified
// recipients.
//
10: blbc t1, 30f // if eq, target not specified
LDP t0, 0(t2) // get target processor block address
sll v0, 16, t3 // shift packet address into position
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
#if defined(_AXP64_)
30: lda t2, 8(t2) // advance to next array element
#else
30: lda t2, 4(t2) // advance to next array element
#endif
srl t1, 1, t1 // shift to next target
bne t1, 10b // if ne, more targets to process
mb // synchronize memory access
LDP t0, __imp_HalRequestIpi // request IPI interrupt on targets
jmp zero, (t0) //
//
// Packet not ready, spin in cache until it looks available.
//
25: 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("Restore Processor Control State")
//++
//
// VOID
// KiRestoreProcessorControlState (
// IN PKPROCESSOR_STATE ProcessorState
// );
//
// Routine Description:
//
// This routine restores the processor control state for the debugger.
//
// Arguments:
//
// ProcessorState (a0) - Pointer to PROCSSOR_STATE
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreProcessorControlState)
ret zero, (ra) // return
.end KiRestoreProcessorControlState
SBTTL("Save Processor Control State")
//++
//
// VOID
// KiSaveProcessorControlState (
// IN PKPROCESSOR_STATE ProcessorState
// );
//
// Routine Description:
//
// This routine saves the processor control state for the debugger.
//
// Arguments:
//
// ProcessorState (a0) - Pointer to PROCSSOR_STATE
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiSaveProcessorControlState)
ret zero, (ra) // return
.end KiSaveProcessorControlState
SBTTL("Signal Packet Done")
//++
//
// VOID
// KiIpiSignalPacketDone (
// IN PKIPI_CONTEXT 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.
//
//--
#if !defined(NT_UP)
LEAF_ENTRY(KiIpiSignalPacketDone)
GET_PROCESSOR_CONTROL_REGION_BASE // get current pcr address
blbs a0, 30f // if lbs, one and only one bit set
ldl a1, PcSetMember(v0) // get processor set member
mb // synchronize memory access
10: ldl_l a2, PbTargetSet(a0) // get request target set
bic a2, a1, a2 // clear processor set member
mov a2, v0 // save result target set
stl_c a2, PbTargetSet(a0) // store target set
beq a2, 10b // if eq, store conditional failed
bne v0, 20f // if ne, more targets to go
stl zero, PbPacketBarrier(a0) // clear packet barrier
mb // synchronize memory access
20: ret zero, (ra) // return
30: stl zero, PbTargetSet - 1(a0) // clear target set
mb // synchronize memory access
ret zero, (ra) //
.end KiIpiSignalPacketDone
#endif
SBTTL("Read Memory Barrier Time Stamp")
//++
//
// ULONG
// KeReadMbTimeStamp (
// VOID
// );
//
// Routine Description:
//
// This routine reads the current memory bazrrier time stamp value.
//
// Arguments:
//
// None.
//
// Return Value:
//
// The current value of the memory barrier time stamp is returned as the
// function value.
//
//--
#if !defined(NT_UP)
LEAF_ENTRY(KeReadMbTimeStamp)
ldl_l v0,KiMbTimeStamp // read current memory barrier time stamp
ret zero, (ra) // return
.end KeReadMbTimeStamp
#endif