summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/alpha/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/rtl/alpha/context.c')
-rw-r--r--private/ntos/rtl/alpha/context.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/private/ntos/rtl/alpha/context.c b/private/ntos/rtl/alpha/context.c
new file mode 100644
index 000000000..dfcf0aa1e
--- /dev/null
+++ b/private/ntos/rtl/alpha/context.c
@@ -0,0 +1,330 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ context.c
+
+Abstract:
+
+ This module implements user-mode callable context manipulation routines.
+
+Author:
+
+ Mark Lucovsky (markl) 20-Jun-1989
+
+Revision History:
+
+ David N. Cutler (davec) 18-Apr-1990
+
+ Revise for MIPS environment.
+
+ Thomas Van Baak (tvb) 11-May-1992
+
+ Adapted for Alpha AXP.
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <alphaops.h>
+
+VOID
+RtlInitializeContext(
+ IN HANDLE Process,
+ OUT PCONTEXT Context,
+ IN PVOID Parameter OPTIONAL,
+ IN PVOID InitialPc OPTIONAL,
+ IN PVOID InitialSp OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a context structure so that it can be used in
+ a subsequent call to NtCreateThread.
+
+Arguments:
+
+ Process - Supplies an open handle to the target process. This argument
+ is ignored by this function.
+
+ Context - Supplies a pointer to a context record that is to be initialized.
+
+ Parameter - Supplies an initial value for register A0.
+
+ InitialPc - Supplies an initial program counter value.
+
+ InitialSp - Supplies an initial stack pointer value.
+
+Return Value:
+
+ Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly
+ aligned.
+
+ Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly
+ aligned.
+
+--*/
+
+{
+
+ //
+ // Check for proper initial stack and PC alignment.
+ //
+
+ if (((ULONG)InitialSp & 0xF) != 0) {
+ RtlRaiseStatus(STATUS_BAD_INITIAL_STACK);
+ }
+ if (((ULONG)InitialPc & 0x3) != 0) {
+ RtlRaiseStatus(STATUS_BAD_INITIAL_PC);
+ }
+
+ //
+ // Initialize the integer registers to contain their register number
+ // (they must be initialized and using register numbers instead of 0
+ // can be useful for debugging). Integer registers a0, ra, gp, and sp
+ // are set later.
+ //
+
+ Context->IntV0 = 0;
+ Context->IntT0 = 1;
+ Context->IntT1 = 2;
+ Context->IntT2 = 3;
+ Context->IntT3 = 4;
+ Context->IntT4 = 5;
+ Context->IntT5 = 6;
+ Context->IntT6 = 7;
+ Context->IntT7 = 8;
+ Context->IntS0 = 9;
+ Context->IntS1 = 10;
+ Context->IntS2 = 11;
+ Context->IntS3 = 12;
+ Context->IntS4 = 13;
+ Context->IntS5 = 14;
+ Context->IntFp = 15;
+ Context->IntA1 = 17;
+ Context->IntA2 = 18;
+ Context->IntA3 = 19;
+ Context->IntA4 = 20;
+ Context->IntA5 = 21;
+ Context->IntT8 = 22;
+ Context->IntT9 = 23;
+ Context->IntT10 = 24;
+ Context->IntT11 = 25;
+ Context->IntT12 = 27;
+ Context->IntAt = 28;
+
+ //
+ // Initialize the floating point registers to contain the integer value
+ // of their register number (they must be initialized and using register
+ // numbers instead of 0 can be useful for debugging).
+ //
+
+ Context->FltF0 = 0;
+ Context->FltF1 = 1;
+ Context->FltF2 = 2;
+ Context->FltF3 = 3;
+ Context->FltF4 = 4;
+ Context->FltF5 = 5;
+ Context->FltF6 = 6;
+ Context->FltF7 = 7;
+ Context->FltF8 = 8;
+ Context->FltF9 = 9;
+ Context->FltF10 = 10;
+ Context->FltF11 = 11;
+ Context->FltF12 = 12;
+ Context->FltF13 = 13;
+ Context->FltF14 = 14;
+ Context->FltF15 = 15;
+ Context->FltF16 = 16;
+ Context->FltF17 = 17;
+ Context->FltF18 = 18;
+ Context->FltF19 = 19;
+ Context->FltF20 = 20;
+ Context->FltF21 = 21;
+ Context->FltF22 = 22;
+ Context->FltF23 = 23;
+ Context->FltF24 = 24;
+ Context->FltF25 = 25;
+ Context->FltF26 = 26;
+ Context->FltF27 = 27;
+ Context->FltF28 = 28;
+ Context->FltF29 = 29;
+ Context->FltF30 = 30;
+ Context->FltF31 = 0;
+
+ //
+ // Initialize the control registers.
+ //
+ // Gp: will be set in LdrpInitialize at thread startup.
+ // Ra: some debuggers compare for 1 as a top-of-stack indication.
+ //
+ // N.B. ULONG becomes canonical longword with (ULONGLONG)(LONG) cast.
+ //
+
+ Context->IntGp = 0;
+ Context->IntSp = (ULONGLONG)(LONG)InitialSp;
+ Context->IntRa = 1;
+ Context->Fir = (ULONGLONG)(LONG)InitialPc;
+
+ //
+ // Set default Alpha floating point control register values.
+ //
+
+ Context->Fpcr = (ULONGLONG)0;
+ ((PFPCR)(&Context->Fpcr))->DynamicRoundingMode = ROUND_TO_NEAREST;
+ Context->SoftFpcr = (ULONGLONG)0;
+
+ Context->Psr = 0;
+ Context->ContextFlags = CONTEXT_FULL;
+
+ //
+ // Set the initial context of the thread in a machine specific way.
+ //
+
+ Context->IntA0 = (ULONGLONG)(LONG)Parameter;
+}
+
+NTSTATUS
+RtlRemoteCall(
+ HANDLE Process,
+ HANDLE Thread,
+ PVOID CallSite,
+ ULONG ArgumentCount,
+ PULONG Arguments,
+ BOOLEAN PassContext,
+ BOOLEAN AlreadySuspended
+ )
+
+/*++
+
+Routine Description:
+
+ This function calls a procedure in another thread/process by using
+ NtGetContext and NtSetContext. Parameters are passed to the target
+ procedure via the nonvolatile registers (s0 - s5).
+
+Arguments:
+
+ Process - Supplies an open handle to the target process.
+
+ Thread - Supplies an open handle to the target thread within the target
+ process.
+
+ CallSite - Supplies the address of the procedure to call in the target
+ process.
+
+ ArgumentCount - Supplies the number of 32 bit parameters to pass to the
+ target procedure.
+
+ Arguments - Supplies a pointer to the array of 32 bit parameters to pass.
+
+ PassContext - Supplies a boolean value that determines whether a parameter
+ is to be passed that points to a context record. This parameter is
+ ignored on MIPS and Alpha hosts.
+
+ AlreadySuspended - Supplies a boolean value that determines whether the
+ target thread is already in a suspended or waiting state.
+
+Return Value:
+
+ Status - Status value.
+
+--*/
+
+{
+
+ NTSTATUS Status;
+ CONTEXT Context;
+ ULONG Index;
+ ULONGLONG NewSp;
+
+ if ((ArgumentCount > 6) ||
+ (PassContext && (ArgumentCount > 5))) {
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ //
+ // If necessary, suspend the target thread before getting the thread's
+ // current state.
+ //
+
+ if (AlreadySuspended == FALSE) {
+ Status = NtSuspendThread(Thread, NULL);
+ if (NT_SUCCESS(Status) == FALSE) {
+ return(Status);
+ }
+ }
+
+ //
+ // Get the current state of the target thread.
+ //
+
+ Context.ContextFlags = CONTEXT_FULL;
+ Status = NtGetContextThread(Thread, &Context);
+ if (NT_SUCCESS(Status) == FALSE) {
+ if (AlreadySuspended == FALSE) {
+ NtResumeThread(Thread, NULL);
+ }
+ return(Status);
+ }
+
+ if (AlreadySuspended) {
+ Context.IntV0 = STATUS_ALERTED;
+ }
+
+ //
+ // Pass the parameters to the other thread via the non-volatile registers
+ // s0 - s5. The context record is passed on the stack of the target thread.
+ //
+
+ NewSp = Context.IntSp - sizeof(CONTEXT);
+ Status = NtWriteVirtualMemory(Process, (PVOID)NewSp, &Context,
+ sizeof(CONTEXT), NULL);
+ if (NT_SUCCESS(Status) == FALSE) {
+ if (AlreadySuspended == FALSE) {
+ NtResumeThread(Thread, NULL);
+ }
+ return(Status);
+ }
+
+ //
+ // N.B. Each ULONG argument is converted to canonical form with the
+ // (ULONGLONG)(LONG) cast as required by the calling standard.
+ //
+ // N.B. Given the PULONG Arguments prototype, this function cannot pass
+ // quadword arguments (including structures such as LARGE_INTEGER).
+ //
+
+ Context.IntSp = NewSp;
+
+ if (PassContext) {
+ Context.IntS0 = NewSp;
+ for (Index = 0; Index < ArgumentCount; Index += 1) {
+ (&Context.IntS1)[Index] = (ULONGLONG)(LONG)Arguments[Index];
+ }
+
+ } else {
+ for (Index = 0; Index < ArgumentCount; Index += 1) {
+ (&Context.IntS0)[Index] = (ULONGLONG)(LONG)Arguments[Index];
+ }
+ }
+
+ //
+ // Set the address of the target code into FIR and set the thread context
+ // to cause the target procedure to be executed.
+ //
+ // N.B. The PVOID CallSite is stored as a canonical longword in order
+ // for Fir to be a valid 64-bit address.
+ //
+
+ Context.Fir = (ULONGLONG)(LONG)CallSite;
+ Status = NtSetContextThread(Thread, &Context);
+ if (AlreadySuspended == FALSE) {
+ NtResumeThread(Thread, NULL);
+ }
+ return(Status);
+}