summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2014-07-12 09:02:24 +0000
committerkettenis <kettenis@openbsd.org>2014-07-12 09:02:24 +0000
commitf5db0a1ca2f526df2d850deeebfc87e3caa07428 (patch)
treedecde2f335abbad7f55e27a7bbe36d9b82b7c1a3 /sys
parent*** empty log message *** (diff)
downloadwireguard-openbsd-f5db0a1ca2f526df2d850deeebfc87e3caa07428.tar.xz
wireguard-openbsd-f5db0a1ca2f526df2d850deeebfc87e3caa07428.zip
Add a function to drop all clean pages on the page daemon queues and call
it when we hibernate. ok mlarkin@, miod@, deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpi/acpi.c6
-rw-r--r--sys/sys/hibernate.h3
-rw-r--r--sys/uvm/uvm_pdaemon.c60
3 files changed, 65 insertions, 4 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index b6a5c155c66..b680f28487b 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.263 2014/07/11 08:18:31 guenther Exp $ */
+/* $OpenBSD: acpi.c,v 1.264 2014/07/12 09:02:24 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -2117,8 +2117,10 @@ acpi_sleep_state(struct acpi_softc *sc, int state)
goto fail_quiesce;
#ifdef HIBERNATE
- if (state == ACPI_STATE_S4)
+ if (state == ACPI_STATE_S4) {
+ uvmpd_hibernate();
hibernate_suspend_bufcache();
+ }
#endif /* HIBERNATE */
bufq_quiesce();
diff --git a/sys/sys/hibernate.h b/sys/sys/hibernate.h
index b1f546980fe..0def3c7f7e4 100644
--- a/sys/sys/hibernate.h
+++ b/sys/sys/hibernate.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate.h,v 1.33 2014/07/11 03:06:08 mlarkin Exp $ */
+/* $OpenBSD: hibernate.h,v 1.34 2014/07/12 09:02:24 kettenis Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -113,6 +113,7 @@ int uvm_pmr_alloc_pig(paddr_t*, psize_t);
int uvm_pmr_alloc_piglet(vaddr_t*, paddr_t*, vsize_t, paddr_t);
void uvm_pmr_free_piglet(vaddr_t, vsize_t);
int uvm_page_rle(paddr_t);
+void uvmpd_hibernate(void);
hibio_fn get_hibernate_io_function(void);
int get_hibernate_info(union hibernate_info *, int);
diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c
index d6509cbba49..38cc8476f65 100644
--- a/sys/uvm/uvm_pdaemon.c
+++ b/sys/uvm/uvm_pdaemon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_pdaemon.c,v 1.70 2014/07/11 16:35:40 jsg Exp $ */
+/* $OpenBSD: uvm_pdaemon.c,v 1.71 2014/07/12 09:02:24 kettenis Exp $ */
/* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */
/*
@@ -75,6 +75,10 @@
#include <sys/vnode.h>
#include <sys/mount.h>
+#ifdef HIBERNATE
+#include <sys/hibernate.h>
+#endif
+
#include <uvm/uvm.h>
/*
@@ -94,6 +98,7 @@
void uvmpd_scan(void);
boolean_t uvmpd_scan_inactive(struct pglist *);
void uvmpd_tune(void);
+void uvmpd_drop(struct pglist *);
/*
* uvm_wait: wait (sleep) for the page daemon to free some pages
@@ -920,3 +925,56 @@ uvmpd_scan(void)
}
}
}
+
+#ifdef HIBERNATE
+
+/*
+ * uvmpd_drop: drop clean pages from list
+ */
+void
+uvmpd_drop(struct pglist *pglst)
+{
+ struct vm_page *p, *nextpg;
+
+ for (p = TAILQ_FIRST(pglst); p != NULL; p = nextpg) {
+ nextpg = TAILQ_NEXT(p, pageq);
+
+ if (p->pg_flags & PQ_ANON || p->uobject == NULL)
+ continue;
+
+ if (p->pg_flags & PG_BUSY)
+ continue;
+
+ if (p->pg_flags & PG_CLEAN) {
+ /*
+ * we now have the page queues locked.
+ * the page is not busy. if the page is clean we
+ * can free it now and continue.
+ */
+ if (p->pg_flags & PG_CLEAN) {
+ if (p->pg_flags & PQ_SWAPBACKED) {
+ /* this page now lives only in swap */
+ uvmexp.swpgonly++;
+ }
+
+ /* zap all mappings with pmap_page_protect... */
+ pmap_page_protect(p, VM_PROT_NONE);
+ uvm_pagefree(p);
+ }
+ }
+ }
+}
+
+void
+uvmpd_hibernate(void)
+{
+ uvm_lock_pageq();
+
+ uvmpd_drop(&uvm.page_inactive_swp);
+ uvmpd_drop(&uvm.page_inactive_obj);
+ uvmpd_drop(&uvm.page_active);
+
+ uvm_unlock_pageq();
+}
+
+#endif