1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_StackMemory.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 24156 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_OS_OS_STACKMEMORY_H_
17 #define NN_OS_OS_STACKMEMORY_H_
18 
19 #include <nn/config.h>
20 #if NN_PLATFORM_HAS_MMU
21 
22 #include <nn/types.h>
23 #include <nn/Handle.h>
24 #include <nn/svc.h>
25 #include <nn/os/CTR/os_MemoryConfig.h>
26 #include <nn/os/os_MemoryBlockBase.h>
27 
28 #ifdef __cplusplus
29 
30 #include <nn/util/util_NonCopyable.h>
31 #include <nn/os/os_SvcTypes.autogen.h>
32 #include <nn/util/util_Result.h>
33 
34 namespace nn{ namespace os{
35 
36     namespace detail
37     {
38         void InitializeStackMemory();
39     }
40 
41 
42 /*!
43     @brief 指定されたメモリ領域をスタック用に隔離するクラスです。
44 
45     指定されたメモリ領域を
46     前後に 4 KByte の未マップ領域を確保した異なるアドレスに
47     マッピングしなおします。
48 
49     前後に未マップ領域が配置されるため、
50     スタックに使用することでスタックオーバーフローや
51     スタックアンダーフローをデータアボートとして
52     検出することができます。
53 */
54 class StackMemory : public MemoryBlockBase
55 {
56 private:
57     uptr    m_MemoryAddress;
58 
59 public:
60     /*!
61         :overload notinit
62 
63         @brief オブジェクトを構築します。
64 
65                引数を指定しない場合は初期化を行いません。別途 @ref Initialize を呼び出す必要があります。
66     */
StackMemory()67     StackMemory() {}
68 
69     /*!
70         :overload init
71 
72         @brief オブジェクトを構築し、メモリ領域の隔離を行います。
73 
74                内部で Initialize を呼び出します。
75 
76         @param[in] pMem 隔離するメモリ領域の先頭を挿すポインタ。
77                         4096 Byte アライメントされていなければなりません。
78         @param[in] size 隔離するメモリ領域のサイズ。
79                         size は 4096 の倍数でなければなりません。
80     */
StackMemory(void * pMem,size_t size)81     explicit StackMemory(void* pMem, size_t size) { Initialize(pMem, size); }
82 
83 
84     /*!
85         @brief メモリ領域を隔離します。
86 
87         引数で指定されたメモリ領域を
88         前後に 4 KByte の未マップ領域を確保した異なるアドレスに
89         マッピングしなおします。
90         以後、Finalize を呼び出すまで指定された指定されたアドレス範囲は
91         アクセス禁止となります。
92         新たなマッピング先のアドレスは MemoryBlockBase::GetAddress で取得できます。
93 
94         @param[in] pMem 隔離するメモリ領域の先頭を挿すポインタ。
95                         4096 Byte アライメントされていなければなりません。
96         @param[in] size 隔離するメモリ領域のサイズ。
97                         size は 4096 の倍数でなければなりません。
98     */
99     void Initialize(void* pMem, size_t size);
100 
101     /*!
102         @brief オブジェクトを破棄します。
103 
104         Finalize が呼び出されていない場合は
105         Finalize の呼び出しも行います。
106     */
~StackMemory()107     ~StackMemory() { Finalize(); }
108 
109     /*!
110         @brief メモリ領域の隔離を解除します。
111 
112         隔離先へのマッピングを解除し、
113         元々のアドレスでアクセス可能な状態に戻します。
114     */
115     void* Finalize();
116 
117     /*!
118         @brief 確保しているメモリ領域の終端アドレスを取得します。
119 
120         Thread::Start に StackMemoryBlock のインスタンスを
121         直接渡すためのインターフェイスです。
122 
123         @return 確保しているメモリ領域の終端アドレスを返します。
124     */
GetStackBottom()125     uptr GetStackBottom() const { return GetAddress() + GetSize(); }
126 
127     /*!
128         @brief 確保しているメモリ領域のサイズを取得します。
129 
130         Thread::Start に StackMemoryBlock のインスタンスを
131         直接渡すためのインターフェイスです。
132 
133         @return 確保しているメモリ領域のサイズを返します。
134     */
GetStackSize()135     size_t GetStackSize() const { return GetSize(); }
136 
137     void MoveFrom(StackMemory* pFrom);
138 };
139 
140 
141 
142 }} // namespace nn::os
143 
144 #endif // __cplusplus
145 
146 // 以下、C 用宣言
147 
148 #include <nn/util/detail/util_CLibImpl.h>
149 
150 /*!
151   @addtogroup   nn_os               os
152   @{
153 
154   @defgroup     nn_os_StackMemory_c       StackMemory (C)
155 
156   @brief        @ref nn::os::StackMemory の C インタフェースモジュールです。
157 
158   @{
159 */
160 
161 /*!
162   @struct       nnosStackMemory
163   @brief        スタックから確保したメモリブロックを表す C の構造体です。
164 
165   @brief 対応するクラス @ref nn::os::StackMemory を参照してください。
166 */
167 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosStackMemory, nn::os::StackMemory, 24, u32);
168 
169 
170 /*!
171   @brief 対応する C++ 関数 @ref nn::os::StackMemory::Initialize を参照してください。
172 */
173 NN_EXTERN_C void nnosStackMemoryProtect(nnosStackMemory* p, void* pMem, size_t size);
174 
175 /*
176   @brief 対応する C++ 関数 @ref nn::os::StackMemory::Finalize を参照してください。
177 */
178 NN_EXTERN_C void nnosStackMemoryUnprotect(nnosStackMemory* p);
179 
180 /*!
181   @brief 対応する C++ 関数 @ref nn::os::StackMemory::GetAddress を参照してください。
182 */
183 NN_EXTERN_C uptr nnosStackMemoryGetAddress(nnosStackMemory* p);
184 
185 /*!
186   @brief 対応する C++ 関数 @ref nn::os::StackMemory::GetSize を参照してください。
187 */
188 NN_EXTERN_C size_t nnosStackMemoryGetSize(nnosStackMemory* p);
189 
190 /*!
191   @brief 対応する C++ 関数 @ref nn::os::StackMemory::GetStackBottom を参照してください。
192 */
193 NN_EXTERN_C uptr nnosStackMemoryGetStackBottom(nnosStackMemory* p);
194 
195 /*!
196   @}
197 
198   @}
199 */
200 
201 #endif  // if NN_PLATFORM_HAS_MMU
202 #endif /* NN_OS_OS_STACKMEMORY_H_ */
203