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