1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_Memory.cpp
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: 17558 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/os.h>
17 #include <nn/assert.h>
18 #include <nn/svc.h>
19 #include <nn/dbg.h>
20 #include <nn/util.h>
21 #include <nn/init.h>
22
23 #include <nn/os/os_MemoryMapSelect.h>
24
25 //---------------------------------------------------------------------------
26
27 using namespace nn;
28 using namespace nn::svc;
29
30 namespace nn{ namespace os{
31
32 namespace
33 {
34 uptr s_DeviceMemoryAddress = 0; //!< デバイスメモリのアドレス
35 size_t s_DeviceMemorySize = 0; //!< デバイスメモリのサイズ
36
37 size_t s_HeapSize = 0; //!< ヒープサイズ
38 }
39
40 // デバイスメモリを初期化します。
InitializeDeviceMemory()41 void InitializeDeviceMemory()
42 {
43 if ( s_DeviceMemorySize == 0 )
44 {
45 Result result;
46 result = SetDeviceMemorySize( DEVICE_MEMORY_SIZE );
47 NN_UTIL_PANIC_IF_FAILED( result );
48 }
49 }
50
51 // デバイスメモリのアドレスを取得します。
GetDeviceMemoryAddress()52 uptr GetDeviceMemoryAddress()
53 {
54 NN_TASSERTMSG_(s_DeviceMemoryAddress != NULL, "Device Memory is NOT Initialized.");
55 return s_DeviceMemoryAddress;
56 }
57
58 // デバイスメモリのサイズを設定します。
SetDeviceMemorySize(size_t size)59 Result SetDeviceMemorySize(size_t size)
60 {
61 // CHECK: ページサイズには定数 NN_OS_MEMORY_PAGE_SIZE の使用を推奨します。
62 // デバイスメモリのサイズは4096の倍数である必要があります。
63 NN_ALIGN_TASSERT_(size, 4096);
64 Result result;
65
66 if( size > s_DeviceMemorySize )
67 {
68 // デバイスメモリを確保します。
69 // すでにデバイスメモリを確保していれば、直後に足りない分のメモリを確保します。
70 uptr addr;
71 const size_t mapSize = size - s_DeviceMemorySize;
72 const uptr requestAddress = (s_DeviceMemorySize == 0) ? NULL: (s_DeviceMemoryAddress + s_DeviceMemorySize);
73
74 // nn::os::MEMORY_OPERATION_FLAG_LINEARを指定して連続したメモリを確保できるようにします。
75 result = nn::svc::ControlMemory( &addr,
76 requestAddress,
77 NULL,
78 mapSize,
79 (nn::os::MEMORY_OPERATION_COMMIT | nn::os::MEMORY_OPERATION_FLAG_LINEAR),
80 nn::os::MEMORY_PERMISSION_READ_WRITE );
81
82 if( result.IsSuccess() )
83 {
84 // 初回デバイスメモリ確保でなければ、連続したアドレスにメモリを取得できたことをチェックします。
85 NN_TASSERT_( s_DeviceMemorySize == 0 || addr == requestAddress );
86
87 // 初回デバイスメモリ確保時にはアドレスを保存します。
88 if( s_DeviceMemorySize == 0 )
89 {
90 s_DeviceMemoryAddress = addr;
91 }
92
93 s_DeviceMemorySize = size;
94 }
95 }
96 else
97 {
98 // デバイスメモリの末尾から不要なサイズ分を解放します。
99 uptr addr;
100 const size_t unmapSize = s_DeviceMemorySize - size;
101 const uptr freeAddress = s_DeviceMemoryAddress + size;
102
103 result = nn::svc::ControlMemory( &addr,
104 freeAddress,
105 NULL,
106 unmapSize,
107 nn::os::MEMORY_OPERATION_FREE,
108 nn::os::MEMORY_PERMISSION_NONE );
109
110 if( result.IsSuccess() )
111 {
112 if( size == 0 )
113 {
114 s_DeviceMemoryAddress = NULL;
115 }
116
117 s_DeviceMemorySize = size;
118 }
119 }
120
121 return result;
122 }
123
124 // デバイスメモリのサイズを取得します。
GetDeviceMemorySize()125 size_t GetDeviceMemorySize()
126 {
127 return s_DeviceMemorySize;
128 }
129
130 // ヒープサイズを設定します。
SetHeapSize(size_t size)131 Result SetHeapSize(size_t size)
132 {
133 // CHECK: ページサイズには定数 NN_OS_MEMORY_PAGE_SIZE の使用を推奨します。
134 // ヒープのサイズは4096の倍数である必要があります。
135 NN_ALIGN_TASSERT_(size, 4096);
136 Result result;
137
138 if( size > s_HeapSize )
139 {
140 // ヒープの先頭からサイズ分の領域を確保します。
141 // すでに確保していれば、直後に足りない分のメモリを確保します。
142 uptr addr;
143 const size_t mapSize = size - s_HeapSize;
144 const uptr requestAddress = NN_OS_ADDR_HEAP_BEGIN + s_HeapSize;
145
146 result = nn::svc::ControlMemory( &addr,
147 requestAddress,
148 NULL,
149 mapSize,
150 nn::os::MEMORY_OPERATION_COMMIT,
151 nn::os::MEMORY_PERMISSION_READ_WRITE );
152
153 if( result.IsSuccess() )
154 {
155 NN_TASSERT_( addr == requestAddress );
156 s_HeapSize = size;
157 }
158 }
159 else
160 {
161 // ヒープの末尾から不要になったサイズ分の領域を解放します。
162 uptr addr;
163 const size_t unmapSize = s_HeapSize - size;
164 const uptr freeAddress = NN_OS_ADDR_HEAP_BEGIN + size;
165
166 result = nn::svc::ControlMemory( &addr,
167 freeAddress,
168 NULL,
169 unmapSize,
170 nn::os::MEMORY_OPERATION_FREE,
171 nn::os::MEMORY_PERMISSION_NONE );
172
173 if( result.IsSuccess() )
174 {
175 s_HeapSize = size;
176 }
177 }
178
179 return result;
180 }
181
182 // ヒープサイズを取得します。
GetHeapSize()183 size_t GetHeapSize()
184 {
185 return s_HeapSize;
186 }
187
188
189 #if NN_PLATFORM_HAS_MMU
SetupHeapForMemoryBlock(size_t heapSize)190 void SetupHeapForMemoryBlock(size_t heapSize)
191 {
192 Result result;
193
194 result = SetHeapSize( heapSize );
195 NN_UTIL_PANIC_IF_FAILED( result );
196
197 InitializeMemoryBlock(GetHeapAddress(), GetHeapSize());
198
199 SetDefaultAutoStackManager();
200 }
201 #endif // if NN_PLATFORM_HAS_MMU
202
203
204
205
206
207 }} // namespace nn::os
208
209
210 #include <new>
211 using namespace nn::os;
212
213 extern "C" {
214
nnosInitializeDeviceMemory()215 void nnosInitializeDeviceMemory()
216 {
217 #pragma push
218 #pragma diag_suppress 1361
219 nn::os::InitializeDeviceMemory();
220 #pragma pop
221 }
222
nnosGetDeviceMemoryAddress()223 uptr nnosGetDeviceMemoryAddress()
224 {
225 return nn::os::GetDeviceMemoryAddress();
226 }
227
228 }
229