1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_MemoryBlock.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
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_(detail::IsMemoryBlockEnabled(), "InitializeMemoryBlock is not called.\n");
74 NN_TASSERTMSG_(GetAddress() == 0, "This MemoryBlock instance has been already initialized.\n");
75 if ( !detail::IsMemoryBlockEnabled() || GetAddress() != 0 )
76 {
77 return;
78 }
79
80 // Get memory from the virtual address space.
81 size = GetPageAlignedSize(size);
82 uptr addr = 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 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 s_IsMemoryBlockEnabled = true;
119 nnosAddressSpaceManagerInitialize(&s_SpaceManager, begin, size);
120 }
121 }
122
123
124 }} // namespace nn::os
125
126
127 #include <new>
128 using namespace nn::os;
129
130 extern "C" {
131
132 // MemoryBlock
133
nnosMemoryBlockAllocate(nnosMemoryBlock * p,size_t size)134 void nnosMemoryBlockAllocate(nnosMemoryBlock* p, size_t size)
135 {
136 NN_TASSERT_(detail::IsMemoryBlockEnabled());
137 new (p) MemoryBlock(size);
138 }
139
nnosMemoryBlockSetReadOnly(nnosMemoryBlock * p,bool readOnly)140 void nnosMemoryBlockSetReadOnly(nnosMemoryBlock* p, bool readOnly)
141 {
142 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
143 pMemoryBlock->SetReadOnly(readOnly);
144 }
145
nnosMemoryBlockFree(nnosMemoryBlock * p)146 void nnosMemoryBlockFree(nnosMemoryBlock* p)
147 {
148 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
149 pMemoryBlock->~MemoryBlock();
150 }
151
nnosMemoryBlockGetAddress(nnosMemoryBlock * p)152 uptr nnosMemoryBlockGetAddress(nnosMemoryBlock* p)
153 {
154 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
155 return pMemoryBlock->GetAddress();
156 }
157
nnosMemoryBlockGetSize(nnosMemoryBlock * p)158 size_t nnosMemoryBlockGetSize(nnosMemoryBlock* p)
159 {
160 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
161 return pMemoryBlock->GetSize();
162 }
163
nnosMemoryBlockIsReadOnly(nnosMemoryBlock * p)164 bool nnosMemoryBlockIsReadOnly(nnosMemoryBlock* p)
165 {
166 MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
167 return pMemoryBlock->IsReadOnly();
168 }
169
170
171 }
172 #endif // if NN_PLATFORM_HAS_MMU
173