Allow writes to rw pages in pte_spill_v
authorgkoehler <gkoehler@openbsd.org>
Mon, 7 Feb 2022 23:20:09 +0000 (23:20 +0000)
committergkoehler <gkoehler@openbsd.org>
Mon, 7 Feb 2022 23:20:09 +0000 (23:20 +0000)
In the powerpc pmap, hash collisions can spill page table entries.
Page faults can use pte_spill_v to reinsert a spilled pte.  If the
fault is a write (DSISR_STORE), then pte_spill_v tries to check for a
read-only page.  The existing check (pte_lo & PTE_RO_64) also matched
rw pages, because PTE_RO_64 is 3 and PTE_RW_64 is 2.  This caused
pte_spill_v to deny writes to rw pages.  Then uvm_fault might allow
the write; but uvm_fault can't handle some pages in the kernel.  Such
faults caused, "panic: uvm_fault: fault on non-pageable map", or
"panic: trap type 300".

Change it to ((pte_lo & PTE_PP_64) == PTE_RO_64).  This seems to fix
one reason why bsd.mp on a macppc dual G5 might panic.

ok kettenis@ miod@

sys/arch/powerpc/powerpc/pmap.c

index 3a01cd5..fae4c8c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.175 2021/03/15 15:49:22 deraadt Exp $ */
+/*     $OpenBSD: pmap.c,v 1.176 2022/02/07 23:20:09 gkoehler Exp $ */
 
 /*
  * Copyright (c) 2015 Martin Pieuchot
@@ -2277,10 +2277,12 @@ pte_spill_v(pmap_t pm, u_int32_t va, u_int32_t dsisr, int exec_fault)
        /* Attempted to write a read-only page. */
        if (dsisr & DSISR_STORE) {
                if (ppc_proc_is_64b) {
-                       if (pted->p.pted_pte64.pte_lo & PTE_RO_64)
+                       if ((pted->p.pted_pte64.pte_lo & PTE_PP_64) ==
+                           PTE_RO_64)
                                goto out;
                } else {
-                       if (pted->p.pted_pte32.pte_lo & PTE_RO_32)
+                       if ((pted->p.pted_pte32.pte_lo & PTE_PP_32) ==
+                           PTE_RO_32)
                                goto out;
                }
        }