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