1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_StackMemory.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/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, 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 NN_UTIL_RETURN_IF_FAILED(result);
96
97 result = nn::svc::ControlMemory( &dummy,
98 m_MemoryAddress,
99 NULL,
100 size,
101 nn::os::MEMORY_OPERATION_PROTECT,
102 nn::os::MEMORY_PERMISSION_NONE );
103 return result;
104 }
105
Finalize()106 void* StackMemory::Finalize()
107 {
108 if ( GetAddress() != NULL )
109 {
110 const uptr addr = GetAddress();
111 const size_t size = GetSize();
112 const uptr memAddr = m_MemoryAddress;
113
114 nnosAddressSpaceManagerFree(&s_SpaceManager, detail::ConvertToC(this));
115
116 Result result;
117 uptr dummy;
118 result = nn::svc::ControlMemory( &dummy,
119 addr,
120 memAddr,
121 size,
122 nn::os::MEMORY_OPERATION_UNMAP,
123 nn::os::MEMORY_PERMISSION_READ_WRITE );
124 NN_OS_ERROR_IF_FAILED(result);
125 // Hereafter, must not access this
126
127 result = nn::svc::ControlMemory( &dummy,
128 memAddr,
129 NULL,
130 size,
131 nn::os::MEMORY_OPERATION_PROTECT,
132 nn::os::MEMORY_PERMISSION_READ_WRITE );
133 NN_OS_ERROR_IF_FAILED(result);
134
135 return reinterpret_cast<void*>(memAddr);
136 }
137
138 return NULL;
139 }
140
MoveFrom(StackMemory * pFrom)141 void StackMemory::MoveFrom(StackMemory* pFrom)
142 {
143 reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager)->Switch(this, pFrom);
144 this->m_MemoryAddress = pFrom->m_MemoryAddress;
145 pFrom->m_MemoryAddress = NULL;
146 }
147
148
149 }} // namespace nn::os
150
151
152 #include <new>
153 using namespace nn::os;
154
155 extern "C" {
156
157 // StackMemory
158
nnosStackMemoryProtect(nnosStackMemory * p,void * pMem,size_t size)159 void nnosStackMemoryProtect(nnosStackMemory* p, void* pMem, size_t size)
160 {
161 new (p) StackMemory(pMem, size);
162 }
163
nnosStackMemoryUnprotect(nnosStackMemory * p)164 void nnosStackMemoryUnprotect(nnosStackMemory* p)
165 {
166 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
167 pStackMemory->~StackMemory();
168 }
169
nnosStackMemoryGetAddress(nnosStackMemory * p)170 uptr nnosStackMemoryGetAddress(nnosStackMemory* p)
171 {
172 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
173 return pStackMemory->GetAddress();
174 }
175
nnosStackMemoryGetSize(nnosStackMemory * p)176 size_t nnosStackMemoryGetSize(nnosStackMemory* p)
177 {
178 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
179 return pStackMemory->GetSize();
180 }
181
nnosStackMemoryGetStackBottom(nnosStackMemory * p)182 uptr nnosStackMemoryGetStackBottom(nnosStackMemory* p)
183 {
184 StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
185 return pStackMemory->GetStackBottom();
186 }
187
188 }
189 #endif // if NN_PLATFORM_HAS_MMU
190