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