summaryrefslogtreecommitdiff
path: root/sys/kern/subr_hibernate.c
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2014-10-22 04:46:06 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2014-10-22 04:46:06 +0000
commitab378b1b79ca0379437901bea913a69273660e98 (patch)
treee2eeb28c40ba503a0a60909d5eb62f7bc799b996 /sys/kern/subr_hibernate.c
parent3560cfcb22e76cdbc385404940d990b7e3c9ae5e (diff)
Use the global piglet address variables as sparingly as possible to avoid
redundant copies of the same information. No functional change. Also add some comments as to how these globals are used.
Diffstat (limited to 'sys/kern/subr_hibernate.c')
-rw-r--r--sys/kern/subr_hibernate.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 5a0592610e4..1137c7468ba 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.104 2014/10/16 04:19:33 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.105 2014/10/22 04:46:05 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -64,7 +64,19 @@ vaddr_t hibernate_rle_page;
/* Hibernate info as read from disk during resume */
union hibernate_info disk_hib;
+
+/*
+ * Global copy of the pig start address. This needs to be a global as we
+ * switch stacks after computing it - it can't be stored on the stack.
+ */
paddr_t global_pig_start;
+
+/*
+ * Global copies of the piglet start addresses (PA/VA). We store these
+ * as globals to avoid having to carry them around as parameters, as the
+ * piglet is allocated early and freed late - its lifecycle extends beyond
+ * that of the hibernate info union which is calculated on suspend/resume.
+ */
vaddr_t global_piglet_va;
paddr_t global_piglet_pa;
@@ -569,6 +581,7 @@ get_hibernate_info(union hibernate_info *hib, int suspend)
min(strlen(version), sizeof(hib->kernel_version)-1));
if (suspend) {
+ /* Grab the previously-allocated piglet addresses */
hib->piglet_va = global_piglet_va;
hib->piglet_pa = global_piglet_pa;
hib->io_page = (void *)hib->piglet_va;
@@ -597,7 +610,6 @@ get_hibernate_info(union hibernate_info *hib, int suspend)
goto fail;
}
-
if (get_hibernate_info_md(hib))
goto fail;
@@ -1315,8 +1327,8 @@ hibernate_write_chunks(union hibernate_info *hib)
* Map the utility VAs to the piglet. See the piglet map at the
* top of this file for piglet layout information.
*/
- hibernate_copy_page = global_piglet_va + 3 * PAGE_SIZE;
- hibernate_rle_page = global_piglet_va + 28 * PAGE_SIZE;
+ hibernate_copy_page = hib->piglet_va + 3 * PAGE_SIZE;
+ hibernate_rle_page = hib->piglet_va + 28 * PAGE_SIZE;
chunks = (struct hibernate_disk_chunk *)(hib->piglet_va +
HIBERNATE_CHUNK_SIZE);
@@ -1831,6 +1843,7 @@ hibernate_alloc(void)
KASSERT(global_piglet_va == 0);
KASSERT(hibernate_temp_page == 0);
+ /* Allocate a piglet, store its addresses in the supplied globals */
if (uvm_pmr_alloc_piglet(&global_piglet_va, &global_piglet_pa,
HIBERNATE_CHUNK_SIZE * 4, HIBERNATE_CHUNK_SIZE))
return (ENOMEM);
@@ -1839,7 +1852,8 @@ hibernate_alloc(void)
* Allocate VA for the temp page.
*
* This will become part of the suspended kernel and will
- * be freed in hibernate_free, upon resume.
+ * be freed in hibernate_free, upon resume (or hibernate
+ * failure)
*/
hibernate_temp_page = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any,
&kp_none, &kd_nowait);
@@ -1861,14 +1875,12 @@ hibernate_free(void)
uvm_pmr_free_piglet(global_piglet_va,
4 * HIBERNATE_CHUNK_SIZE);
- if (hibernate_temp_page)
+ if (hibernate_temp_page) {
pmap_kremove(hibernate_temp_page, PAGE_SIZE);
-
- pmap_update(pmap_kernel());
-
- if (hibernate_temp_page)
+ pmap_update(pmap_kernel());
km_free((void *)hibernate_temp_page, PAGE_SIZE,
&kv_any, &kp_none);
+ }
global_piglet_va = 0;
hibernate_temp_page = 0;