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