summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/alpha/trampoln.s
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/rtl/alpha/trampoln.s
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/rtl/alpha/trampoln.s')
-rw-r--r--private/ntos/rtl/alpha/trampoln.s524
1 files changed, 524 insertions, 0 deletions
diff --git a/private/ntos/rtl/alpha/trampoln.s b/private/ntos/rtl/alpha/trampoln.s
new file mode 100644
index 000000000..b37d471e7
--- /dev/null
+++ b/private/ntos/rtl/alpha/trampoln.s
@@ -0,0 +1,524 @@
+// TITLE("Trampoline Code For User Mode APC and Exception Dispatching")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// trampoln.s
+//
+// Abstract:
+//
+// This module implements the trampoline code necessary to dispatch user
+// mode APCs and exceptions.
+//
+// Author:
+//
+// David N. Cutler (davec) 3-Apr-1990
+//
+// Environment:
+//
+// User mode only.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 11-May-1992
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define length of exception dispatcher stack frame.
+//
+
+#define ExceptionDispatcherFrameLength (ExceptionRecordLength + ContextFrameLength)
+
+ SBTTL("User APC Dispatcher")
+//++
+//
+// The following code is never executed. Its purpose is to support unwinding
+// through the call to the APC dispatcher.
+//
+//--
+
+//
+// N.B. This function specifies its own private exception handler.
+//
+ EXCEPTION_HANDLER(KiUserApcHandler)
+
+ NESTED_ENTRY(KiUserApcDispatch, ContextFrameLength, zero);
+
+ .set noreorder
+ .set noat
+ stq sp, CxIntSp(sp) // save stack pointer
+ stq ra, CxIntRa(sp) // save return address
+ stq ra, CxFir(sp) // set continuation address
+ stq fp, CxIntFp(sp) // save integer register fp
+ stq gp, CxIntGp(sp) // save integer register gp
+
+ stq s0, CxIntS0(sp) // save integer registers s0 - s5
+ stq s1, CxIntS1(sp) //
+ stq s2, CxIntS2(sp) //
+ stq s3, CxIntS3(sp) //
+ stq s4, CxIntS4(sp) //
+ stq s5, CxIntS5(sp) //
+
+ stt f2, CxFltF2(sp) // save floating registers f2 - f9
+ stt f3, CxFltF3(sp) //
+ stt f4, CxFltF4(sp) //
+ stt f5, CxFltF5(sp) //
+ stt f6, CxFltF6(sp) //
+ stt f7, CxFltF7(sp) //
+ stt f8, CxFltF8(sp) //
+ stt f9, CxFltF9(sp) //
+
+ mov sp, fp // set frame pointer
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//++
+//
+// VOID
+// KiUserApcDispatcher (
+// IN PVOID NormalContext,
+// IN PVOID SystemArgument1,
+// IN PVOID SystemArgument2,
+// IN PKNORMAL_ROUTINE NormalRoutine
+// )
+//
+// Routine Description:
+//
+// This routine is entered on return from kernel mode to deliver an APC
+// in user mode. The context frame for this routine was built when the
+// APC interrupt was processed and contains the entire machine state of
+// the current thread. The specified APC routine is called and then the
+// machine state is restored and execution is continued.
+//
+// Arguments:
+//
+// a0 - Supplies the normal context parameter that was specified when the
+// APC was initialized.
+//
+// a1 - Supplies the first argument that was provided by the executive when
+// the APC was queued.
+//
+// a2 - Supplies the second argument that was provided by the executive
+// when the APC was queued.
+//
+// a3 - Supplies the address of the function that is to be called.
+//
+// N.B. Register sp supplies a pointer to a context frame.
+//
+// N.B. Register fp supplies the same value as sp and is used as a frame
+// pointer.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+//
+// N.B. This function is not called in the typical way. Instead of a normal
+// subroutine call to the nested entry point above, the alternate entry point
+// address below is stuffed into the Fir address of the trap frame. Thus when
+// the kernel returns from the trap, the following code is executed directly.
+//
+ ALTERNATE_ENTRY(KiUserApcDispatcher)
+
+ jsr ra, (a3) // call specified APC routine
+
+ mov fp, a0 // set address of context frame
+ ldil a1, TRUE // set test alert argument true
+ bsr ra, ZwContinue // execute system service to continue
+ mov v0, s0 // save status value
+
+//
+// Unsuccessful completion after attempting to continue execution. Use the
+// return status as the exception code, set noncontinuable exception and
+// attempt to raise another exception. Note there is no return from raise
+// status.
+//
+
+10: mov s0, a0 // set status value
+ bsr ra, RtlRaiseStatus // raise exception
+ br zero, 10b // loop on return
+
+ .end KiUserApcDispatch
+
+ SBTTL("User APC Exception Handler")
+//++
+//
+// EXCEPTION_DISPOSITION
+// KiUserApcHandler (
+// IN PEXCEPTION_RECORD ExceptionRecord,
+// IN ULONG EstablisherFrame,
+// IN OUT PCONTEXT ContextRecord,
+// IN OUT PDISPATCHER_CONTEXT DispatcherContext
+//
+// Routine Description:
+//
+// This function is called when an exception occurs in an APC routine
+// or one of its dynamic descendents, or when an unwind through the
+// APC dispatcher is in progress. If an unwind is in progress, then test
+// alert is called to ensure that all currently queued APCs are executed.
+//
+// Arguments:
+//
+// ExceptionRecord (a0) - Supplies a pointer to an exception record.
+//
+// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
+// of this exception handler.
+//
+// ContextRecord (a2) - Supplies a pointer to a context record.
+//
+// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
+// record.
+//
+// Return Value:
+//
+// ExceptionContinueSearch is returned as the function value.
+//
+//--
+
+ .struct 0
+HdRa: .space 8 // saved return address
+ .space 1 * 8 // required for 16-byte stack alignment
+HandlerFrameLength: // length of handler frame
+
+ NESTED_ENTRY(KiUserApcHandler, HandlerFrameLength, zero)
+
+ lda sp, -HandlerFrameLength(sp) // allocate stack frame
+ stq ra, HdRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// The following code is equivalent to:
+//
+// EXCEPTION_DISPOSITION
+// KiUserApcHandler(IN PEXCEPTION_RECORD ExceptionRecord)
+// {
+// if (IS_UNWINDING(ExceptionRecord->ExceptionFlags)) {
+// NtTestAlert();
+// }
+// return ExceptionContinueSearch
+// }
+//
+
+ ldl t0, ErExceptionFlags(a0) // get exception flags
+ and t0, EXCEPTION_UNWIND, t0 // check if unwind in progress
+ beq t0, 10f // if eq, no unwind in progress
+
+ bsr ra, ZwTestAlert // test for alert pending
+
+10: ldil v0, ExceptionContinueSearch // set disposition value
+ ldq ra, HdRa(sp) // restore return address
+ lda sp, HandlerFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end KiUserApcHandler
+
+
+ SBTTL("User Callback Dispatcher")
+//++
+//
+// The following code is never executed. Its purpose is to support unwinding
+// through the call to the exception dispatcher.
+//
+//--
+
+ NESTED_ENTRY(KiUserCallbackDispatch, ContextFrameLength, zero);
+.set noreorder
+ stq sp, CkSp(sp)
+ stq ra, CkRa(sp)
+.set reorder
+ PROLOGUE_END
+//++
+//
+// VOID
+// KiUserCallbackDispatcher (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This routine is entered on a callout from kernel mode to execute a
+// user mode callback function. All arguments for this function have
+// been placed on the stack.
+//
+// Arguments:
+//
+// (sp + 16) - Supplies a value of zero for alignment.
+//
+// (sp + 24) - Supplies the API number of the callback function that is
+// executed.
+//
+// (sp + 32) - Supplies a pointer to the input buffer.
+//
+// (sp + 40) - Supplies the input buffer length.
+//
+// Return Value:
+//
+// This function returns to kernel mode.
+//
+//--
+
+ ALTERNATE_ENTRY(KiUserCallbackDispatcher)
+
+ ldl a0, CkBuffer(sp) // get input buffer address
+ ldl a1, CkLength(sp) // get input buffer length
+ ldl t0, CkApiNumber(sp) // get API number
+ GET_THREAD_ENVIRONMENT_BLOCK // get TEB in v0
+ ldl t5, TePeb(v0) // get PEB in t5
+ ldl t2, PeKernelCallbackTable(t5) // get address of callback table
+ s4addl t0, t2, t3 // get address of callback
+ ldl t4, 0(t3) // get callback pointer
+ jsr ra, (t4) // call specified function
+
+//
+// If a return from the callback function occurs, then the output buffer
+// address and length are returned as NULL.
+//
+
+ bis zero,zero,a0 // set zero buffer address
+ bis zero,zero,a1 // set zero buffer length
+ bis v0, zero, a2 // set completion status
+ bsr ra, ZwCallbackReturn // return to kernel mode
+
+//
+// Unsuccessful completion after attempting to return to kernel mode. Use
+// the return status as the exception code, set noncontinuable exception and
+// attempt to raise another exception. Note there is no return from raise
+// status.
+//
+
+ bis v0, zero, s0 // save status value
+10: bis s0, zero, a0 // set status value
+ bsr ra, RtlRaiseStatus // raise exception
+ br zero, 10b // loop on return
+
+ .end KiUserCallbackDispatch
+
+ SBTTL("User Exception Dispatcher")
+//++
+//
+// The following code is never executed. Its purpose is to support unwinding
+// through the call to the exception dispatcher.
+//
+// When reverse executed, this prologue will restore all integer registers,
+// rather than just the non-volatile registers. This is necessary for proper
+// unwinding through the call to the exception dispatcher when non-standard
+// calls have been used in frames at or above the exception frame. Non-leaf
+// functions using a non-standard call are allowed to save the return address
+// register in another integer register instead of on the stack.
+//
+//--
+
+ NESTED_ENTRY(KiUserExceptionDispatch, ExceptionDispatcherFrameLength, zero);
+
+ .set noreorder
+ .set noat
+ stq sp, CxIntSp(sp) // save stack pointer
+ stq ra, CxIntRa(sp) // save return address
+ stq ra, CxFir(sp) // set continuation address
+
+ stq v0, CxIntV0(sp) // save integer register v0
+ stq t0, CxIntT0(sp) // save integer registers t0 - t6
+ stq t1, CxIntT1(sp) //
+ stq t2, CxIntT2(sp) //
+ stq t3, CxIntT3(sp) //
+ stq t4, CxIntT4(sp) //
+ stq t5, CxIntT5(sp) //
+ stq t6, CxIntT6(sp) //
+ stq t7, CxIntT7(sp) //
+
+ stq s0, CxIntS0(sp) // save integer registers s0 - s5
+ stq s1, CxIntS1(sp) //
+ stq s2, CxIntS2(sp) //
+ stq s3, CxIntS3(sp) //
+ stq s4, CxIntS4(sp) //
+ stq s5, CxIntS5(sp) //
+ stq fp, CxIntFp(sp) // save integer register fp
+
+ stq a0, CxIntA0(sp) // save integer registers a0 - a5
+ stq a1, CxIntA1(sp) //
+ stq a2, CxIntA2(sp) //
+ stq a3, CxIntA3(sp) //
+ stq a4, CxIntA4(sp) //
+ stq a5, CxIntA5(sp) //
+
+ stq t8, CxIntT8(sp) // save integer registers t8 - t11
+ stq t9, CxIntT9(sp) //
+ stq t10, CxIntT10(sp) //
+ stq t11, CxIntT11(sp) //
+
+ stq t12, CxIntT12(sp) // save integer register t12
+ stq AT, CxIntAt(sp) // save integer register AT
+ stq gp, CxIntGp(sp) // save integer register gp
+
+ stt f2, CxFltF2(sp) // save floating registers f2 - f9
+ stt f3, CxFltF3(sp) //
+ stt f4, CxFltF4(sp) //
+ stt f5, CxFltF5(sp) //
+ stt f6, CxFltF6(sp) //
+ stt f7, CxFltF7(sp) //
+ stt f8, CxFltF8(sp) //
+ stt f9, CxFltF9(sp) //
+
+ mov sp, fp // set frame pointer
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//++
+//
+// VOID
+// KiUserExceptionDispatcher (
+// IN PEXCEPTION_RECORD ExceptionRecord,
+// IN PCONTEXT ContextRecord
+// )
+//
+// Routine Description:
+//
+// This routine is entered on return from kernel mode to dispatch a user
+// mode exception. If a frame based handler handles the exception, then
+// the execution is continued. Otherwise last chance processing is performed.
+//
+// Arguments:
+//
+// s0 - Supplies a pointer to an exception record.
+//
+// s1 - Supplies a pointer to a context frame.
+//
+// fp - Supplies the same value as sp and is used as a frame pointer.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+//
+// N.B. This function is not called in the typical way. Instead of a normal
+// subroutine call to the nested entry point above, the alternate entry point
+// address below is stuffed into the Fir address of the trap frame. Thus when
+// the kernel returns from the trap, the following code is executed directly.
+//
+
+ ALTERNATE_ENTRY(KiUserExceptionDispatcher)
+
+ mov s0, a0 // set address of exception record
+ mov s1, a1 // set address of context frame
+ bsr ra, RtlDispatchException // attempt to dispatch the exception
+
+//
+// If the return status is TRUE, then the exception was handled and execution
+// should be continued with the NtContinue service in case the context was
+// changed. If the return status is FALSE, then the exception was not handled
+// and NtRaiseException is called to perform last chance exception processing.
+//
+
+ beq v0, 10f // if eq [false], perform last chance processing
+
+//
+// Continue execution.
+//
+
+ mov s1, a0 // set address of context frame
+ ldil a1, FALSE // set test alert argument false
+ bsr ra, ZwContinue // execute system service to continue
+ br zero, 20f // join common code
+
+//
+// Last chance processing.
+//
+
+10: mov s0, a0 // set address of exception record
+ mov s1, a1 // set address of context frame
+ ldil a2, FALSE // set first chance argument false
+ bsr ra, ZwRaiseException // perform last chance processing
+
+//
+// Common code for unsuccessful completion of the continue or last chance
+// service. Use the return status (which is now in v0) as the exception code,
+// set noncontinuable exception and attempt to raise another exception. Note
+// the stack grows and eventually this loop will end.
+//
+
+20: lda sp, -ExceptionRecordLength(sp) // allocate exception record
+ mov sp, a0 // get address of actual record
+ stl v0, ErExceptionCode(a0) // set exception code
+ ldil t0, EXCEPTION_NONCONTINUABLE // set noncontinuable flag
+ stl t0, ErExceptionFlags(a0) // store exception flags
+ stl s0, ErExceptionRecord(a0) // set associated exception record
+ stl zero, ErNumberParameters(a0) // set number of parameters
+ bsr ra, RtlRaiseException // raise exception
+ br zero, 20b // loop on error
+
+ .end KiUserExceptionDispatch
+
+//++
+//
+// NTSTATUS
+// KiRaiseUserExceptionDispatcher (
+// IN NTSTATUS ExceptionCode
+// )
+//
+// Routine Description:
+//
+// This routine is entered on return from kernel mode to raise a user
+// mode exception.
+//
+// Arguments:
+//
+// v0 - Supplies the status code to be raised.
+//
+// Return Value:
+//
+// ExceptionCode
+//
+//--
+
+//
+// N.B. This function is not called in the typical way. Instead of a normal
+// subroutine call to the nested entry point above, the alternate entry point
+// address below is stuffed into the Fir address of the trap frame. Thus when
+// the kernel returns from the trap, the following code is executed directly.
+//
+
+ .struct 0
+RaiseRa: .space 8 // saved return address
+RaiseV0: .space 8 // saved S0
+RaiseExr: .space ExceptionRecordLength // exception record for RtlRaiseException
+RaiseFrameLength: // length of handler frame
+
+ NESTED_ENTRY(KiRaiseUserExceptionDispatcher, RaiseFrameLength, zero)
+ lda sp, -RaiseFrameLength(sp) // allocate stack frame
+ stq ra, RaiseRa(sp) // save return address
+ PROLOGUE_END
+
+ stq v0, RaiseV0(sp) // save function return status
+ stl v0, ErExceptionCode+RaiseExr(sp) // set exception code
+ stl zero, ErExceptionFlags+RaiseExr(sp) // set exception flags
+ stl zero, ErExceptionRecord+RaiseExr(sp) // set exception record
+ stl ra, ErExceptionAddress+RaiseExr(sp) // set exception address
+ stl zero, ErNumberParameters+RaiseExr(sp)
+
+ lda a0, RaiseExr(sp) // set argument to RtlRaiseException
+ bsr ra, RtlRaiseException // attempt to raise the exception
+
+ ldq v0, RaiseV0(sp) // return status
+
+ ldq ra, RaiseRa(sp) // restore ra
+ lda sp, RaiseFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end KiRaiseUserExceptionDispatch