summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_hibernate.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_hibernate.c')
-rw-r--r--sys/kern/subr_hibernate.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 17f74030a08..d1d7c41fe28 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.28 2011/11/18 01:31:37 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.29 2011/11/22 07:59:06 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -729,18 +729,6 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest,
/* Flush cache and TLB */
hibernate_flush();
- /*
- * Is this a special page? If yes, redirect the
- * inflate output to a scratch page (eg, discard it)
- */
- if (hibernate_inflate_skip(hiber_info, dest))
- hibernate_enter_resume_mapping(
- HIBERNATE_INFLATE_PAGE,
- HIBERNATE_INFLATE_PAGE, 0);
- else
- hibernate_enter_resume_mapping(
- HIBERNATE_INFLATE_PAGE, dest, 0);
-
/* Read RLE code */
hibernate_state->hib_stream.avail_out = sizeof(psize_t);
hibernate_state->hib_stream.next_out = (char *)&rle;
@@ -754,6 +742,9 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest,
panic("inflate rle error");
}
+ if (i == Z_STREAM_END)
+ goto next_page;
+
/* Skip while RLE code is != 0 */
while (rle != 0) {
dest += (rle * PAGE_SIZE);
@@ -773,6 +764,23 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest,
}
}
+ if (i == Z_STREAM_END)
+ goto next_page;
+
+ /*
+ * Is this a special page? If yes, redirect the
+ * inflate output to a scratch page (eg, discard it)
+ */
+ if (hibernate_inflate_skip(hiber_info, dest))
+ hibernate_enter_resume_mapping(
+ HIBERNATE_INFLATE_PAGE,
+ HIBERNATE_INFLATE_PAGE, 0);
+ else
+ hibernate_enter_resume_mapping(
+ HIBERNATE_INFLATE_PAGE, dest, 0);
+
+ hibernate_flush();
+
/* Set up the stream for inflate */
hibernate_state->hib_stream.avail_out = PAGE_SIZE;
hibernate_state->hib_stream.next_out =
@@ -788,6 +796,7 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest,
panic("inflate error");
}
+next_page:
dest += PAGE_SIZE - hibernate_state->hib_stream.avail_out;
} while (i != Z_STREAM_END);
}
@@ -1108,6 +1117,9 @@ hibernate_unpack_image(union hibernate_info *hiber_info)
/* Can't use hiber_info that's passed in after here */
bcopy(hiber_info, &local_hiber_info, sizeof(union hibernate_info));
+ hibernate_state = (struct hibernate_zlib_state *)
+ (pva + (7 * PAGE_SIZE));
+
hibernate_activate_resume_pt_machdep();
for (i = 0; i < local_hiber_info.chunk_ctr; i++) {
@@ -1250,18 +1262,11 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
while (inaddr < range_end) {
out_remaining = PAGE_SIZE;
while (out_remaining > 0 && inaddr < range_end) {
- pmap_kenter_pa(hibernate_temp_page,
- inaddr & PMAP_PA_MASK, VM_PROT_ALL);
-
- /* XXX - not needed on all archs */
- pmap_activate(curproc);
-
- bcopy((caddr_t)hibernate_temp_page,
- (caddr_t)hibernate_copy_page, PAGE_SIZE);
/*
* Adjust for regions that are not evenly
- * divisible by PAGE_SIZE
+ * divisible by PAGE_SIZE or overflowed
+ * pages from the previous iteration.
*/
temp_inaddr = (inaddr & PAGE_MASK) +
hibernate_copy_page;
@@ -1338,9 +1343,18 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
}
/* Deflate from temp_inaddr to IO page */
- if (inaddr != range_end)
+ if (inaddr != range_end) {
+ pmap_kenter_pa(hibernate_temp_page,
+ inaddr & PMAP_PA_MASK, VM_PROT_ALL);
+
+ /* XXX - not needed on all archs */
+ pmap_activate(curproc);
+
+ bcopy((caddr_t)hibernate_temp_page,
+ (caddr_t)hibernate_copy_page, PAGE_SIZE);
inaddr += hibernate_deflate(hiber_info,
temp_inaddr, &out_remaining);
+ }
}
if (out_remaining == 0) {