git: 1c69690319c5 - main - Unmap shared page manually before doing vm_map_remove() on exit or exec
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 28 Oct 2021 19:02:12 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=1c69690319c5bb7deae6ce1add6ea25bb40b3b91
commit 1c69690319c5bb7deae6ce1add6ea25bb40b3b91
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-20 20:32:59 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-10-28 19:01:59 +0000
Unmap shared page manually before doing vm_map_remove() on exit or exec
This allows the pmap_remove(min, max) call to see empty pmap and exploit
empty pmap optimization.
Reviewed by: markj
Tested by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D32569
---
sys/kern/kern_exec.c | 25 +++++++++++++++++++++++++
sys/kern/kern_exit.c | 1 +
sys/sys/sysent.h | 1 +
3 files changed, 27 insertions(+)
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 52119036e95b..780b917ad21d 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1104,6 +1104,30 @@ exec_onexec_old(struct thread *td)
umtx_exec(td->td_proc);
}
+/*
+ * This is an optimization which removes the unmanaged shared page
+ * mapping. In combination with pmap_remove_pages(), which cleans all
+ * managed mappings in the process' vmspace pmap, no work will be left
+ * for pmap_remove(min, max).
+ */
+void
+exec_free_abi_mappings(struct proc *p)
+{
+ struct vmspace *vmspace;
+ struct sysentvec *sv;
+
+ vmspace = p->p_vmspace;
+ if (refcount_load(&vmspace->vm_refcnt) != 1)
+ return;
+
+ sv = p->p_sysent;
+ if (sv->sv_shared_page_obj == NULL)
+ return;
+
+ pmap_remove(vmspace_pmap(vmspace), sv->sv_shared_page_base,
+ sv->sv_shared_page_base + sv->sv_shared_page_len);
+}
+
/*
* Destroy old address space, and allocate a new stack.
* The new stack is only sgrowsiz large because it is grown
@@ -1146,6 +1170,7 @@ exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
vm_map_min(map) == sv_minuser &&
vm_map_max(map) == sv->sv_maxuser &&
cpu_exec_vmspace_reuse(p, map)) {
+ exec_free_abi_mappings(p);
shmexit(vmspace);
pmap_remove_pages(vmspace_pmap(vmspace));
vm_map_remove(map, vm_map_min(map), vm_map_max(map));
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 44203435fa68..14be2425511d 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -417,6 +417,7 @@ exit1(struct thread *td, int rval, int signo)
mtx_unlock(&ppeers_lock);
}
+ exec_free_abi_mappings(p);
vmspace_exit(td);
(void)acct_process(td);
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index ea96c87a79af..fc678d49750a 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -324,6 +324,7 @@ void exec_sysvec_init_secondary(struct sysentvec *sv, struct sysentvec *sv2);
void exec_inittk(void);
void exit_onexit(struct proc *p);
+void exec_free_abi_mappings(struct proc *p);
void exec_onexec_old(struct thread *td);
#define INIT_SYSENTVEC(name, sv) \