クラス Onikiri::EmulatorUtility::VirtualMemory

#include <VirtualMemory.h>

Onikiri::EmulatorUtility::VirtualMemoryのコラボレーション図

Collaboration graph
[凡例]
すべてのメンバ一覧

Public メソッド

void AssignAndCopyPhysicalMemory (u64 addr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr)
void AssignAndCopyPhysicalMemory (u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr)
void AssignPhysicalMemory (u64 addr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr)
void AssignPhysicalMemory (u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr)
bool CopyPageOnWrite (u64 addr)
void FreePhysicalMemory (u64 addr, u64 size)
void FreePhysicalMemory (u64 addr)
u64 GetPageSize () const
bool IsBigEndian () const
void MemCopyToHost (void *dst, u64 src, u64 size)
void MemCopyToTarget (u64 dst, const void *src, u64 size)
void ReadMemory (MemAccess *access)
void SetPageAttribute (u64 addr, VIRTUAL_MEMORY_ATTR_TYPE attr)
void SetPhysicalMemoryMapping (u64 dstAddr, u64 srcAddr, u64 size, VIRTUAL_MEMORY_ATTR_TYPE attr)
void SetPhysicalMemoryMapping (u64 dstAddr, u64 srcAddr, VIRTUAL_MEMORY_ATTR_TYPE attr)
void TargetMemset (u64 targetAddr, int value, u64 size)
 VirtualMemory (int pid, bool bigEndian, SystemIF *simSystem)
void WriteMemory (MemAccess *access)
 ~VirtualMemory ()

構成

struct  MemoryBlock

説明

VirtualMemory.h146 行で定義されています。


コンストラクタとデストラクタ

VirtualMemory::VirtualMemory ( int  pid,
bool  bigEndian,
SystemIF simSystem 
)

VirtualMemory.cpp307 行で定義されています。

00307                                                                            : 
00308     m_pageTbl( VIRTUAL_MEMORY_PAGE_SIZE_BITS ),     // Prbgw
00309     m_pool( m_pageTbl.GetPageSize() ),      // m_pageTbl PvZ
00310     m_simSystem( simSystem ),
00311     m_pid(pid),
00312     m_bigEndian(bigEndian)
00313 {
00314 }

VirtualMemory::~VirtualMemory (  ) 

VirtualMemory.cpp316 行で定義されています。

00317 {
00318 }


関数

void VirtualMemory::AssignAndCopyPhysicalMemory ( u64  addr,
u64  size,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp601 行で定義されています。

参照先 AssignAndCopyPhysicalMemory().

00602 {
00603     BlockArray blocks;
00604     SplitAtMapUnitBoundary(addr, size, back_inserter(blocks) );
00605     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e){
00606         AssignAndCopyPhysicalMemory(e->addr, attr);
00607     }
00608 }

関数の呼び出しグラフ:

void VirtualMemory::AssignAndCopyPhysicalMemory ( u64  addr,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp582 行で定義されています。

参照先 AssignPhysicalMemory()Onikiri::EmulatorUtility::PageTable::GetMap()Onikiri::EmulatorUtility::PageTable::GetOffsetMask()GetPageSize()MemCopyToTarget()Onikiri::EmulatorUtility::PageTableEntry::phyPageOnikiri::EmulatorUtility::PhysicalMemoryPage::ptrOnikiri::EmulatorUtility::PhysicalMemoryPage::refCountOnikiri::EmulatorUtility::PageTable::RemoveMap()THROW_RUNTIME_ERROR.

参照元 AssignAndCopyPhysicalMemory()CopyPageOnWrite().

00583 {
00584     PageTableEntry page;
00585     if( !m_pageTbl.GetMap( addr, &page ) ) {
00586         THROW_RUNTIME_ERROR( "The specified address is not mapped." );
00587         return; // To avoid compiler's warning "Uninitialized 'page' is used".
00588     }
00589 
00590     // Do not need to copy in this case.
00591     if( page.phyPage->refCount == 1 ){
00592         return;
00593     }
00594 
00595     m_pageTbl.RemoveMap( addr );
00596     AssignPhysicalMemory( addr, attr );
00597     MemCopyToTarget( addr & m_pageTbl.GetOffsetMask(), page.phyPage->ptr, GetPageSize() );
00598 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::AssignPhysicalMemory ( u64  addr,
u64  size,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp514 行で定義されています。

参照先 AssignPhysicalMemory().

00515 {
00516     BlockArray blocks;
00517     SplitAtMapUnitBoundary(addr, size, back_inserter(blocks) );
00518 
00519     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e){
00520         AssignPhysicalMemory(e->addr, attr);
00521     }
00522 }

関数の呼び出しグラフ:

void VirtualMemory::AssignPhysicalMemory ( u64  addr,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp493 行で定義されています。

参照先 Onikiri::EmulatorUtility::PageTable::AddMap()GetPageSize()Onikiri::EmulatorUtility::PageTable::IsMapped()Onikiri::SystemIF::NotifyMemoryAllocation()THROW_RUNTIME_ERROR.

参照元 AssignAndCopyPhysicalMemory()AssignPhysicalMemory()Onikiri::EmulatorUtility::MemorySystem::AssignPhysicalMemory()Onikiri::EmulatorUtility::MemorySystem::Brk()Onikiri::EmulatorUtility::MemorySystem::MemorySystem()Onikiri::EmulatorUtility::MemorySystem::MMap()Onikiri::EmulatorUtility::MemorySystem::MRemap().

00494 {
00495     if (m_pageTbl.IsMapped(addr)) {
00496         THROW_RUNTIME_ERROR( "The specified target address is already mapped." );
00497         //THROW_RUNTIME_ERROR( "%08x%08x is already mapped.", (u32)(addr >> 32), (u32)(addr & 0xffffffff) );
00498         return;
00499     }
00500 
00501     void* mem = m_pool.malloc();
00502     if (!mem)
00503         THROW_RUNTIME_ERROR("out of memory");
00504     m_pageTbl.AddMap(addr, (u8*)mem, attr);
00505     memset(mem, 0, (size_t)GetPageSize());
00506 
00507     m_simSystem->NotifyMemoryAllocation(
00508         Addr( m_pid, TID_INVALID, addr),
00509         GetPageSize(),
00510         true 
00511     );
00512 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

bool VirtualMemory::CopyPageOnWrite ( u64  addr  ) 

VirtualMemory.cpp624 行で定義されています。

参照先 AssignAndCopyPhysicalMemory()Onikiri::EmulatorUtility::PageTableEntry::attrOnikiri::EmulatorUtility::PageTable::GetMap()Onikiri::EmulatorUtility::PageTableEntry::phyPageOnikiri::EmulatorUtility::PhysicalMemoryPage::refCountTHROW_RUNTIME_ERROR.

参照元 MemCopyToTarget()TargetMemset()WriteMemory().

00625 {
00626     PageTableEntry page;
00627     if( !m_pageTbl.GetMap( addr, &page ) ){
00628         THROW_RUNTIME_ERROR( "The specified address is not mapped." );
00629         return false;   // To avoid compiler's warning "Uninitialized 'page' is used".
00630     }
00631 
00632     // A page with reference count that is greater than 1 is a copy and
00633     // copy-on-write must be done to such a page.
00634     if( page.phyPage->refCount > 1 ){
00635         // Copy-on-write
00636         AssignAndCopyPhysicalMemory( addr, page.attr );
00637         return true;
00638     }
00639     return false;
00640 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::FreePhysicalMemory ( u64  addr,
u64  size 
)

VirtualMemory.cpp545 行で定義されています。

参照先 FreePhysicalMemory().

00546 {
00547     BlockArray blocks;
00548     SplitAtMapUnitBoundary(addr, size, back_inserter(blocks) );
00549 
00550     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e){
00551         FreePhysicalMemory(e->addr);
00552     }
00553 }

関数の呼び出しグラフ:

void VirtualMemory::FreePhysicalMemory ( u64  addr  ) 

VirtualMemory.cpp524 行で定義されています。

参照先 Onikiri::EmulatorUtility::PageTable::GetMap()GetPageSize()Onikiri::EmulatorUtility::PageTable::IsMapped()Onikiri::SystemIF::NotifyMemoryAllocation()Onikiri::EmulatorUtility::PageTableEntry::phyPageOnikiri::EmulatorUtility::PhysicalMemoryPage::ptrOnikiri::EmulatorUtility::PhysicalMemoryPage::refCountOnikiri::EmulatorUtility::PageTable::RemoveMap().

参照元 Onikiri::EmulatorUtility::MemorySystem::Brk()FreePhysicalMemory()Onikiri::EmulatorUtility::MemorySystem::MRemap()Onikiri::EmulatorUtility::MemorySystem::MUnmap()Onikiri::EmulatorUtility::MemorySystem::~MemorySystem().

00525 {
00526     if(!m_pageTbl.IsMapped(addr)){
00527         return;
00528     }
00529 
00530     PageTableEntry page;
00531     if( m_pageTbl.GetMap( addr, &page ) ){
00532         // QJE^1Cl
00533         if( page.phyPage->refCount == 1 && page.phyPage->ptr ){
00534             m_simSystem->NotifyMemoryAllocation( 
00535                 Addr( m_pid, TID_INVALID, addr), 
00536                 GetPageSize(), 
00537                 false
00538             );
00539             m_pool.free( page.phyPage->ptr );
00540         }
00541         m_pageTbl.RemoveMap( addr );
00542     }
00543 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

u64 VirtualMemory::GetPageSize (  )  const

VirtualMemory.cpp321 行で定義されています。

参照先 Onikiri::EmulatorUtility::PageTable::GetPageSize().

参照元 AssignAndCopyPhysicalMemory()AssignPhysicalMemory()FreePhysicalMemory()Onikiri::EmulatorUtility::MemorySystem::GetPageSize().

00322 {
00323     return m_pageTbl.GetPageSize();
00324 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

bool Onikiri::EmulatorUtility::VirtualMemory::IsBigEndian (  )  const [inline]

VirtualMemory.h201 行で定義されています。

00201                                      {
00202                 return m_bigEndian;
00203             }

void VirtualMemory::MemCopyToHost ( void *  dst,
u64  src,
u64  size 
)

VirtualMemory.cpp450 行で定義されています。

参照先 ReadMemory()Onikiri::EmulatorUtility::PageTable::TargetToHost().

参照元 Onikiri::EmulatorUtility::MemorySystem::MemCopyToHost().

00451 {
00452 #ifdef ENABLED_VIRTUAL_MEMORY_FAST_HELPER
00453     
00454     BlockArray blocks;
00455     SplitAtMapUnitBoundary(src, size, back_inserter(blocks) );
00456 
00457     u8* dst_u8 = static_cast<u8*>(dst);
00458     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e) {
00459         memcpy(dst_u8, m_pageTbl.TargetToHost(e->addr), (size_t)e->size);
00460         dst_u8 += e->size;
00461     }
00462 #else
00463     u8* host   = static_cast<u8*>(dst);
00464     u64 target = src;
00465     for( u64 i = 0; i < size; i++ ){
00466         host[i] = static_cast<u8>( ReadMemory( target + i, 1 ) );
00467     }
00468 #endif
00469 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::MemCopyToTarget ( u64  dst,
const void *  src,
u64  size 
)

VirtualMemory.cpp471 行で定義されています。

参照先 CopyPageOnWrite()Onikiri::EmulatorUtility::PageTable::TargetToHost()WriteMemory().

参照元 AssignAndCopyPhysicalMemory()Onikiri::EmulatorUtility::MemorySystem::MemCopyToTarget().

00472 {
00473 #ifdef ENABLED_VIRTUAL_MEMORY_FAST_HELPER
00474     
00475     BlockArray blocks;
00476     SplitAtMapUnitBoundary(dst, size, back_inserter(blocks) );
00477 
00478     const u8* src_u8 = static_cast<const u8*>(src);
00479     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e) {
00480         CopyPageOnWrite( e->addr );
00481         memcpy(m_pageTbl.TargetToHost(e->addr), src_u8, (size_t)e->size);
00482         src_u8 += e->size;
00483     }
00484 #else
00485     const u8* host = static_cast<const u8*>(src);
00486     u64 target = dst;
00487     for( u64 i = 0; i < size; i++ ){
00488         WriteMemory( target + i, 1, host[i] );
00489     }
00490 #endif
00491 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::ReadMemory ( MemAccess access  ) 

VirtualMemory.cpp326 行で定義されています。

参照先 Onikiri::Addr::addressOnikiri::MemAccess::addressOnikiri::EmulatorUtility::PageTableEntry::attrOnikiri::EndianSpecifiedToHost()Onikiri::EmulatorUtility::PageTable::GetMap()Onikiri::MemAccess::MAR_READ_INVALID_ADDRESSOnikiri::MemAccess::MAR_READ_NOT_READABLEOnikiri::MemAccess::MAR_READ_UNALIGNED_ADDRESSOnikiri::MemAccess::MAR_SUCCESSOnikiri::MemAccess::resultOnikiri::MemAccess::signOnikiri::MemAccess::sizeOnikiri::EmulatorUtility::PageTable::TargetToHost()THROW_RUNTIME_ERROROnikiri::MemAccess::value.

参照元 MemCopyToHost()Onikiri::EmulatorUtility::MemorySystem::ReadMemory().

00327 {
00328     u64 addr = access->address.address;
00329     PageTableEntry page;
00330 
00331     // @IoCANZXCID
00332     if( !m_pageTbl.GetMap( addr, &page ) ) {
00333         access->result = MemAccess::MAR_READ_INVALID_ADDRESS;
00334         access->value = 0;
00335         return;
00336     }
00337 
00338     // ANZX}bvPE
00339     if ((addr ^ (addr+access->size-1)) >> VIRTUAL_MEMORY_PAGE_SIZE_BITS != 0) {
00340         access->result = MemAccess::MAR_READ_UNALIGNED_ADDRESS;
00341         access->value = 0;
00342         return;
00343     }
00344     
00345     // Check attribute
00346     if( !(page.attr & VIRTUAL_MEMORY_ATTR_READ) ){
00347         access->result = MemAccess::MAR_READ_NOT_READABLE;
00348         return;
00349     }
00350 
00351     void *ptr = m_pageTbl.TargetToHost( addr );
00352     u64 result;
00353     switch (access->size) {
00354     case 1:
00355         if (access->sign)
00356             result = (u64)(s64)EndianSpecifiedToHost(*static_cast<s8*>(ptr), m_bigEndian);
00357         else
00358             result = (u64)EndianSpecifiedToHost(*static_cast<u8*>(ptr), m_bigEndian);
00359         break;
00360     case 2:
00361         if (access->sign)
00362             result = (u64)(s64)EndianSpecifiedToHost(*static_cast<s16*>(ptr), m_bigEndian);
00363         else
00364             result = (u64)EndianSpecifiedToHost(*static_cast<u16*>(ptr), m_bigEndian);
00365         break;
00366     case 4:
00367         if (access->sign)
00368             result = (u64)(s64)EndianSpecifiedToHost(*static_cast<s32*>(ptr), m_bigEndian);
00369         else
00370             result = (u64)EndianSpecifiedToHost(*static_cast<u32*>(ptr), m_bigEndian);
00371         break;
00372     case 8:
00373         result = EndianSpecifiedToHost(*static_cast<u64*>(ptr), m_bigEndian);
00374         break;
00375     default:
00376         THROW_RUNTIME_ERROR("Invalid Read Size");
00377         result = 0; // to suppress "result is uninitialized" warning
00378     }
00379 
00380     access->result = MemAccess::MAR_SUCCESS;
00381     access->value = result;
00382 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::SetPageAttribute ( u64  addr,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp611 行で定義されています。

参照先 Onikiri::EmulatorUtility::PageTableEntry::attrOnikiri::EmulatorUtility::PageTable::GetMap()Onikiri::EmulatorUtility::PageTable::SetMap()THROW_RUNTIME_ERROR.

00612 {
00613     PageTableEntry page;
00614     if( !m_pageTbl.GetMap( addr, &page ) ) {
00615         THROW_RUNTIME_ERROR( "The specified address is not mapped." );
00616     }
00617 
00618     page.attr = attr;
00619     m_pageTbl.SetMap( addr, page );
00620 }

関数の呼び出しグラフ:

void VirtualMemory::SetPhysicalMemoryMapping ( u64  dstAddr,
u64  srcAddr,
u64  size,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp571 行で定義されています。

参照先 SetPhysicalMemoryMapping().

00572 {
00573     BlockArray blocks;
00574     SplitAtMapUnitBoundary( dstAddr, size, back_inserter(blocks) );
00575     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e){
00576         SetPhysicalMemoryMapping( e->addr, srcAddr, attr );
00577     }
00578 }

関数の呼び出しグラフ:

void VirtualMemory::SetPhysicalMemoryMapping ( u64  dstAddr,
u64  srcAddr,
VIRTUAL_MEMORY_ATTR_TYPE  attr 
)

VirtualMemory.cpp556 行で定義されています。

参照先 Onikiri::EmulatorUtility::PageTable::CopyMap()Onikiri::EmulatorUtility::PageTable::IsMapped()THROW_RUNTIME_ERROR.

参照元 Onikiri::EmulatorUtility::MemorySystem::MMap()SetPhysicalMemoryMapping().

00557 {
00558     if( !m_pageTbl.IsMapped( srcAddr ) ){
00559         THROW_RUNTIME_ERROR( "The specified source address is not mapped." );
00560     }
00561 
00562     // y[WX[
00563     if( m_pageTbl.IsMapped( dstAddr ) ){
00564         THROW_RUNTIME_ERROR( "The specified target address is already mapped." );
00565     }
00566 
00567     m_pageTbl.CopyMap( dstAddr, srcAddr, attr );
00568 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::TargetMemset ( u64  targetAddr,
int  value,
u64  size 
)

VirtualMemory.cpp433 行で定義されています。

参照先 CopyPageOnWrite()Onikiri::EmulatorUtility::PageTable::TargetToHost()WriteMemory().

参照元 Onikiri::EmulatorUtility::MemorySystem::MemorySystem()Onikiri::EmulatorUtility::MemorySystem::TargetMemset().

00434 {
00435 #ifdef ENABLED_VIRTUAL_MEMORY_FAST_HELPER
00436     BlockArray blocks;
00437     SplitAtMapUnitBoundary(targetAddr, size, back_inserter(blocks) );
00438 
00439     for (BlockArray::iterator e = blocks.begin(); e != blocks.end(); ++e) {
00440         CopyPageOnWrite( e->addr );
00441         memset(m_pageTbl.TargetToHost(e->addr), value, (size_t)e->size);
00442     }
00443 #else
00444     for( u64 i = 0; i < size; i++ ){
00445         WriteMemory( targetAddr + i, 1, value );
00446     }
00447 #endif
00448 }

関数の呼び出しグラフ:

Here is the caller graph for this function:

void VirtualMemory::WriteMemory ( MemAccess access  ) 

VirtualMemory.cpp384 行で定義されています。

参照先 Onikiri::Addr::addressOnikiri::MemAccess::addressOnikiri::EmulatorUtility::PageTableEntry::attrCopyPageOnWrite()Onikiri::EndianHostToSpecified()Onikiri::EmulatorUtility::PageTable::GetMap()Onikiri::MemAccess::MAR_SUCCESSOnikiri::MemAccess::MAR_WRITE_INVALID_ADDRESSOnikiri::MemAccess::MAR_WRITE_NOT_WRITABLEOnikiri::MemAccess::MAR_WRITE_UNALIGNED_ADDRESSOnikiri::MemAccess::resultOnikiri::MemAccess::sizeOnikiri::EmulatorUtility::PageTable::TargetToHost()THROW_RUNTIME_ERROROnikiri::MemAccess::value.

参照元 MemCopyToTarget()TargetMemset()Onikiri::EmulatorUtility::MemorySystem::WriteMemory().

00385 {
00386     PageTableEntry page;
00387     u64 addr = access->address.address;
00388     if( !m_pageTbl.GetMap( addr, &page ) ) {
00389         access->result = MemAccess::MAR_WRITE_INVALID_ADDRESS;
00390         return;
00391     }
00392 
00393     // ANZX}bvPE
00394     if ((addr ^ (addr+access->size-1)) >> VIRTUAL_MEMORY_PAGE_SIZE_BITS != 0) {
00395         access->result = MemAccess::MAR_WRITE_UNALIGNED_ADDRESS;
00396         return;
00397     }
00398 
00399     if( !(page.attr & VIRTUAL_MEMORY_ATTR_WRITE) ){
00400         access->result = MemAccess::MAR_WRITE_NOT_WRITABLE;
00401         return;
00402     }
00403 
00404     if( CopyPageOnWrite( addr ) ){
00405         // copy-on-writ e[uQXVCxe[uGg
00406         // Get a page table entry again because a reference in the page table entry
00407         // is updated on copy-on-write.
00408         m_pageTbl.GetMap( addr, &page );
00409     }
00410 
00411     void *ptr = m_pageTbl.TargetToHost( addr );
00412     switch (access->size) {
00413     case 1:
00414         *static_cast<u8*>(ptr) = EndianHostToSpecified((u8)access->value, m_bigEndian);
00415         break;
00416     case 2:
00417         *static_cast<u16*>(ptr) = EndianHostToSpecified((u16)access->value, m_bigEndian);
00418         break;
00419     case 4:
00420         *static_cast<u32*>(ptr) = EndianHostToSpecified((u32)access->value, m_bigEndian);
00421         break;
00422     case 8:
00423         *static_cast<u64*>(ptr) = EndianHostToSpecified((u64)access->value, m_bigEndian);
00424         break;
00425     default:
00426         THROW_RUNTIME_ERROR("Invalid Write Size");
00427     }
00428 
00429     access->result = MemAccess::MAR_SUCCESS;
00430 }

関数の呼び出しグラフ:

Here is the caller graph for this function:


このクラスの説明は次のファイルから生成されました:
Onikiri2に対してTue Jun 18 15:30:55 2013に生成されました。  doxygen 1.4.7