00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef __EMULATORUTILITY_VIRTUAL_MEMORY_H__
00033 #define __EMULATORUTILITY_VIRTUAL_MEMORY_H__
00034
00035 #include "Emu/Utility/System/Memory/HeapAllocator.h"
00036
00037
00038 namespace Onikiri {
00039 namespace EmulatorUtility {
00040
00041
00042 static const int VIRTUAL_MEMORY_PAGE_SIZE_BITS = 12;
00043
00044
00045 typedef u32 VIRTUAL_MEMORY_ATTR_TYPE;
00046 static const u32 VIRTUAL_MEMORY_ATTR_READ = 1 << 0;
00047 static const u32 VIRTUAL_MEMORY_ATTR_WRITE = 1 << 1;
00048 static const u32 VIRTUAL_MEMORY_ATTR_EXEC = 1 << 2;
00049
00050
00051
00052 struct PhysicalMemoryPage
00053 {
00054 u8* ptr;
00055 int refCount;
00056 };
00057
00058
00059
00060 struct PageTableEntry
00061 {
00062 PhysicalMemoryPage* phyPage;
00063 VIRTUAL_MEMORY_ATTR_TYPE attr;
00064 };
00065
00066
00067 class TLB
00068 {
00069 protected:
00070 u64 m_addr;
00071 bool m_valid;
00072 PageTableEntry m_body;
00073 u64 m_offsetBits;
00074 u64 m_addrMask;
00075
00076 public:
00077 TLB( int offsetBits );
00078 ~TLB();
00079 bool Lookup( u64 addr, PageTableEntry* entry ) const;
00080 void Write( u64 addr, const PageTableEntry& entry );
00081 void Flush();
00082 };
00083
00084
00085 class PageTable
00086 {
00087 public:
00088
00089 explicit PageTable(int offsetBits);
00090 ~PageTable();
00091
00092
00093 size_t GetPageSize() const;
00094
00095
00096 int GetOffsetBits() const;
00097
00098
00099 u64 GetOffsetMask() const;
00100
00101
00102 void *TargetToHost(u64 addr);
00103
00104
00105
00106 void AddMap(u64 targetAddr, u8* hostAddr, VIRTUAL_MEMORY_ATTR_TYPE attr);
00107 bool IsMapped(u64 targetAddr) const;
00108
00109
00110
00111 void CopyMap( u64 dstTargetAddr, u64 srcTargetAddr, VIRTUAL_MEMORY_ATTR_TYPE dstAttr );
00112
00113
00114 bool GetMap( u64 targetAddr, PageTableEntry* page );
00115 bool SetMap( u64 targetAddr, const PageTableEntry& page );
00116
00117
00118 int GetPageReferenceCount( u64 targetAddr );
00119
00120
00121
00122 int RemoveMap(u64 targetAddr);
00123
00124 private:
00125 class AddrHash
00126 {
00127 private:
00128 int m_offsetBits;
00129 public:
00130 explicit AddrHash(int offsetBits) : m_offsetBits(offsetBits) {}
00131
00132 size_t operator()(const u64 value) const
00133 {
00134 return (size_t)(value >> m_offsetBits);
00135 }
00136 };
00137 typedef unordered_map<u64, PageTableEntry, AddrHash > map_type;
00138 map_type m_map;
00139 int m_offsetBits;
00140 u64 m_offsetMask;
00141 TLB m_tlb;
00142 boost::pool<> m_phyPagePool;
00143 };
00144
00145
00146 class VirtualMemory
00147 {
00148 public:
00149 VirtualMemory( int pid, bool bigEndian, SystemIF* simSystem );
00150 ~VirtualMemory();
00151
00152
00153 void ReadMemory( MemAccess* access );
00154 void WriteMemory( MemAccess* access );
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 void TargetMemset(u64 targetAddr, int value, u64 size);
00166
00167 void MemCopyToHost(void* dst, u64 src, u64 size);
00168
00169 void MemCopyToTarget(u64 dst, const void* src, u64 size);
00170
00171
00172 u64 GetPageSize() const;
00173
00174
00175 void AssignPhysicalMemory(u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr);
00176
00177 void AssignPhysicalMemory(u64 addr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr);
00178
00179 void FreePhysicalMemory(u64 addr);
00180
00181 void FreePhysicalMemory(u64 addr, u64 size);
00182
00183
00184 void SetPhysicalMemoryMapping( u64 dstAddr, u64 srcAddr, VIRTUAL_MEMORY_ATTR_TYPE attr );
00185
00186 void SetPhysicalMemoryMapping( u64 dstAddr, u64 srcAddr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr );
00187
00188
00189 void AssignAndCopyPhysicalMemory( u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr );
00190
00191 void AssignAndCopyPhysicalMemory( u64 addr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr );
00192
00193
00194 void SetPageAttribute( u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr );
00195
00196
00197
00198 bool CopyPageOnWrite( u64 addr );
00199
00200
00201 bool IsBigEndian() const {
00202 return m_bigEndian;
00203 }
00204
00205 private:
00206
00207
00208
00209
00210 template <typename Iter>
00211 int SplitAtMapUnitBoundary(u64 addr, u64 size, Iter e) const;
00212
00213 struct MemoryBlock {
00214 MemoryBlock(u64 addr, u64 size) { this->addr = addr; this->size = size; }
00215 u64 addr;
00216 u64 size;
00217 };
00218 typedef std::vector<MemoryBlock> BlockArray;
00219
00220
00221 PageTable m_pageTbl;
00222 boost::pool<> m_pool;
00223
00224
00225 SystemIF* m_simSystem;
00226
00227
00228 int m_pid;
00229
00230
00231 bool m_bigEndian;
00232
00233 };
00234
00235
00236 }
00237 }
00238
00239 #endif