#include <VirtualMemory.h>
Onikiri::EmulatorUtility::VirtualMemoryのコラボレーション図
VirtualMemory.h の 146 行で定義されています。
VirtualMemory::VirtualMemory | ( | int | pid, | |
bool | bigEndian, | |||
SystemIF * | simSystem | |||
) |
VirtualMemory.cpp の 307 行で定義されています。
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 | ( | ) |
void VirtualMemory::AssignAndCopyPhysicalMemory | ( | u64 | addr, | |
u64 | size, | |||
VIRTUAL_MEMORY_ATTR_TYPE | attr | |||
) |
VirtualMemory.cpp の 601 行で定義されています。
参照先 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.cpp の 582 行で定義されています。
参照先 AssignPhysicalMemory()・Onikiri::EmulatorUtility::PageTable::GetMap()・Onikiri::EmulatorUtility::PageTable::GetOffsetMask()・GetPageSize()・MemCopyToTarget()・Onikiri::EmulatorUtility::PageTableEntry::phyPage・Onikiri::EmulatorUtility::PhysicalMemoryPage::ptr・Onikiri::EmulatorUtility::PhysicalMemoryPage::refCount・Onikiri::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.cpp の 514 行で定義されています。
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.cpp の 493 行で定義されています。
参照先 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.cpp の 624 行で定義されています。
参照先 AssignAndCopyPhysicalMemory()・Onikiri::EmulatorUtility::PageTableEntry::attr・Onikiri::EmulatorUtility::PageTable::GetMap()・Onikiri::EmulatorUtility::PageTableEntry::phyPage・Onikiri::EmulatorUtility::PhysicalMemoryPage::refCount・THROW_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:
VirtualMemory.cpp の 545 行で定義されています。
参照先 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.cpp の 524 行で定義されています。
参照先 Onikiri::EmulatorUtility::PageTable::GetMap()・GetPageSize()・Onikiri::EmulatorUtility::PageTable::IsMapped()・Onikiri::SystemIF::NotifyMemoryAllocation()・Onikiri::EmulatorUtility::PageTableEntry::phyPage・Onikiri::EmulatorUtility::PhysicalMemoryPage::ptr・Onikiri::EmulatorUtility::PhysicalMemoryPage::refCount・Onikiri::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.cpp の 321 行で定義されています。
参照先 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.cpp の 450 行で定義されています。
参照先 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:
VirtualMemory.cpp の 471 行で定義されています。
参照先 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.cpp の 326 行で定義されています。
参照先 Onikiri::Addr::address・Onikiri::MemAccess::address・Onikiri::EmulatorUtility::PageTableEntry::attr・Onikiri::EndianSpecifiedToHost()・Onikiri::EmulatorUtility::PageTable::GetMap()・Onikiri::MemAccess::MAR_READ_INVALID_ADDRESS・Onikiri::MemAccess::MAR_READ_NOT_READABLE・Onikiri::MemAccess::MAR_READ_UNALIGNED_ADDRESS・Onikiri::MemAccess::MAR_SUCCESS・Onikiri::MemAccess::result・Onikiri::MemAccess::sign・Onikiri::MemAccess::size・Onikiri::EmulatorUtility::PageTable::TargetToHost()・THROW_RUNTIME_ERROR・Onikiri::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.cpp の 611 行で定義されています。
参照先 Onikiri::EmulatorUtility::PageTableEntry::attr・Onikiri::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.cpp の 571 行で定義されています。
参照先 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.cpp の 556 行で定義されています。
参照先 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:
VirtualMemory.cpp の 433 行で定義されています。
参照先 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.cpp の 384 行で定義されています。
参照先 Onikiri::Addr::address・Onikiri::MemAccess::address・Onikiri::EmulatorUtility::PageTableEntry::attr・CopyPageOnWrite()・Onikiri::EndianHostToSpecified()・Onikiri::EmulatorUtility::PageTable::GetMap()・Onikiri::MemAccess::MAR_SUCCESS・Onikiri::MemAccess::MAR_WRITE_INVALID_ADDRESS・Onikiri::MemAccess::MAR_WRITE_NOT_WRITABLE・Onikiri::MemAccess::MAR_WRITE_UNALIGNED_ADDRESS・Onikiri::MemAccess::result・Onikiri::MemAccess::size・Onikiri::EmulatorUtility::PageTable::TargetToHost()・THROW_RUNTIME_ERROR・Onikiri::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: