Browse Source

Check for NAPOT PTE validity before raising SS-related faults

Resolves #1925
pull/1926/head
Andrew Waterman 1 year ago
parent
commit
283b6af1fa
  1. 14
      riscv/mmu.cc

14
riscv/mmu.cc

@ -431,6 +431,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
reg_t ppn = (pte & ~reg_t(PTE_ATTR)) >> PTE_PPN_SHIFT;
bool pbmte = proc->get_state()->menvcfg->read() & MENVCFG_PBMTE;
bool hade = proc->get_state()->menvcfg->read() & MENVCFG_ADUE;
int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (pte & PTE_RSVD) {
break;
@ -446,6 +447,8 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
base = ppn << PGSHIFT;
} else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break;
} else if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4)) {
break;
} else if (!(pte & PTE_U)) {
break;
} else if (type == FETCH || hlvx ? !(pte & PTE_X) :
@ -457,10 +460,6 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
} else {
reg_t ad = PTE_A | ((type == STORE) * PTE_D);
int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4))
break;
if ((pte & ad) != ad) {
if (hade) {
// set accessed and possibly dirty bits
@ -536,6 +535,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
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);
bool ss_page = !(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X);
int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (pte & PTE_RSVD) {
break;
@ -557,6 +557,8 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
// 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_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4)) {
break;
} else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break;
} else if (ss_page && ((type == STORE && !ss_access) || access_info.flags.clean_inval)) {
@ -575,10 +577,6 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
} else {
reg_t ad = PTE_A | ((type == STORE) * PTE_D);
int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4))
break;
if ((pte & ad) != ad) {
if (hade) {
// Check for write permission to the first-stage PT in second-stage

Loading…
Cancel
Save