-/* $OpenBSD: pmap.c,v 1.180 2023/01/07 10:09:34 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.181 2023/01/24 16:51:05 kettenis Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
pmap_unlock(pmap);
}
+void
+pmap_page_write_protect(struct vm_page *pg)
+{
+ struct pv_entry *pve;
+ int attrs;
+
+ DPRINTF(PDB_FOLLOW|PDB_BITS, ("pmap_page_write_protect(%p)\n", pg));
+
+ attrs = 0;
+ mtx_enter(&pg->mdpage.pvh_mtx);
+ for (pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) {
+ struct pmap *pmap = pve->pv_pmap;
+ vaddr_t va = pve->pv_va;
+ volatile pt_entry_t *pde;
+ pt_entry_t opte, pte;
+
+ if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
+ opte = pte = pmap_pte_get(pde, va);
+ if (pte & TLB_GATEWAY)
+ continue;
+ pte &= ~TLB_WRITE;
+ attrs |= pmap_pvh_attrs(pte);
+
+ if (opte != pte) {
+ pmap_pte_flush(pmap, va, opte);
+ pmap_pte_set(pde, va, pte);
+ }
+ }
+ }
+ mtx_leave(&pg->mdpage.pvh_mtx);
+ if (attrs != (PG_PMAP_REF | PG_PMAP_MOD))
+ atomic_clearbits_int(&pg->pg_flags,
+ attrs ^(PG_PMAP_REF | PG_PMAP_MOD));
+ if (attrs != 0)
+ atomic_setbits_int(&pg->pg_flags, attrs);
+}
+
void
pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
-/* $OpenBSD: pmap.h,v 1.53 2023/01/01 19:49:17 miod Exp $ */
+/* $OpenBSD: pmap.h,v 1.54 2023/01/24 16:51:06 kettenis Exp $ */
/*
* Copyright (c) 2002-2004 Michael Shalayeff
#include <sys/mutex.h>
#ifdef _KERNEL
+#include <sys/systm.h>
#include <machine/pte.h>
struct pmap {
void pmap_bootstrap(vaddr_t);
boolean_t pmap_changebit(struct vm_page *, pt_entry_t, pt_entry_t);
boolean_t pmap_testbit(struct vm_page *, int);
+void pmap_page_write_protect(struct vm_page *);
void pmap_write_protect(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
void pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva);
void pmap_page_remove(struct vm_page *pg);
static __inline void
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
{
- if ((prot & PROT_WRITE) == 0) {
- if (prot & (PROT_READ | PROT_EXEC))
- pmap_changebit(pg, 0, PTE_PROT(TLB_WRITE));
- else
- pmap_page_remove(pg);
+ if (prot == PROT_READ) {
+ pmap_page_write_protect(pg);
+ } else {
+ KASSERT(prot == PROT_NONE);
+ pmap_page_remove(pg);
}
}
static __inline void
pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
- if ((prot & PROT_WRITE) == 0) {
- if (prot & (PROT_READ | PROT_EXEC))
- pmap_write_protect(pmap, sva, eva, prot);
- else
- pmap_remove(pmap, sva, eva);
- }
+ if (prot != PROT_NONE)
+ pmap_write_protect(pmap, sva, eva, prot);
+ else
+ pmap_remove(pmap, sva, eva);
}
#endif /* _KERNEL */