aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.cc
diff options
context:
space:
mode:
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;