2020-09-30 17:12:29 +02:00

132 lines
4.3 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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