|
|
|
@ -36,9 +36,9 @@ void mmu_t::flush_icache() |
|
|
|
|
|
|
|
void mmu_t::flush_tlb() |
|
|
|
{ |
|
|
|
memset(tlb_insn_tag, -1, sizeof(tlb_insn_tag)); |
|
|
|
memset(tlb_load_tag, -1, sizeof(tlb_load_tag)); |
|
|
|
memset(tlb_store_tag, -1, sizeof(tlb_store_tag)); |
|
|
|
memset(tlb_insn, -1, sizeof(tlb_insn)); |
|
|
|
memset(tlb_load, -1, sizeof(tlb_load)); |
|
|
|
memset(tlb_store, -1, sizeof(tlb_store)); |
|
|
|
|
|
|
|
flush_icache(); |
|
|
|
} |
|
|
|
@ -76,7 +76,7 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) |
|
|
|
|
|
|
|
tlb_entry_t result; |
|
|
|
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])); |
|
|
|
if (auto host_addr = sim->addr_to_mem(paddr)) { |
|
|
|
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-1))}; |
|
|
|
} |
|
|
|
} 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-1))))); |
|
|
|
@ -195,8 +195,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 transformed_addr = access_info.transformed_vaddr; |
|
|
|
reg_t vpn = transformed_addr >> PGSHIFT; |
|
|
|
if (!access_info.flags.is_special_access() && vpn == (tlb_load_tag[vpn % TLB_ENTRIES] & ~TLB_CHECK_TRIGGERS)) { |
|
|
|
auto host_addr = (const void*)(tlb_data[vpn % TLB_ENTRIES].host_addr + (transformed_addr & (PGSIZE-1))); |
|
|
|
if (!access_info.flags.is_special_access() && vpn == (tlb_load[vpn % TLB_ENTRIES].tag & ~TLB_CHECK_TRIGGERS)) { |
|
|
|
auto host_addr = (const void*)(tlb_load[vpn % TLB_ENTRIES].data.host_addr + (transformed_addr & (PGSIZE-1))); |
|
|
|
memcpy(bytes, host_addr, len); |
|
|
|
return; |
|
|
|
} |
|
|
|
@ -258,9 +258,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 transformed_addr = access_info.transformed_vaddr; |
|
|
|
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) { |
|
|
|
auto host_addr = (void*)(tlb_data[vpn % TLB_ENTRIES].host_addr + (transformed_addr & (PGSIZE-1))); |
|
|
|
auto host_addr = (void*)(tlb_store[vpn % TLB_ENTRIES].data.host_addr + (transformed_addr & (PGSIZE-1))); |
|
|
|
memcpy(host_addr, bytes, len); |
|
|
|
} |
|
|
|
return; |
|
|
|
@ -320,28 +320,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-1)), paddr - (vaddr & (PGSIZE-1))}; |
|
|
|
|
|
|
|
if (in_mprv()) |
|
|
|
if (in_mprv() || !pmp_homogeneous(paddr & ~reg_t(PGSIZE - 1), PGSIZE)) |
|
|
|
return entry; |
|
|
|
|
|
|
|
if ((tlb_load_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag) |
|
|
|
tlb_load_tag[idx] = -1; |
|
|
|
if ((tlb_store_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag) |
|
|
|
tlb_store_tag[idx] = -1; |
|
|
|
if ((tlb_insn_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag) |
|
|
|
tlb_insn_tag[idx] = -1; |
|
|
|
|
|
|
|
if ((check_triggers_fetch && type == FETCH) || |
|
|
|
(check_triggers_load && type == LOAD) || |
|
|
|
(check_triggers_store && type == STORE)) |
|
|
|
expected_tag |= TLB_CHECK_TRIGGERS; |
|
|
|
|
|
|
|
if (pmp_homogeneous(paddr & ~reg_t(PGSIZE - 1), PGSIZE)) { |
|
|
|
if (type == FETCH) tlb_insn_tag[idx] = expected_tag; |
|
|
|
else if (type == STORE) tlb_store_tag[idx] = expected_tag; |
|
|
|
else tlb_load_tag[idx] = expected_tag; |
|
|
|
switch (type) { |
|
|
|
case FETCH: |
|
|
|
tlb_insn[idx].data = entry; |
|
|
|
tlb_insn[idx].tag = expected_tag | (check_triggers_fetch ? TLB_CHECK_TRIGGERS : 0); |
|
|
|
break; |
|
|
|
case LOAD: |
|
|
|
tlb_load[idx].data = entry; |
|
|
|
tlb_load[idx].tag = expected_tag | (check_triggers_load ? TLB_CHECK_TRIGGERS : 0); |
|
|
|
break; |
|
|
|
case STORE: |
|
|
|
tlb_store[idx].data = entry; |
|
|
|
tlb_store[idx].tag = expected_tag | (check_triggers_store ? TLB_CHECK_TRIGGERS : 0); |
|
|
|
break; |
|
|
|
default: |
|
|
|
abort(); |
|
|
|
} |
|
|
|
|
|
|
|
tlb_data[idx] = entry; |
|
|
|
return entry; |
|
|
|
} |
|
|
|
|
|
|
|
|