summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/alpha/chkstk.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/rtl/alpha/chkstk.s')
-rw-r--r--private/ntos/rtl/alpha/chkstk.s131
1 files changed, 131 insertions, 0 deletions
diff --git a/private/ntos/rtl/alpha/chkstk.s b/private/ntos/rtl/alpha/chkstk.s
new file mode 100644
index 000000000..749af86a7
--- /dev/null
+++ b/private/ntos/rtl/alpha/chkstk.s
@@ -0,0 +1,131 @@
+// TITLE("Runtime Stack Checking")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// chkstk.s
+//
+// Abstract:
+//
+// This module implements runtime stack checking.
+//
+// Author:
+//
+// David N. Cutler (davec) 14-Mar-1991
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 7-May-1992
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+ SBTTL("Check Stack")
+//++
+//
+// ULONG
+// _RtlCheckStack (
+// IN ULONG Allocation
+// )
+//
+// Routine Description:
+//
+// This function provides runtime stack checking for local allocations
+// that are more than a page and for storage dynamically allocated with
+// the alloca function. Stack checking consists of probing downward in
+// the stack a page at a time. If the current stack commitment is exceeded,
+// then the system will automatically attempts to expand the stack. If the
+// attempt succeeds, then another page is committed. Otherwise, a stack
+// overflow exception is raised. It is the responsibility of the caller to
+// handle this exception.
+//
+// N.B. This routine is called using a non-standard calling sequence since
+// it is typically called from within the prologue. The allocation size
+// argument is in register t12 and it must be preserved. Register t11
+// may contain the callers saved ra and it must be preserved. The choice
+// of these registers is hard-coded into the acc C compiler. Register v0
+// may contain a static link pointer (exception handlers) and so it must
+// be preserved. Since this function is called from within the prolog,
+// the a' registers must be preserved, as well as all the s' registers.
+// Registers t8, t9, and t10 are used by this function and are not
+// preserved.
+//
+// The typical calling sequence from the prologue is:
+//
+// mov ra, t11 // save return address
+// ldil t12, SIZE // set requested stack frame size
+// bsr ra, _RtlCheckStack // check stack page allocation
+// subq sp, t12, sp // allocate stack frame
+// mov t11, ra // restore return address
+//
+// Arguments:
+//
+// Allocation (t12) - Supplies the size of the allocation on the stack.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(_RtlCheckStack)
+
+ subq sp, t12, t8 // compute requested new stack address
+ mov v0, t10 // save v0 since the PALcode uses it
+#if defined(NTOS_KERNEL_RUNTIME)
+
+//
+// Running on kernel stack - get stack limit from thread object
+//
+
+ GET_CURRENT_THREAD // current thread in v0
+ ldl t9, ThStackLimit(v0)
+
+#else
+//
+// Running on user stack - get stack limit from thread environment block.
+//
+
+10: GET_THREAD_ENVIRONMENT_BLOCK // (PALcode) put TEB address in v0
+
+ ldl t9, TeStackLimit(v0) // get low limit of user stack address
+#endif
+
+//
+// The requested bottom of the stack is in t8.
+// The current low limit of the stack is in t9.
+//
+// If the new stack address is greater than the current stack limit, then the
+// pages have already been allocated, and nothing further needs to be done.
+//
+
+ mov t10, v0 // restore v0, no further PAL calls
+ cmpult t8, t9, t10 // t8<t9? new stack base within limit?
+ beq t10, 40f // if eq [false], then t8>=t9, so yes
+
+ ldil t10, ~(PAGE_SIZE - 1) // round down new stack address
+ and t8, t10, t8 // to next page boundary
+
+//
+// Go down one page, touch one quadword in it, and repeat until we reach the
+// new stack limit.
+//
+
+30: lda t9, -PAGE_SIZE(t9) // compute next address to check
+ stq zero, 0(t9) // probe stack address with a write
+ cmpeq t8, t9, t10 // t8=t9? at the low limit yet?
+ beq t10, 30b // if eq [false], more pages to probe
+
+40: ret zero, (ra) // return
+
+ .end _RtlCheckStack