@ -36,9 +36,9 @@ void mmu_t::flush_icache()
void mmu_t : : flush_tlb ( )
void mmu_t : : flush_tlb ( )
{
{
memset ( tlb_insn_tag , - 1 , sizeof ( tlb_insn_tag ) ) ;
memset ( tlb_insn , - 1 , sizeof ( tlb_insn ) ) ;
memset ( tlb_load_tag , - 1 , sizeof ( tlb_load_tag ) ) ;
memset ( tlb_load , - 1 , sizeof ( tlb_load ) ) ;
memset ( tlb_store_tag , - 1 , sizeof ( tlb_store_tag ) ) ;
memset ( tlb_store , - 1 , sizeof ( tlb_store ) ) ;
flush_icache ( ) ;
flush_icache ( ) ;
}
}
@ -76,7 +76,7 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
tlb_entry_t result ;
tlb_entry_t result ;
reg_t vpn = vaddr > > PGSHIFT ;
reg_t vpn = vaddr > > PGSHIFT ;
if ( unlikely ( tlb_insn_tag [ vpn % TLB_ENTRIES ] ! = ( vpn | TLB_CHECK_TRIGGERS ) ) ) {
if ( unlikely ( tlb_insn [ vpn % TLB_ENTRIES ] . tag ! = ( vpn | TLB_CHECK_TRIGGERS ) ) ) {
reg_t paddr = translate ( access_info , sizeof ( fetch_temp [ 0 ] ) ) ;
reg_t paddr = translate ( access_info , sizeof ( fetch_temp [ 0 ] ) ) ;
if ( auto host_addr = sim - > addr_to_mem ( paddr ) ) {
if ( auto host_addr = sim - > addr_to_mem ( paddr ) ) {
result = refill_tlb ( vaddr , paddr , host_addr , FETCH ) ;
result = refill_tlb ( vaddr , paddr , host_addr , FETCH ) ;
@ -86,7 +86,7 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
result = { uintptr_t ( & fetch_temp ) , paddr - ( vaddr % PGSIZE ) } ;
result = { uintptr_t ( & fetch_temp ) , paddr - ( vaddr % PGSIZE ) } ;
}
}
} else {
} else {
result = tlb_data [ vpn % TLB_ENTRIES ] ;
result = tlb_insn [ vpn % TLB_ENTRIES ] . data ;
}
}
check_triggers ( triggers : : OPERATION_EXECUTE , vaddr , access_info . effective_virt , from_le ( * ( const uint16_t * ) ( result . host_addr + ( vaddr % PGSIZE ) ) ) ) ;
check_triggers ( triggers : : OPERATION_EXECUTE , vaddr , access_info . effective_virt , from_le ( * ( const uint16_t * ) ( result . host_addr + ( vaddr % PGSIZE ) ) ) ) ;
@ -196,8 +196,8 @@ void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_
reg_t addr = access_info . vaddr ;
reg_t addr = access_info . vaddr ;
reg_t transformed_addr = access_info . transformed_vaddr ;
reg_t transformed_addr = access_info . transformed_vaddr ;
reg_t vpn = transformed_addr > > PGSHIFT ;
reg_t vpn = transformed_addr > > PGSHIFT ;
if ( ! access_info . flags . is_special_access ( ) & & vpn = = ( tlb_load_tag [ vpn % TLB_ENTRIES ] & ~ TLB_CHECK_TRIGGERS ) ) {
if ( ! access_info . flags . is_special_access ( ) & & vpn = = ( tlb_load [ vpn % TLB_ENTRIES ] . tag & ~ TLB_CHECK_TRIGGERS ) ) {
auto host_addr = ( const void * ) ( tlb_data [ vpn % TLB_ENTRIES ] . host_addr + ( transformed_addr % PGSIZE ) ) ;
auto host_addr = ( const void * ) ( tlb_load [ vpn % TLB_ENTRIES ] . data . host_addr + ( transformed_addr % PGSIZE ) ) ;
memcpy ( bytes , host_addr , len ) ;
memcpy ( bytes , host_addr , len ) ;
return ;
return ;
}
}
@ -263,9 +263,9 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces
reg_t addr = access_info . vaddr ;
reg_t addr = access_info . vaddr ;
reg_t transformed_addr = access_info . transformed_vaddr ;
reg_t transformed_addr = access_info . transformed_vaddr ;
reg_t vpn = transformed_addr > > PGSHIFT ;
reg_t vpn = transformed_addr > > PGSHIFT ;
if ( ! access_info . flags . is_special_access ( ) & & vpn = = ( tlb_store_tag [ vpn % TLB_ENTRIES ] & ~ TLB_CHECK_TRIGGERS ) ) {
if ( ! access_info . flags . is_special_access ( ) & & vpn = = ( tlb_store [ vpn % TLB_ENTRIES ] . tag & ~ TLB_CHECK_TRIGGERS ) ) {
if ( actually_store ) {
if ( actually_store ) {
auto host_addr = ( void * ) ( tlb_data [ vpn % TLB_ENTRIES ] . host_addr + ( transformed_addr % PGSIZE ) ) ;
auto host_addr = ( void * ) ( tlb_store [ vpn % TLB_ENTRIES ] . data . host_addr + ( transformed_addr % PGSIZE ) ) ;
memcpy ( host_addr , bytes , len ) ;
memcpy ( host_addr , bytes , len ) ;
}
}
return ;
return ;
@ -327,28 +327,26 @@ tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_
tlb_entry_t entry = { uintptr_t ( host_addr ) - ( vaddr % PGSIZE ) , paddr - ( vaddr % PGSIZE ) } ;
tlb_entry_t entry = { uintptr_t ( host_addr ) - ( vaddr % PGSIZE ) , paddr - ( vaddr % PGSIZE ) } ;
if ( in_mprv ( ) )
if ( in_mprv ( ) | | ! pmp_homogeneous ( paddr & ~ reg_t ( PGSIZE - 1 ) , PGSIZE ) )
return entry ;
return entry ;
if ( ( tlb_load_tag [ idx ] & ~ TLB_CHECK_TRIGGERS ) ! = expected_tag )
switch ( type ) {
tlb_load_tag [ idx ] = - 1 ;
case FETCH :
if ( ( tlb_store_tag [ idx ] & ~ TLB_CHECK_TRIGGERS ) ! = expected_tag )
tlb_insn [ idx ] . data = entry ;
tlb_store_tag [ idx ] = - 1 ;
tlb_insn [ idx ] . tag = expected_tag | ( check_triggers_fetch ? TLB_CHECK_TRIGGERS : 0 ) ;
if ( ( tlb_insn_tag [ idx ] & ~ TLB_CHECK_TRIGGERS ) ! = expected_tag )
break ;
tlb_insn_tag [ idx ] = - 1 ;
case LOAD :
tlb_load [ idx ] . data = entry ;
if ( ( check_triggers_fetch & & type = = FETCH ) | |
tlb_load [ idx ] . tag = expected_tag | ( check_triggers_load ? TLB_CHECK_TRIGGERS : 0 ) ;
( check_triggers_load & & type = = LOAD ) | |
break ;
( check_triggers_store & & type = = STORE ) )
case STORE :
expected_tag | = TLB_CHECK_TRIGGERS ;
tlb_store [ idx ] . data = entry ;
tlb_store [ idx ] . tag = expected_tag | ( check_triggers_store ? TLB_CHECK_TRIGGERS : 0 ) ;
if ( pmp_homogeneous ( paddr & ~ reg_t ( PGSIZE - 1 ) , PGSIZE ) ) {
break ;
if ( type = = FETCH ) tlb_insn_tag [ idx ] = expected_tag ;
default :
else if ( type = = STORE ) tlb_store_tag [ idx ] = expected_tag ;
abort ( ) ;
else tlb_load_tag [ idx ] = expected_tag ;
}
}
tlb_data [ idx ] = entry ;
return entry ;
return entry ;
}
}