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: 38846 $
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/os/os_MemoryMapSelect.h>
23 #include <nn/os/os_ErrorHandlerSelect.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 // Initializes device memory.
InitializeDeviceMemory()41 void InitializeDeviceMemory()
42 {
43 if ( s_DeviceMemorySize == 0 )
44 {
45 Result result;
46 result = SetDeviceMemorySize( DEVICE_MEMORY_SIZE );
47 NN_OS_ERROR_IF_FAILED( result );
48 }
49 }
50
51 // Gets the device memory address.
GetDeviceMemoryAddress()52 uptr GetDeviceMemoryAddress()
53 {
54 NN_TASSERTMSG_(s_DeviceMemoryAddress != NULL, "Device Memory is NOT Initialized.");
55 return s_DeviceMemoryAddress;
56 }
57
58 // Sets the device memory size.
SetDeviceMemorySize(size_t size)59 Result SetDeviceMemorySize(size_t size)
60 {
61 // The device memory size must be a multiple of 4096.
62 if ( (size % NN_OS_MEMORY_PAGE_SIZE) != 0 )
63 {
64 return ResultMisalignedSize();
65 }
66 Result result;
67
68 if( size > s_DeviceMemorySize )
69 {
70 // Allocates device memory.
71 // If device memory has already been allocated, immediately afterwards allocates the portion of memory that was insufficient
72 if (s_DeviceMemorySize != 0)
73 {
74 // If already allocated, the size before and after must be 1 MiB aligned.
75 if (!(s_DeviceMemorySize % (1024 * 1024) == 0 && size % (1024 * 1024) == 0))
76 {
77 return ResultMisalignedSize();
78 }
79 }
80 uptr addr;
81 const size_t mapSize = size - s_DeviceMemorySize;
82 const uptr requestAddress = (s_DeviceMemorySize == 0) ? NULL: (s_DeviceMemoryAddress + s_DeviceMemorySize);
83
84 // Continuous memory can be allocated by specifying nn::os::MEMORY_OPERATION_FLAG_LINEAR.
85 result = nn::svc::ControlMemory( &addr,
86 requestAddress,
87 NULL,
88 mapSize,
89 (nn::os::MEMORY_OPERATION_COMMIT | nn::os::MEMORY_OPERATION_FLAG_LINEAR),
90 nn::os::MEMORY_PERMISSION_READ_WRITE );
91
92 if( result.IsSuccess() )
93 {
94 // If this is not the first time device memory has been allocated, checks if memory was obtained for the continuous address.
95 NN_TASSERT_( s_DeviceMemorySize == 0 || addr == requestAddress );
96
97 // For first time device memory allocation, save addresses.
98 if( s_DeviceMemorySize == 0 )
99 {
100 s_DeviceMemoryAddress = addr;
101 }
102
103 s_DeviceMemorySize = size;
104 }
105 }
106 else
107 {
108 // Releases unnecessary memory of size amount from the end of the device memory.
109 uptr addr;
110 const size_t unmapSize = s_DeviceMemorySize - size;
111 const uptr freeAddress = s_DeviceMemoryAddress + size;
112
113 result = nn::svc::ControlMemory( &addr,
114 freeAddress,
115 NULL,
116 unmapSize,
117 nn::os::MEMORY_OPERATION_FREE,
118 nn::os::MEMORY_PERMISSION_NONE );
119
120 if( result.IsSuccess() )
121 {
122 if( size == 0 )
123 {
124 s_DeviceMemoryAddress = NULL;
125 }
126
127 s_DeviceMemorySize = size;
128 }
129 }
130
131 return result;
132 }
133
134 // Gets the device memory size.
GetDeviceMemorySize()135 size_t GetDeviceMemorySize()
136 {
137 return s_DeviceMemorySize;
138 }
139
140 // Sets the heap size.
SetHeapSize(size_t size)141 Result SetHeapSize(size_t size)
142 {
143 // The heap size must be a multiple of 4096.
144 if ( (size % NN_OS_MEMORY_PAGE_SIZE) != 0 )
145 {
146 return ResultMisalignedSize();
147 }
148 Result result;
149
150 if( size > s_HeapSize )
151 {
152 // Allocate a region in size amount from the start of the heap.
153 // If already allocated, immediately afterwards allocates the memory size that was insufficient
154 uptr addr;
155 const size_t mapSize = size - s_HeapSize;
156 const uptr requestAddress = NN_OS_ADDR_HEAP_BEGIN + s_HeapSize;
157
158 result = nn::svc::ControlMemory( &addr,
159 requestAddress,
160 NULL,
161 mapSize,
162 nn::os::MEMORY_OPERATION_COMMIT,
163 nn::os::MEMORY_PERMISSION_READ_WRITE );
164
165 if( result.IsSuccess() )
166 {
167 NN_TASSERT_( addr == requestAddress );
168 s_HeapSize = size;
169 }
170 }
171 else
172 {
173 // Releases unnecessary memory region in size amount from the end of the heap.
174 uptr addr;
175 const size_t unmapSize = s_HeapSize - size;
176 const uptr freeAddress = NN_OS_ADDR_HEAP_BEGIN + size;
177
178 result = nn::svc::ControlMemory( &addr,
179 freeAddress,
180 NULL,
181 unmapSize,
182 nn::os::MEMORY_OPERATION_FREE,
183 nn::os::MEMORY_PERMISSION_NONE );
184
185 if( result.IsSuccess() )
186 {
187 s_HeapSize = size;
188 }
189 }
190
191 return result;
192 }
193
194 // Get heap size.
GetHeapSize()195 size_t GetHeapSize()
196 {
197 return s_HeapSize;
198 }
199
200
201 #if NN_PLATFORM_HAS_MMU
SetupHeapForMemoryBlock(size_t heapSize)202 void SetupHeapForMemoryBlock(size_t heapSize)
203 {
204 Result result;
205
206 result = SetHeapSize( heapSize );
207 NN_OS_ERROR_IF_FAILED( result );
208
209 InitializeMemoryBlock(GetHeapAddress(), GetHeapSize());
210
211 SetDefaultAutoStackManager();
212 }
213 #endif // if NN_PLATFORM_HAS_MMU
214
215
216
217
218
219 }} // namespace nn::os
220
221
222 #include <new>
223 using namespace nn::os;
224
225 extern "C" {
226
nnosInitializeDeviceMemory()227 void nnosInitializeDeviceMemory()
228 {
229 #pragma push
230 #pragma diag_suppress 1361
231 nn::os::InitializeDeviceMemory();
232 #pragma pop
233 }
234
nnosGetDeviceMemoryAddress()235 uptr nnosGetDeviceMemoryAddress()
236 {
237 return nn::os::GetDeviceMemoryAddress();
238 }
239
240 }
241