summaryrefslogtreecommitdiff
path: root/sys/uvm/uvm_pmemrange.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/uvm/uvm_pmemrange.c')
-rw-r--r--sys/uvm/uvm_pmemrange.c155
1 files changed, 154 insertions, 1 deletions
diff --git a/sys/uvm/uvm_pmemrange.c b/sys/uvm/uvm_pmemrange.c
index 128772d90ed..8cd16969217 100644
--- a/sys/uvm/uvm_pmemrange.c
+++ b/sys/uvm/uvm_pmemrange.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: uvm_pmemrange.c,v 1.63 2023/04/10 04:21:20 jsg Exp $ */
+/* $OpenBSD: uvm_pmemrange.c,v 1.64 2024/04/17 13:12:58 mpi Exp $ */
/*
+ * Copyright (c) 2024 Martin Pieuchot <mpi@openbsd.org>
* Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -1262,6 +1263,28 @@ out:
}
/*
+ * Acquire a single page.
+ *
+ * flags: UVM_PLA_* flags
+ * result: returned page.
+ */
+struct vm_page *
+uvm_pmr_getone(int flags)
+{
+ struct vm_page *pg;
+ struct pglist pgl;
+
+ TAILQ_INIT(&pgl);
+ if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, flags, &pgl) != 0)
+ return NULL;
+
+ pg = TAILQ_FIRST(&pgl);
+ KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL);
+
+ return pg;
+}
+
+/*
* Free a number of contig pages (invoked by uvm_page_init).
*/
void
@@ -2190,3 +2213,133 @@ uvm_pagezero_thread(void *arg)
yield();
}
}
+
+#if defined(MULTIPROCESSOR) && defined(__HAVE_UVM_PERCPU)
+int
+uvm_pmr_cache_alloc(struct uvm_pmr_cache_item *upci)
+{
+ struct vm_page *pg;
+ struct pglist pgl;
+ int flags = UVM_PLA_NOWAIT|UVM_PLA_NOWAKE;
+ int npages = UVM_PMR_CACHEMAGSZ;
+
+ KASSERT(upci->upci_npages == 0);
+
+ TAILQ_INIT(&pgl);
+ if (uvm_pmr_getpages(npages, 0, 0, 1, 0, npages, flags, &pgl))
+ return -1;
+
+ while ((pg = TAILQ_FIRST(&pgl)) != NULL) {
+ TAILQ_REMOVE(&pgl, pg, pageq);
+ upci->upci_pages[upci->upci_npages] = pg;
+ upci->upci_npages++;
+ }
+ atomic_add_int(&uvmexp.percpucaches, npages);
+
+ return 0;
+}
+
+struct vm_page *
+uvm_pmr_cache_get(int flags)
+{
+ struct uvm_pmr_cache *upc = &curcpu()->ci_uvm;
+ struct uvm_pmr_cache_item *upci;
+ struct vm_page *pg;
+
+ upci = &upc->upc_magz[upc->upc_actv];
+ if (upci->upci_npages == 0) {
+ unsigned int prev;
+
+ prev = (upc->upc_actv == 0) ? 1 : 0;
+ upci = &upc->upc_magz[prev];
+ if (upci->upci_npages == 0) {
+ atomic_inc_int(&uvmexp.pcpmiss);
+ if (uvm_pmr_cache_alloc(upci))
+ return uvm_pmr_getone(flags);
+ }
+ /* Swap magazines */
+ upc->upc_actv = prev;
+ } else {
+ atomic_inc_int(&uvmexp.pcphit);
+ }
+
+ atomic_dec_int(&uvmexp.percpucaches);
+ upci->upci_npages--;
+ pg = upci->upci_pages[upci->upci_npages];
+
+ if (flags & UVM_PLA_ZERO)
+ uvm_pagezero(pg);
+
+ return pg;
+}
+
+void
+uvm_pmr_cache_free(struct uvm_pmr_cache_item *upci)
+{
+ struct pglist pgl;
+ unsigned int i;
+
+ TAILQ_INIT(&pgl);
+ for (i = 0; i < upci->upci_npages; i++)
+ TAILQ_INSERT_TAIL(&pgl, upci->upci_pages[i], pageq);
+
+ uvm_pmr_freepageq(&pgl);
+
+ atomic_sub_int(&uvmexp.percpucaches, upci->upci_npages);
+ upci->upci_npages = 0;
+ memset(upci->upci_pages, 0, sizeof(upci->upci_pages));
+}
+
+void
+uvm_pmr_cache_put(struct vm_page *pg)
+{
+ struct uvm_pmr_cache *upc = &curcpu()->ci_uvm;
+ struct uvm_pmr_cache_item *upci;
+
+ upci = &upc->upc_magz[upc->upc_actv];
+ if (upci->upci_npages >= UVM_PMR_CACHEMAGSZ) {
+ unsigned int prev;
+
+ prev = (upc->upc_actv == 0) ? 1 : 0;
+ upci = &upc->upc_magz[prev];
+ if (upci->upci_npages > 0)
+ uvm_pmr_cache_free(upci);
+
+ /* Swap magazines */
+ upc->upc_actv = prev;
+ KASSERT(upci->upci_npages == 0);
+ }
+
+ upci->upci_pages[upci->upci_npages] = pg;
+ upci->upci_npages++;
+ atomic_inc_int(&uvmexp.percpucaches);
+}
+
+void
+uvm_pmr_cache_drain(void)
+{
+ struct uvm_pmr_cache *upc = &curcpu()->ci_uvm;
+
+ uvm_pmr_cache_free(&upc->upc_magz[0]);
+ uvm_pmr_cache_free(&upc->upc_magz[1]);
+}
+
+#else /* !(MULTIPROCESSOR && __HAVE_UVM_PERCPU) */
+
+struct vm_page *
+uvm_pmr_cache_get(int flags)
+{
+ return uvm_pmr_getone(flags);
+}
+
+void
+uvm_pmr_cache_put(struct vm_page *pg)
+{
+ uvm_pmr_freepages(pg, 1);
+}
+
+void
+uvm_pmr_cache_drain(void)
+{
+}
+#endif