summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2011-07-09 01:30:40 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2011-07-09 01:30:40 +0000
commitfcb72f95947e42c2d4ae9d7baa5d0fca11be731e (patch)
tree9d2cd0300c27c22571aa67bf913639c06a927c6d
parentb62ede43b6ac09cc9ba3315db12e28c440c2cce1 (diff)
Extract hibernate_write_signature and hibernate_clear_signature to the MI
hibernate code, and add chunk range overlap checking.
-rw-r--r--sys/arch/i386/i386/hibernate_machdep.c50
-rw-r--r--sys/kern/subr_hibernate.c124
-rw-r--r--sys/sys/hibernate.h7
3 files changed, 130 insertions, 51 deletions
diff --git a/sys/arch/i386/i386/hibernate_machdep.c b/sys/arch/i386/i386/hibernate_machdep.c
index 61f3809829d..cb7f194b1b6 100644
--- a/sys/arch/i386/i386/hibernate_machdep.c
+++ b/sys/arch/i386/i386/hibernate_machdep.c
@@ -54,9 +54,6 @@ void hibernate_enter_resume_4k_pde(vaddr_t);
void hibernate_enter_resume_4m_pde(vaddr_t, paddr_t);
void hibernate_populate_resume_pt(paddr_t *, paddr_t *);
int get_hibernate_info_md(union hibernate_info *);
-int hibernate_write_signature(void);
-int hibernate_clear_signature(void);
-int hibernate_inflate_skip(paddr_t);
union hibernate_info *global_hiber_info;
paddr_t global_image_start;
@@ -324,7 +321,7 @@ hibernate_write_image()
}
/* Image write complete, write the signature and return */
- return hibernate_write_signature();
+ return hibernate_write_signature(&hiber_info);
}
int
@@ -489,51 +486,6 @@ hibernate_resume()
hibernate_resume_machine();
}
-int
-hibernate_write_signature()
-{
- union hibernate_info hiber_info;
- u_int8_t *io_page;
-
- /* Get current running machine's hibernate info */
- if (get_hibernate_info(&hiber_info))
- return (1);
-
- io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
- if (!io_page)
- return (1);
-
- /* Write hibernate info to disk */
- hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
- (vaddr_t)&hiber_info, 512, 1, io_page);
-
- free(io_page, M_DEVBUF);
-
- return (0);
-}
-
-int
-hibernate_clear_signature()
-{
- union hibernate_info hiber_info;
- u_int8_t *io_page;
-
- /* Zero out a blank hiber_info */
- bzero(&hiber_info, sizeof(hiber_info));
-
- io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
- if (!io_page)
- return (1);
-
- /* Write (zeroed) hibernate info to disk */
- hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
- (vaddr_t)&hiber_info, 512, 1, io_page);
-
- free(io_page, M_DEVBUF);
-
- return (0);
-}
-
/*
* hibernate_inflate_skip
*
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index bbb7a9f7de3..69cfb2f25ca 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.10 2011/07/09 00:55:00 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.11 2011/07/09 01:30:39 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -17,6 +17,7 @@
*/
#include <sys/hibernate.h>
+#include <sys/malloc.h>
#include <sys/param.h>
#include <sys/tree.h>
#include <sys/types.h>
@@ -610,6 +611,19 @@ void
}
/*
+ * hibernate_zlib_free
+ *
+ * Free the memory pointed to by addr in the hiballoc area presently in
+ * use
+ *
+ */
+void
+hibernate_zlib_free(void *unused, void *addr)
+{
+ hib_free(&hibernate_state->hiballoc_arena, addr);
+}
+
+/*
* hibernate_inflate
*
* Inflate size bytes from src into dest, skipping any pages in
@@ -697,3 +711,111 @@ hibernate_deflate(paddr_t src, size_t *remaining)
return (PAGE_SIZE - (src & PAGE_MASK)) -
hibernate_state->hib_stream.avail_in;
}
+
+/*
+ * hibernate_write_signature
+ *
+ * Write the hibernation information specified in hiber_info
+ * to the location in swap previously calculated (last block of
+ * swap), called the "signature block".
+ *
+ * Write the memory chunk table to the area in swap immediately
+ * preceding the signature block.
+ */
+int
+hibernate_write_signature(union hibernate_info *hiber_info)
+{
+ u_int8_t *io_page;
+ daddr_t chunkbase;
+ size_t i;
+
+ io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+ if (!io_page)
+ return (1);
+
+ /* Write hibernate info to disk */
+ if( hiber_info->io_func(hiber_info->device, hiber_info->sig_offset,
+ (vaddr_t)hiber_info, hiber_info->secsize, 1, io_page))
+ panic("error in hibernate write sig\n");
+
+ chunkbase = hiber_info->sig_offset -
+ (HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize);
+
+ /* Write chunk table */
+ for(i=0; i < HIBERNATE_CHUNK_TABLE_SIZE; i += NBPG) {
+ if(hiber_info->io_func(hiber_info->device,
+ chunkbase + (i/hiber_info->secsize),
+ (vaddr_t)(HIBERNATE_CHUNK_TABLE_START + i),
+ NBPG,
+ 1,
+ io_page))
+ panic("error in hibernate write chunks\n");
+ }
+
+ free(io_page, M_DEVBUF);
+
+ return (0);
+}
+
+/*
+ * hibernate_clear_signature
+ *
+ * Write an empty hiber_info to the swap signature block, which is
+ * guaranteed to not match any valid hiber_info.
+ */
+int
+hibernate_clear_signature()
+{
+ union hibernate_info blank_hiber_info;
+ union hibernate_info hiber_info;
+ u_int8_t *io_page;
+
+ /* Zero out a blank hiber_info */
+ bzero(&blank_hiber_info, sizeof(hiber_info));
+
+ if (get_hibernate_info(&hiber_info))
+ return (1);
+
+ io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+ if (!io_page)
+ return (1);
+
+ /* Write (zeroed) hibernate info to disk */
+ if(hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
+ (vaddr_t)&blank_hiber_info, hiber_info.secsize, 1, io_page))
+ panic("error hibernate write 6\n");
+
+ free(io_page, M_DEVBUF);
+
+ return (0);
+}
+
+/*
+ * hibernate_check_overlap
+ *
+ * Check chunk range overlap when calculating whether or not to copy a
+ * compressed chunk to the piglet area before decompressing.
+ *
+ * returns zero if the ranges do not overlap, non-zero otherwise.
+ */
+int
+hibernate_check_overlap(paddr_t r1s, paddr_t r1e, paddr_t r2s, paddr_t r2e)
+{
+ /* case A : end of r1 overlaps start of r2 */
+ if (r1s < r2s && r1e > r2s)
+ return (1);
+
+ /* case B : r1 entirely inside r2 */
+ if (r1s >= r2s && r1e <= r2e)
+ return (1);
+
+ /* case C : r2 entirely inside r1 */
+ if (r2s >= r1s && r2e <= r1e)
+ return (1);
+
+ /* case D : end of r2 overlaps start of r1 */
+ if (r2s < r1s && r2e > r1s)
+ return (1);
+
+ return (0);
+}
diff --git a/sys/sys/hibernate.h b/sys/sys/hibernate.h
index 58b28f15550..5e3bfbfe4ef 100644
--- a/sys/sys/hibernate.h
+++ b/sys/sys/hibernate.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate.h,v 1.9 2011/07/09 00:55:00 mlarkin Exp $ */
+/* $OpenBSD: hibernate.h,v 1.10 2011/07/09 01:30:39 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -119,4 +119,9 @@ void hibernate_zlib_free(void *, void *);
void hibernate_inflate(paddr_t, paddr_t, size_t);
size_t hibernate_deflate(paddr_t, size_t *);
+int hibernate_write_signature(union hibernate_info *);
+int hibernate_clear_signature(void);
+
+int hibernate_check_overlap(paddr_t, paddr_t, paddr_t, paddr_t);
+
#endif /* _SYS_HIBERNATE_H_ */