diff options
Diffstat (limited to 'private/crt32/startup/alpha/chkstk.s')
-rw-r--r-- | private/crt32/startup/alpha/chkstk.s | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/private/crt32/startup/alpha/chkstk.s b/private/crt32/startup/alpha/chkstk.s new file mode 100644 index 000000000..104254349 --- /dev/null +++ b/private/crt32/startup/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 + bgt sp, 10f // if sp>0, then running on user stack + +// +// Running on kernel stack - compute stack limit from initial kernel stack. +// + + GET_INITIAL_KERNEL_STACK // (PALcode) result in v0 + + lda t9, -KERNEL_STACK_SIZE(v0) // compute low limit of kernel stack + br zero, 20f // finish in common code + +// +// 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 + +// +// 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. +// + +20: 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 |