summaryrefslogtreecommitdiffstats
path: root/private/ntos/ke/alpha/mpipi.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ke/alpha/mpipi.s')
-rw-r--r--private/ntos/ke/alpha/mpipi.s546
1 files changed, 546 insertions, 0 deletions
diff --git a/private/ntos/ke/alpha/mpipi.s b/private/ntos/ke/alpha/mpipi.s
new file mode 100644
index 000000000..95e65f477
--- /dev/null
+++ b/private/ntos/ke/alpha/mpipi.s
@@ -0,0 +1,546 @@
+// 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