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