From 283b6af1faad1aa5a26ec8758f0083fab9d6e8d7 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Feb 2025 13:34:29 -0800 Subject: [PATCH] Check for NAPOT PTE validity before raising SS-related faults Resolves #1925 --- riscv/mmu.cc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 35e9daa2..c8d6f255 100644 --- a/riscv/mmu.cc +++ b/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