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: 17610 $
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 "os_AddressSpaceManager.h"
30 
31 //---------------------------------------------------------------------------
32 
33 using namespace nn;
34 using namespace nn::svc;
35 
36 namespace nn{ namespace os{
37 
38     namespace
39     {
40         nnosAddressSpaceManager s_SpaceManager;
41     }
42 
43     namespace detail
44     {
InitializeStackMemory()45         void InitializeStackMemory()
46         {
47             nnosAddressSpaceManagerInitialize(&s_SpaceManager, NN_OS_ADDR_STACK_BEGIN, NN_OS_ADDR_STACK_SIZE);
48         }
49     }
50 
51 
Initialize(void * pMem,size_t size)52 void StackMemory::Initialize(void* pMem, size_t size)
53 {
54     // 未初期化であることをチェックします。
55     NN_TASSERT_( GetAddress() == NULL );
56     NN_ALIGN_TASSERT_( pMem, NN_OS_MEMORY_PAGE_SIZE );
57     NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
58 
59 
60     // 仮想アドレス空間からメモリを取得します。
61     uptr addr = nnosAddressSpaceManagerAllocate(&s_SpaceManager, detail::ConvertToC(this), size, NN_OS_MEMORY_PAGE_SIZE);
62     if (addr == NULL)
63     {
64         NN_TPANIC_("failed to allocate address space.");
65     }
66 
67     m_MemoryAddress = reinterpret_cast<uptr>(pMem);
68 
69     Result result;
70     uptr dummy;
71     result = nn::svc::ControlMemory( &dummy,
72                                      addr,
73                                      m_MemoryAddress,
74                                      size,
75                                      nn::os::MEMORY_OPERATION_MAP,
76                                      nn::os::MEMORY_PERMISSION_READ_WRITE );
77     NN_UTIL_PANIC_IF_FAILED(result);
78 
79     result = nn::svc::ControlMemory( &dummy,
80                                      m_MemoryAddress,
81                                      NULL,
82                                      size,
83                                      nn::os::MEMORY_OPERATION_PROTECT,
84                                      nn::os::MEMORY_PERMISSION_NONE );
85     NN_UTIL_PANIC_IF_FAILED(result);
86 }
87 
Finalize()88 void* StackMemory::Finalize()
89 {
90     if ( GetAddress() != NULL )
91     {
92         const uptr addr = GetAddress();
93         const size_t size = GetSize();
94         const uptr memAddr = m_MemoryAddress;
95 
96         nnosAddressSpaceManagerFree(&s_SpaceManager, detail::ConvertToC(this));
97 
98         Result result;
99         uptr dummy;
100         result = nn::svc::ControlMemory( &dummy,
101                                          addr,
102                                          NULL,
103                                          size,
104                                          nn::os::MEMORY_OPERATION_FREE,
105                                          nn::os::MEMORY_PERMISSION_READ_WRITE );
106         NN_UTIL_PANIC_IF_FAILED(result);
107         // これ以降 this にアクセスしてはいけない
108 
109         result = nn::svc::ControlMemory( &dummy,
110                                          memAddr,
111                                          NULL,
112                                          size,
113                                          nn::os::MEMORY_OPERATION_PROTECT,
114                                          nn::os::MEMORY_PERMISSION_READ_WRITE );
115         NN_UTIL_PANIC_IF_FAILED(result);
116 
117         return reinterpret_cast<void*>(memAddr);
118     }
119 
120     return NULL;
121 }
122 
MoveFrom(StackMemory * pFrom)123 void StackMemory::MoveFrom(StackMemory* pFrom)
124 {
125     reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager)->Switch(this, pFrom);
126     this->m_MemoryAddress = pFrom->m_MemoryAddress;
127     pFrom->m_MemoryAddress = NULL;
128 }
129 
130 
131 }} // namespace nn::os
132 
133 
134 #include <new>
135 using namespace nn::os;
136 
137 extern "C" {
138 
139 // StackMemory
140 
nnosStackMemoryProtect(nnosStackMemory * p,void * pMem,size_t size)141 void nnosStackMemoryProtect(nnosStackMemory* p, void* pMem, size_t size)
142 {
143     new (p) StackMemory(pMem, size);
144 }
145 
nnosStackMemoryUnprotect(nnosStackMemory * p)146 void nnosStackMemoryUnprotect(nnosStackMemory* p)
147 {
148     StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
149     pStackMemory->~StackMemory();
150 }
151 
nnosStackMemoryGetAddress(nnosStackMemory * p)152 uptr nnosStackMemoryGetAddress(nnosStackMemory* p)
153 {
154     StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
155     return pStackMemory->GetAddress();
156 }
157 
nnosStackMemoryGetSize(nnosStackMemory * p)158 size_t nnosStackMemoryGetSize(nnosStackMemory* p)
159 {
160     StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
161     return pStackMemory->GetSize();
162 }
163 
nnosStackMemoryGetStackBottom(nnosStackMemory * p)164 uptr nnosStackMemoryGetStackBottom(nnosStackMemory* p)
165 {
166     StackMemory* pStackMemory = reinterpret_cast<StackMemory*>(p);
167     return pStackMemory->GetStackBottom();
168 }
169 
170 }
171 #endif  // if NN_PLATFORM_HAS_MMU
172