1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_MemoryBlock.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
20 #include <nn/assert.h>
21 #include <nn/dbg/dbg_Logger.h>
22 #include <nn/os/os_CriticalSection.h>
23 #include <nn/os/os_Memory.h>
24 #include <nn/os/os_MemoryBlock.h>
25 #include <nn/os/os_MemoryMapSelect.h>
26 #include <nn/os/os_Result.h>
27 #include <nn/os/os_StackMemoryBlock.h>
28 #include <nn/os/os_ErrorHandlerSelect.h>
29 #include <nn/svc/svc_Stub.h>
30 #include <nn/util/util_Result.h>
31
32 #include "os_AddressSpaceManager.h"
33
34 //---------------------------------------------------------------------------
35
36 using namespace nn;
37 using namespace nn::svc;
38
39 namespace nn{ namespace os{
40
41 namespace
42 {
43 nnosAddressSpaceManager s_SpaceManager;
44 bool s_IsMemoryBlockEnabled = false;
45 }
46
47 namespace detail
48 {
AllocateFromMemoryBlockSpace(MemoryBlockBase * p,size_t s)49 uptr AllocateFromMemoryBlockSpace(MemoryBlockBase* p, size_t s)
50 {
51 AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
52 return pManager->Allocate(p, s, 0);
53 }
FreeToMemoryBlockSpace(MemoryBlockBase * p)54 void FreeToMemoryBlockSpace(MemoryBlockBase* p)
55 {
56 AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
57 pManager->Free(p);
58 }
Switch(MemoryBlock * pTo,MemoryBlock * pFrom)59 void Switch(MemoryBlock* pTo, MemoryBlock* pFrom)
60 {
61 nnosAddressSpaceManagerSwitch(&s_SpaceManager, ConvertToC(pTo), ConvertToC(pFrom));
62 }
63
IsMemoryBlockEnabled()64 bool IsMemoryBlockEnabled()
65 {
66 return s_IsMemoryBlockEnabled;
67 }
68 }
69
Initialize(size_t size)70 void MemoryBlock::Initialize(size_t size)
71 {
72 // Check that the memory block has been initialized and that this instance is not initialized.
73 NN_TASSERTMSG_(os::detail::IsMemoryBlockEnabled(), "InitializeMemoryBlock is not called.\n");
74 NN_TASSERTMSG_(GetAddress() == 0, "This MemoryBlock instance has already been initialized.\n");
75 if ( !os::detail::IsMemoryBlockEnabled() || GetAddress() != 0 )
76 {
77 return;
78 }
79
80 // Get memory from the virtual address space.
81 size = GetPageAlignedSize(size);
82 uptr addr = os::detail::AllocateFromMemoryBlockSpace(this, size);
83 if (addr == 0)
84 {
85 NN_OS_ERROR_IF_FAILED(ResultNoAddressSpace());
86 }
87 this->MemoryBlockBase::SetReadOnly(false);
88 }
89
Finalize()90 void MemoryBlock::Finalize()
91 {
92 if (GetAddress())
93 {
94 // Return the memory block to the virtual memory space.
95 os::detail::FreeToMemoryBlockSpace(this);
96 }
97 }
98
99 // Set the read-only attribute.
SetReadOnly(bool readOnly)100 void MemoryBlock::SetReadOnly(bool readOnly)
101 {
102 NN_TASSERT_(GetAddress());
103 if (GetAddress() )
104 {
105 if (IsReadOnly() == readOnly)
106 {
107 return;
108 }
109 this->MemoryBlockBase::SetReadOnly(readOnly);
110 }
111 }
112
113
InitializeMemoryBlock(uptr begin,size_t size)114 void InitializeMemoryBlock(uptr begin, size_t size)
115 {
116 if ( s_IsMemoryBlockEnabled )
117 {
118 NN_TASSERTMSG_(false, "nn::os::InitializeMemoryBlock() called twice.");
119 }
120 else
121 {
122 s_IsMemoryBlockEnabled = true;
123 nnosAddressSpaceManagerInitialize(&s_SpaceManager, begin, size);
124 }
125 }
126
127
128 }} // namespace nn::os
129
130
131 #include <new>
132 using namespace nn::os;
133
134 extern "C" {
135
136 // MemoryBlock
137
nnosMemoryBlockAllocate(nnosMemoryBlock * p,size_t size)138 void nnosMemoryBlockAllocate(nnosMemoryBlock* p, size_t size)
139 {
140 NN_TASSERT_(os::detail::IsMemoryBlockEnabled());
141 new (p) MemoryBlock(size);
142 }
143
nnosMemoryBlockSetReadOnly(nnosMemoryBlock * p,bool readOnly)144 void nnosMemoryBlockSetReadOnly(nnosMemoryBlock* p, bool readOnly)
145 {
146 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
147 pMemoryBlock->SetReadOnly(readOnly);
148 }
149
nnosMemoryBlockFree(nnosMemoryBlock * p)150 void nnosMemoryBlockFree(nnosMemoryBlock* p)
151 {
152 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
153 pMemoryBlock->~MemoryBlock();
154 }
155
nnosMemoryBlockGetAddress(nnosMemoryBlock * p)156 uptr nnosMemoryBlockGetAddress(nnosMemoryBlock* p)
157 {
158 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
159 return pMemoryBlock->GetAddress();
160 }
161
nnosMemoryBlockGetSize(nnosMemoryBlock * p)162 size_t nnosMemoryBlockGetSize(nnosMemoryBlock* p)
163 {
164 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
165 return pMemoryBlock->GetSize();
166 }
167
nnosMemoryBlockIsReadOnly(nnosMemoryBlock * p)168 bool nnosMemoryBlockIsReadOnly(nnosMemoryBlock* p)
169 {
170 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
171 return pMemoryBlock->IsReadOnly();
172 }
173
174
175 }
176 #endif // if NN_PLATFORM_HAS_MMU
177