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: 17610 $
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/svc/svc_Stub.h>
29 #include <nn/util/util_Result.h>
30 
31 #include "os_AddressSpaceManager.h"
32 
33 //---------------------------------------------------------------------------
34 
35 using namespace nn;
36 using namespace nn::svc;
37 
38 namespace nn{ namespace os{
39 
40     namespace
41     {
42         nnosAddressSpaceManager s_SpaceManager;
43         bool s_IsMemoryBlockEnabled = false;
44     }
45 
46     namespace detail
47     {
AllocateFromMemoryBlockSpace(MemoryBlockBase * p,size_t s)48         uptr AllocateFromMemoryBlockSpace(MemoryBlockBase* p, size_t s)
49         {
50             AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
51             return pManager->Allocate(p, s, 0);
52         }
FreeToMemoryBlockSpace(MemoryBlockBase * p)53         void FreeToMemoryBlockSpace(MemoryBlockBase* p)
54         {
55             AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
56             pManager->Free(p);
57         }
Switch(MemoryBlock * pTo,MemoryBlock * pFrom)58         void Switch(MemoryBlock* pTo, MemoryBlock* pFrom)
59         {
60             nnosAddressSpaceManagerSwitch(&s_SpaceManager, ConvertToC(pTo), ConvertToC(pFrom));
61         }
62 
IsMemoryBlockEnabled()63         bool IsMemoryBlockEnabled()
64         {
65             return s_IsMemoryBlockEnabled;
66         }
67     }
68 
Initialize(size_t size)69 void MemoryBlock::Initialize(size_t size)
70 {
71     // 未初期化であることをチェックします。
72     NN_TASSERT_(detail::IsMemoryBlockEnabled());
73     NN_TASSERT_(!GetAddress());
74 
75     // 仮想アドレス空間からメモリを取得します。
76     size = GetPageAlignedSize(size);
77     uptr addr = detail::AllocateFromMemoryBlockSpace(this, size);
78     if (addr == 0)
79     {
80         NN_TPANIC_("Out Of Memory.");
81     }
82     this->MemoryBlockBase::SetReadOnly(false);
83 }
84 
Finalize()85 void MemoryBlock::Finalize()
86 {
87     if (GetAddress())
88     {
89         // メモリブロックを仮想メモリ空間に戻します。
90         detail::FreeToMemoryBlockSpace(this);
91     }
92 }
93 
94 // 読み込み専用属性を設定します。
SetReadOnly(bool readOnly)95 void MemoryBlock::SetReadOnly(bool readOnly)
96 {
97     NN_TASSERT_(GetAddress());
98     if (IsReadOnly() == readOnly)
99     {
100         return;
101     }
102     this->MemoryBlockBase::SetReadOnly(readOnly);
103 }
104 
105 
106 
InitializeMemoryBlock(uptr begin,size_t size)107 void InitializeMemoryBlock(uptr begin, size_t size)
108 {
109     s_IsMemoryBlockEnabled = true;
110     nnosAddressSpaceManagerInitialize(&s_SpaceManager, begin, size);
111 }
112 
113 
114 }} // namespace nn::os
115 
116 
117 #include <new>
118 using namespace nn::os;
119 
120 extern "C" {
121 
122 // MemoryBlock
123 
nnosMemoryBlockAllocate(nnosMemoryBlock * p,size_t size)124 void nnosMemoryBlockAllocate(nnosMemoryBlock* p, size_t size)
125 {
126     NN_TASSERT_(detail::IsMemoryBlockEnabled());
127     new (p) MemoryBlock(size);
128 }
129 
nnosMemoryBlockSetReadOnly(nnosMemoryBlock * p,bool readOnly)130 void nnosMemoryBlockSetReadOnly(nnosMemoryBlock* p, bool readOnly)
131 {
132     MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
133     pMemoryBlock->SetReadOnly(readOnly);
134 }
135 
nnosMemoryBlockFree(nnosMemoryBlock * p)136 void nnosMemoryBlockFree(nnosMemoryBlock* p)
137 {
138     MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
139     pMemoryBlock->~MemoryBlock();
140 }
141 
nnosMemoryBlockGetAddress(nnosMemoryBlock * p)142 uptr nnosMemoryBlockGetAddress(nnosMemoryBlock* p)
143 {
144     MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
145     return pMemoryBlock->GetAddress();
146 }
147 
nnosMemoryBlockGetSize(nnosMemoryBlock * p)148 size_t nnosMemoryBlockGetSize(nnosMemoryBlock* p)
149 {
150     MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
151     return pMemoryBlock->GetSize();
152 }
153 
nnosMemoryBlockIsReadOnly(nnosMemoryBlock * p)154 bool nnosMemoryBlockIsReadOnly(nnosMemoryBlock* p)
155 {
156     MemoryBlock* pMemoryBlock = reinterpret_cast<MemoryBlock*>(p);
157     return pMemoryBlock->IsReadOnly();
158 }
159 
160 
161 }
162 #endif  // if NN_PLATFORM_HAS_MMU
163