aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.cc
diff options
context:
space:
mode:
authorSuHsien Ho <su-hsien.ho@mediatek.com>2023-10-04 15:00:49 +0800
committerSuHsien Ho <su-hsien.ho@mediatek.com>2024-04-18 13:05:28 +0800
commit9ba5bd3171e97560bc28fe555ff7b8404272a3bb (patch)
treec0ac867c7df2ce90c83071e93c0ea5f0c6745d70 /riscv/mmu.cc
parent3192ee4d31f481e84281a24d55bb6130e3743668 (diff)
downloadriscv-isa-sim-9ba5bd3171e97560bc28fe555ff7b8404272a3bb.zip
riscv-isa-sim-9ba5bd3171e97560bc28fe555ff7b8404272a3bb.tar.gz
riscv-isa-sim-9ba5bd3171e97560bc28fe555ff7b8404272a3bb.tar.bz2
Add Zicfiss extension from CFI extension, v0.4.0
1. Add EXT_ZICFISS for enable Zicfiss with zicfiss extension name. 2. Add new software exception with tval 3 for shadow stack. 3. Implement sspush_x1/sspush_x5/sspopchk_x1/sspopchk_x5/ssrdp/ssamoswap_w/ssamoswap_d. 4. Implement c_sspush_x1/c_sspopchk_x5 in c_lui.h which has same encoding. 5. Add new special access type ss_access in xlate_flags_t for checking special read/write permission in SS(Shadow Stack) page. 6. Add new ss_load/ss_store/ssamoswap to enable ss_access flag. 7. Check special pte(xwr=010) of SS page.
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r--riscv/mmu.cc29
1 files changed, 26 insertions, 3 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 1a0c830..8660b71 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -63,7 +63,7 @@ reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
reg_t mode = (reg_t) access_info.effective_priv;
reg_t paddr = walk(access_info) | (addr & (PGSIZE-1));
- if (!pmp_ok(paddr, len, type, mode))
+ if (!pmp_ok(paddr, len, access_info.flags.ss_access ? STORE : type, mode))
throw_access_exception(virt, addr, type);
return paddr;
}
@@ -491,6 +491,15 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
reg_t page_mask = (reg_t(1) << PGSHIFT) - 1;
reg_t satp = proc->get_state()->satp->readvirt(virt);
vm_info vm = decode_vm_info(proc->get_const_xlen(), false, mode, satp);
+
+ bool ss_access = access_info.flags.ss_access;
+
+ if (ss_access) {
+ if (vm.levels == 0)
+ trap_store_access_fault(virt, addr, 0, 0);
+ type = STORE;
+ }
+
if (vm.levels == 0)
return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx, false) & ~page_mask; // zero-extend from xlen
@@ -516,6 +525,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
reg_t ppn = (pte & ~reg_t(PTE_ATTR)) >> PTE_PPN_SHIFT;
bool pbmte = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_PBMTE) : (proc->get_state()->menvcfg->read() & MENVCFG_PBMTE);
bool hade = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_ADUE) : (proc->get_state()->menvcfg->read() & MENVCFG_ADUE);
+ bool sse = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_SSE) : (proc->get_state()->menvcfg->read() & MENVCFG_SSE);
if (pte & PTE_RSVD) {
break;
@@ -531,11 +541,24 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
base = ppn << PGSHIFT;
} else if ((pte & PTE_U) ? s_mode && (type == FETCH || !sum) : !s_mode) {
break;
- } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
+ } else if (!(pte & PTE_V) ||
+ (!(pte & PTE_R) && (pte & PTE_W) && ((!sse && !(pte & PTE_X)) || (pte & PTE_X)))) {
+ // invalid
+ // not shadow stack access xwr=110 or xwr=010 page cause page fault
+ // shadow stack access with PTE_X moved to following check
break;
+ } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && (type == STORE && !ss_access)) {
+ // not shadow stack store and xwr = 010 cause access-fault
+ throw trap_store_access_fault(virt, addr, 0, 0);
+ } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && type == FETCH) {
+ // fetch from shadow stack pages cause instruction access-fault
+ throw trap_instruction_access_fault(virt, addr, 0, 0);
+ } else if ((((pte & PTE_R) && (pte & PTE_W)) || (pte & PTE_X)) && ss_access) {
+ // shadow stack access cause store access fault if xwr!=010 and xwr!=001
+ throw trap_store_access_fault(virt, addr, 0, 0);
} else if (type == FETCH || hlvx ? !(pte & PTE_X) :
type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
- !((pte & PTE_R) && (pte & PTE_W))) {
+ !(pte & PTE_W)) {
break;
} else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break;