summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/ppc/chkstk.s
blob: 67910e07c935d60974544dcfd04628491e49cf96 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
//         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.


        .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)

        // r.13 contains the TEB pointer

        lwz     r.11,TeStackLimit(r.13) // Get low stack address

        // r.11 contains "bot" of stack

        subi    r.0,r.12,(PAGE_SIZE-1)
        add     r.0,r.0,r.sp

        // r.0 is desired "bot"

        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)



        .debug$S
        .ualong         1

        .uashort        52
        .uashort        0x205          // S_GPROC32
        .ualong         0
        .ualong         0
        .ualong         0
        .ualong         _RtlCheckStack.end-.._RtlCheckStack
        .ualong         0
        .ualong         _RtlCheckStack.end-.._RtlCheckStack
        .ualong         [secoff].._RtlCheckStack
        .uashort        [secnum].._RtlCheckStack
        .uashort        0x1000
        .byte           0x00
        .byte           16, ".._RtlCheckStack"

        .uashort        29
        .uashort        0x209          // S_LABEL32
        .ualong         [secoff].._RtlCheckStack.12
        .uashort        [secnum].._RtlCheckStack.12
        .byte           0
        .byte           19, ".._RtlCheckStack.12"

        .uashort        2, 0x6         // S_END