📄 mmu.cpp
字号:
#include "MMU.h"
#include "Exception.h"
#include "Core/System.h"
#include "Register.h"
#include "Reg_Flag.h"
#include "Reg_Utils.h"
#include "Core/System.h"
#include "Core/Board.h"
#include "Utils/Logger.h"
#define ACTUAL_SIZE 66
namespace PPC
{
TLB::Entry TLB::entrys_[ACTUAL_SIZE] =
{
{0xf0000000|TLB_VALID|SZ_256M, 0, 0xf0000000, AC_R|AC_W|AC_X|SA_G|SA_I},
{CFG_PERIPHERAL_BASE|TLB_VALID|SZ_256M,0, 0x40000000, AC_R|AC_W|SA_G|SA_I},
{CFG_ISRAM_BASE|TLB_VALID|SZ_4K, 0,0x80000000, AC_R|AC_W|AC_X },
{(CFG_ISRAM_BASE + 0x1000)| TLB_VALID|SZ_4K, 0,0x80001000, AC_R|AC_W|AC_X},
{CFG_SDRAM_BASE|TLB_VALID| SZ_256M, 0,0x00000000, AC_R|AC_W|AC_X|SA_G|SA_I},
};
TLB::TLB(size_t size)
{
size_ = size;
reset();
}
void TLB::reset()
{
// Fix me!
entrys_[64].ws0 = 0xfdffd000 | TLB_VALID | TS_SET | SZ_4K ;
entrys_[64].ws0_TID = 0;
entrys_[64].ws1 = 0x40000000;
entrys_[64].ws2 = AC_R|AC_W|SA_G|SA_I;
entrys_[65].ws0 = 0xfdfff000 | TLB_VALID | TS_SET | SZ_4K;
entrys_[65].ws0_TID = 0;
entrys_[65].ws1 = 0x48001000;
entrys_[65].ws2 = AC_R|AC_W|SA_G|SA_I;
}
TLB::Entry * TLB::search(Core::u32 as, Core::u32 pid, Core::u32 ea, size_t * index)
{
for( size_t i = 0; i < ACTUAL_SIZE; ++i)
{
Core::u32 SIZE =get_SIZE(entrys_[i]);
Core::u32 V = get_V(entrys_[i]) ;
Core::u32 TS = get_TS(entrys_[i]);
Core::u32 EPN = get_EPN(entrys_[i]);
Core::u32 mask = 0xFFFFFFFF << ( 10 + get_SIZE(entrys_[i]) * 2);
bool b;
b = ( TS == as );
b = ( entrys_[i].ws0_TID == pid);
b = (( EPN & mask) == (ea & mask));
if( get_V(entrys_[i])
&& get_TS(entrys_[i]) == as
&& ( entrys_[i].ws0_TID == 0 || entrys_[i].ws0_TID != 0 && entrys_[i].ws0_TID == pid)
&& (get_EPN(entrys_[i]) & mask) == (ea & mask) )
{
*index = i;
return &entrys_[i];
}
}
return NULL;
}
TLB::Entry & TLB::get_entry(size_t index)
{
assert(index < size_);
return entrys_[index];
}
MMU::MMU()
{
utlb_ = new TLB(64);
}
MMU::~MMU()
{
delete utlb_;
}
TLB & MMU::get_utlb()
{
return *utlb_;
}
Core::Memory_Result MMU::access(Core::Memory_Access_Type type,
Core::u32 start, size_t size, Core::Bytecode_Type & buffer)
{
Core::u32 as;
if( type == DATA_READ || type == DATA_WRITE )
as = REG_BIT_IS_SET(MSR, Reg_Flag::MSR_DS) ? 1 : 0;
else if(type = INSTR_READ)
as = REG_BIT_IS_SET(MSR, Reg_Flag::MSR_IS) ? 1 : 0;
else
assert(0);
PPC_u32 pid = REG_TO_INT(REG(PID)) & 0x000000ff;
size_t index;
TLB::Entry * entry = utlb_->search(as, pid, start, &index);
if( entry )
{
switch( type )
{
case INSTR_READ:
if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UX(*entry) == 0
|| ! REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SX(*entry) == 0)
{
//an Execute Access Control exception type Instruction Storage interrupt is taken.
Exception_Mgr::instance()->handle(Exception::EXC_ISI);
return ACCESS_FAULT;
}
break;
case DATA_READ:
if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UW(*entry) == 0
|| !REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SW(*entry) == 0)
{
//an Write Access Control exception type Data Storage interrupt is taken.
Exception_Mgr::instance()->handle(Exception::EXC_DSI);
return ACCESS_FAULT;
}
break;
case DATA_WRITE:
if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UR(*entry) == 0
|| !REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SR(*entry) == 0)
{
//an Read Access Control exception type Data Storage interrupt is taken.
Exception_Mgr::instance()->handle(Exception::EXC_DSI);
return ACCESS_FAULT;
}
break;
}
}
else
{
if( type == DATA_READ || type == DATA_WRITE )
Exception_Mgr::instance()->handle(Exception::EXC_DATA_TLB);// data tlb exc
else if(type = INSTR_READ)
Exception_Mgr::instance()->handle(Exception::EXC_INSTR_TLB);// instr tlb exc
return ACCESS_FAULT;
}
// assume 32bit real address , the ERPN domain of tlb entry is 0000
Core::u32 mask = 0xFFFFFFFF << ( 10 + TLB::get_SIZE(*entry) * 2);
Core::u32 ra =( TLB::get_RPN(*entry) & mask ) | ( start & ~mask );
PPC_TRACE_2("physical addr: ", (Core::u32 *)ra, "\n");
Core::Memory<Core::u32> * mem = (Core::Memory<Core::u32> *)Core::Wukong_Get_System().get_memory(ra);
assert(mem);
if (mem->is_mapped())
{
Core::Board<Core::u32> * board = (Core::Board<Core::u32> *)(Core::Wukong_Get_System().get_board());
assert(board);
Core::Memory_Result io_result = board->io_dispatch(type, ra, size, buffer);
if(io_result == IO_RW)
{
Core::u32 value = 0;
Core::Wukong_Get_System().convert_to_bytecode(value, buffer);
}
}
if(!mem->test_fit(ra) || !mem->test_fit(ra + (Core::u32)size - 1))
return ACCESS_FAULT;
if(type == Core::Memory<Core::u32>::MEMORY_WRITE && mem->is_readonly())
return ACCESS_FAULT;
if( type == DATA_READ || type == INSTR_READ)
mem->unchecked_access(Core::Memory_32Bit::MEMORY_READ, ra, size, buffer);
else
mem->unchecked_access(Core::Memory_32Bit::MEMORY_WRITE, ra, size, buffer);
return ACCESS_SUCCESSFUL;
}
} // namespace PPC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -