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

191 lines
4.2 KiB
ArmAsm
Raw 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("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)