diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -3471,6 +3471,14 @@ vm_page_dirty(m); } else { pmap_store(l3, new_l3); + if (pmap == kernel_pmap) { + /* + * Issue a TLB shootdown for 'va' to guard + * against spurious kernel page faults on + * implementations that cache invalid PTEs. + */ + pmap_invalidate_page(pmap, va); + } } #if VM_NRESERVLEVEL > 0 @@ -3694,6 +3702,8 @@ * Map the superpage. */ pmap_store(l2, new_l2); + if (pmap == kernel_pmap && oldl2 == 0) + pmap_invalidate_range(pmap, va, va + L2_SIZE); atomic_add_long(&pmap_l2_mappings, 1); CTR2(KTR_PMAP, "pmap_enter_l2: success for va %#lx in pmap %p", @@ -3782,7 +3792,7 @@ { struct spglist free; pd_entry_t *l2; - pt_entry_t *l3, newl3; + pt_entry_t *l3, newl3, oldl3; KASSERT(!VA_IS_CLEANMAP(va) || (m->oflags & VPO_UNMANAGED) != 0, @@ -3840,7 +3850,9 @@ } if (l3 == NULL) panic("pmap_enter_quick_locked: No l3"); - if (pmap_load(l3) != 0) { + + oldl3 = pmap_load(l3); + if (oldl3 != 0) { if (mpte != NULL) mpte->ref_count--; return (NULL); @@ -3903,6 +3915,9 @@ } #endif + if (pmap == kernel_pmap && oldl3 == 0) + pmap_invalidate_page(pmap, va); + return (mpte); }