summaryrefslogtreecommitdiffstats
path: root/private/crt32/startup/mips/chkstk.s
blob: 3ba199feae0052a6332f8096cc12dc5f0f019a88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//      TITLE("Runtime Stack Checking")
//++
//
// Copyright (c) 1991  Microsoft Corporation
//
// Module Name:
//
//    chkstk.s
//
// Abstract:
//
//    This module implements runtime stack checking.
//
// Author:
//
//    David N. Cutler (davec) 14-Mar-1991
//
// Environment:
//
//    User mode.
//
// Revision History:
//
//--

#include "ksmips.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 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.
//
//    N.B. This routine is called using a calling sequence that assumes that
//       all registers are preserved.
//
// Arguments:
//
//    Allocation (t8) - Supplies the size of the allocation on the stack.
//
// Return Value:
//
//    None.
//
//--

        NESTED_ENTRY(_RtlCheckStack, 0, ra)

        sw      t7,0(sp)                // save temporary register
        sw      t8,4(sp)                // save allocation size
        sw      t9,8(sp)                // save temporary register

        PROLOGUE_END

        .set    noreorder
        .set    noat
        li      t9,UsPcr                // get address of user PCR
        bgez    sp,10f                  // if gez, running on user stack
        subu    t8,sp,t8                // compute new bottom of stack

//
// Running on kernel stack - compute stack limit from initial kernel stack.
//

        lw      t9,KiPcr + PcInitialStack(zero) // get initial kernel stack
        b       20f                     // finish in common code
        subu    t9,t9,KERNEL_STACK_SIZE // compute low limit of kernel stack

//
// Running on user stack - get stack limit from thread environment block.
//

10:     lw      t9,PcTeb(t9)            // get address of environment block
        nop                             // fill
        lw      t9,TeStackLimit(t9)     // get low stack address
        nop                             // fill
20:     sltu    t7,t8,t9                // new stack address within limits?
        beq     zero,t7,40f             // if eq, stack within limits
        li      t7,~(PAGE_SIZE - 1)     // set address mask
        and     t8,t8,t7                // round down new stack address
30:     subu    t9,t9,PAGE_SIZE         // compute next address to check
        bne     t8,t9,30b               // if ne, more pages to probe
        sw      zero,0(t9)              // check stack address
40:     lw      t7,0(sp)                // restore temporary register
        lw      t8,4(sp)                // restore allocation size
        j       ra                      // return
        lw      t9,8(sp)                // restore temporary register
        .set    at
        .set    reorder

        .end    _RtlCheckStack