191 lines
4.2 KiB
ArmAsm
191 lines
4.2 KiB
ArmAsm
|
// TITLE("C-Runtime Stack Checking")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1993,1994 IBM Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// chkstk.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements runtime stack checking.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// Mark D. Johnson
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// User/Kernel mode.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include <ksppc.h>
|
|||
|
|
|||
|
|
|||
|
SBTTL("Check Stack")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID _RtlCheckStack(in ULONG n_alloc)
|
|||
|
//
|
|||
|
// 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 attempt to expand the stack. If the
|
|||
|
// attempt succeeds, then another page is committed. Otherwise, a stack
|
|||
|
// overflow exception is raised. It is the responsiblity of the caller to
|
|||
|
// handle this exception.
|
|||
|
//
|
|||
|
// Two entry points are supported. The first/standard entry point
|
|||
|
// calls for n_alloc to be passed as single argument (in r.3). In
|
|||
|
// the second case, the single argument is the negative of the amount
|
|||
|
// requested (the amount by which to decrement the stack pointer), and
|
|||
|
// is passed in r.12.
|
|||
|
//
|
|||
|
// Registers r.0 and r.11 are modified.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// n_alloc(r.3/r.12) - Supplies the size of the allocation on the stack.
|
|||
|
// With standard entry, passed in r.3. In alternate
|
|||
|
// entry, passed in r.12. In the latter case (r.12)
|
|||
|
// the value supplied is the quanitity by which to
|
|||
|
// decrement r.sp (a negative value).
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
// Assumptions:
|
|||
|
//
|
|||
|
// The value of Teb_Ptr is provided in r.13.
|
|||
|
//
|
|||
|
// The bottom of stack "bot" (r.11) is multiple of PAGE_SIZE.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// low
|
|||
|
// :
|
|||
|
// | :
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// |.......|<--- r.sp + r.12 - (PAGE_SIZE-1)
|
|||
|
// | ^ |
|
|||
|
// | |< -|- - - - - - always < PAGE_SIZE
|
|||
|
// | v |
|
|||
|
// +-------+<--- bot - m*PAGE_SIZE
|
|||
|
// | |
|
|||
|
// | : |
|
|||
|
// | |
|
|||
|
// +-------+<--- r.sp + r.12
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | : |
|
|||
|
// | : |
|
|||
|
// | : |
|
|||
|
// | : |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// +=======+<--- bottom of stack "bot" (r.11)
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | : |
|
|||
|
// | : |
|
|||
|
// | : |
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// +-------+<--- r.sp
|
|||
|
// | |
|
|||
|
// | |
|
|||
|
// | : |
|
|||
|
// | :
|
|||
|
// | : high
|
|||
|
// : m is count for add'l pages to commit
|
|||
|
//
|
|||
|
//
|
|||
|
// m:=max(0,{bot-[(r.sp+r.12)-(PAGE_SIZE-1)]}/PAGE_SIZE)
|
|||
|
// =max(0,bot-[r.12-(PAGE_SIZE-1)+r.sp])/PAGE_SIZE
|
|||
|
//
|
|||
|
// Operands in expression [r.12-(PAGE_SIZE-1)+r.sp) are known upon entry
|
|||
|
// to routine. This intermediate quantity is calculated early in r.0,
|
|||
|
// behind user/kernel mode test.
|
|||
|
|
|||
|
|
|||
|
.text
|
|||
|
.align 5
|
|||
|
|
|||
|
// want entry for _RtlCheckStack aligned on a 2**5-1 byte boundary so that
|
|||
|
// more commonly used (internal) entry _RtlCheckStack.12 is aligned on
|
|||
|
// 2**5 byte (cache-line) boundary ... and most often used code fits in
|
|||
|
// single cache-line
|
|||
|
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
|
|||
|
or r.11, r.11, r.11; or r.11, r.11, r.11
|
|||
|
or r.11, r.11, r.11
|
|||
|
|
|||
|
LEAF_ENTRY(_RtlCheckStack)
|
|||
|
|
|||
|
neg r.12,r.3
|
|||
|
|
|||
|
ALTERNATE_ENTRY(_RtlCheckStack.12)
|
|||
|
|
|||
|
cmpwi r.sp,0 // user or kernel mode?
|
|||
|
|
|||
|
// partial comp of num pages to commit moved here for performance
|
|||
|
|
|||
|
subi r.0,r.12,(PAGE_SIZE-1)
|
|||
|
add r.0,r.0,r.sp
|
|||
|
|
|||
|
bge+ UsrMode // sp >=0 indicates user mode
|
|||
|
|
|||
|
// kernel mode, KIPCR is system mode macro to get KiPcr
|
|||
|
|
|||
|
KIPCR(r.11)
|
|||
|
lwz r.11,PcInitialStack(r.11)
|
|||
|
subi r.11,r.11,KERNEL_STACK_SIZE
|
|||
|
b CommonCode
|
|||
|
|
|||
|
UsrMode:
|
|||
|
|
|||
|
// r.13 contains the TEB pointer
|
|||
|
|
|||
|
lwz r.11,TeStackLimit(r.13) // Get low stack address
|
|||
|
|
|||
|
CommonCode:
|
|||
|
|
|||
|
// r.11 contains computed "bot" of stack
|
|||
|
|
|||
|
sub r.0,r.11,r.0
|
|||
|
srawi. r.0,r.0,PAGE_SHIFT // Number pages to add/commit
|
|||
|
blelr // if <=0, return
|
|||
|
|
|||
|
mtctr r.0
|
|||
|
|
|||
|
PageLoop:
|
|||
|
|
|||
|
// Attempt to commit pages beyond the limit
|
|||
|
|
|||
|
lwzu r.0,-PAGE_SIZE(r.11)
|
|||
|
bdnz PageLoop
|
|||
|
|
|||
|
|
|||
|
LEAF_EXIT(_RtlCheckStack)
|