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