1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_StackMemory.cpp
4
5 Copyright (C)2009-2012 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: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/config.h>
17 #if NN_PLATFORM_HAS_MMU
18
19 #include <nn/os/os_StackMemory.h>
20 #include <nn/os/os_MemoryBlock.h>
21 #include <nn/os/os_Result.h>
22 #include <nn/assert.h>
23 #include <nn/svc/svc_Stub.h>
24 #include <nn/dbg/dbg_Logger.h>
25 #include <nn/util/util_Result.h>
26 #include <nn/os/os_Memory.h>
27 #include <nn/os/os_CriticalSection.h>
28 #include <nn/os/os_MemoryMapSelect.h>
29 #include <nn/os/os_ErrorHandlerSelect.h>
30 #include "os_AddressSpaceManager.h"
31
32 //---------------------------------------------------------------------------
33
34 using namespace nn;
35 using namespace nn::svc;
36
37 namespace nn{ namespace os{
38
39 namespace
40 {
41 nnosAddressSpaceManager s_SpaceManager;
42 }
43
44 namespace detail
45 {
InitializeStackMemory()46 void InitializeStackMemory()
47 {
48 nnosAddressSpaceManagerInitialize(&s_SpaceManager, NN_OS_ADDR_STACK_BEGIN, NN_OS_ADDR_STACK_SIZE);
49 }
50 }
51
52
Initialize(void * pMem,size_t size)53 void StackMemory::Initialize(void* pMem, size_t size)
54 {
55 NN_OS_ERROR_IF_FAILED(TryInitialize(pMem, size));
56 }
57
TryInitialize(void * pMem,size_t size)58 Result StackMemory::TryInitialize(void* pMem, size_t size)
59 {
60 // Check that it is uninitialized.
61 if ( GetAddress() )
62 {
63 return ResultAlreadyInitialized();
64 }
65
66 // Check alignment.
67 //NN_ALIGN_TASSERT_( pMem, NN_OS_MEMORY_PAGE_SIZE );
68 //NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
69 if ( ( size % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
70 {
71 return ResultMisalignedSize();
72 }
73 if ( ( reinterpret_cast<uptr>(pMem) % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
74 {
75 return ResultMisalignedAddress();
76 }
77
78 // Get memory from the virtual address space.
79 uptr addr = nnosAddressSpaceManagerAllocate(&s_SpaceManager, os::detail::ConvertToC(this), size, NN_OS_MEMORY_PAGE_SIZE);
80 if (addr == NULL)
81 {
82 return ResultNoAddressSpace();
83 }
84
85 m_MemoryAddress = reinterpret_cast<uptr>(pMem);
86
87 Result result;
88 uptr dummy;
89 result = nn::svc::ControlMemory( &dummy,
90 addr,
91 m_MemoryAddress,
92 size,
93 nn::os::MEMORY_OPERATION_MAP,
94 nn::os::MEMORY_PERMISSION_READ_WRITE );
95
96 if ( result.IsFailure() )
97 {
98 nnosAddressSpaceManagerFree(&s_SpaceManager, os::detail::ConvertToC(this));
99
100 return result;
101 }
102
103 result = nn::svc::ControlMemory( &dummy,
104 m_MemoryAddress,
105 NULL,
106 size,
107 nn::os::MEMORY_OPERATION_PROTECT,
108 nn::os::MEMORY_PERMISSION_NONE );
109
110 if ( result.IsFailure() )
111 {
112 uptr memAddr = m_MemoryAddress;
113
114 nnosAddressSpaceManagerFree(&s_SpaceManager, os::detail::ConvertToC(this));
115
116 nn::svc::ControlMemory( &dummy,
117 addr,
118 memAddr,
119 size,
120 nn::os::MEMORY_OPERATION_UNMAP,
121 nn::os::MEMORY_PERMISSION_READ_WRITE );
122 }
123
124 return result;
125 }
126
Finalize()127 void* StackMemory::Finalize()
128 {
129 if ( GetAddress() != NULL )
130 {
131 const uptr addr = GetAddress();
132 const size_t size = GetSize();
133 const uptr memAddr = m_MemoryAddress;
134
135 nnosAddressSpaceManagerFree(&s_SpaceManager, os::detail::ConvertToC(this));
136
137 Result result;
138 uptr dummy;
139 result = nn::svc::ControlMemory( &dummy,
140 addr,
141 memAddr,
142 size,
143 nn::os::MEMORY_OPERATION_UNMAP,
144 nn::os::MEMORY_PERMISSION_READ_WRITE );
145 NN_OS_ERROR_IF_FAILED(result);
146 // Hereafter, must not access this
147
148 result = nn::svc::ControlMemory( &dummy,
149 memAddr,
150 NULL,
151 size,
152 nn::os::MEMORY_OPERATION_PROTECT,
153 nn::os::MEMORY_PERMISSION_READ_WRITE );
154 NN_OS_ERROR_IF_FAILED(result);
155
156 return reinterpret_cast<void*>(memAddr);
157 }
158
159 return NULL;
160 }
161
MoveFrom(StackMemory * pFrom)162 void StackMemory::MoveFrom(StackMemory* pFrom)
163 {
164 reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager)->Switch(this, pFrom);
165 this->m_MemoryAddress = pFrom->m_MemoryAddress;
166 pFrom->m_MemoryAddress = NULL;
167 }
168
169
170 }} // namespace nn::os
171
172
173 #include <new>
174 using namespace nn::os;
175
176 extern "C" {
177
178 // StackMemory
179
nnosStackMemoryProtect(nnosStackMemory * p,void * pMem,size_t size)180 void nnosStackMemoryProtect(nnosStackMemory* p, void* pMem, size_t size)
181 {
182 new (p) StackMemory(pMem, size);
183 }
184
nnosStackMemoryUnprotect(nnosStackMemory * p)185 void nnosStackMemoryUnprotect(nnosStackMemory* p)
186 {
187 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
188 pStackMemory->~StackMemory();
189 }
190
nnosStackMemoryGetAddress(nnosStackMemory * p)191 uptr nnosStackMemoryGetAddress(nnosStackMemory* p)
192 {
193 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
194 return pStackMemory->GetAddress();
195 }
196
nnosStackMemoryGetSize(nnosStackMemory * p)197 size_t nnosStackMemoryGetSize(nnosStackMemory* p)
198 {
199 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
200 return pStackMemory->GetSize();
201 }
202
nnosStackMemoryGetStackBottom(nnosStackMemory * p)203 uptr nnosStackMemoryGetStackBottom(nnosStackMemory* p)
204 {
205 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
206 return pStackMemory->GetStackBottom();
207 }
208
209 }
210 #endif // if NN_PLATFORM_HAS_MMU
211