summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/i386/i386/acpi_machdep.c14
-rw-r--r--sys/arch/i386/i386/autoconf.c7
-rw-r--r--sys/kern/subr_hibernate.c25
-rw-r--r--sys/sys/hibernate.h4
4 files changed, 33 insertions, 17 deletions
diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c
index 95c753e3bda..027658fe2fe 100644
--- a/sys/arch/i386/i386/acpi_machdep.c
+++ b/sys/arch/i386/i386/acpi_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi_machdep.c,v 1.41 2010/10/06 18:21:09 kettenis Exp $ */
+/* $OpenBSD: acpi_machdep.c,v 1.42 2012/03/26 16:15:42 mlarkin Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -23,6 +23,7 @@
#include <sys/memrange.h>
#include <sys/proc.h>
#include <sys/user.h>
+#include <sys/hibernate.h>
#include <uvm/uvm_extern.h>
@@ -263,12 +264,23 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
i386_broadcast_ipi(I386_IPI_HALT);
#endif
wbinvd();
+#ifdef HIBERNATE
+ if (state == ACPI_STATE_S4)
+ if (hibernate_suspend())
+ panic("%s: hibernate failed", DEVNAME(sc));
+#endif
acpi_enter_sleep_state(sc, state);
panic("%s: acpi_enter_sleep_state failed", DEVNAME(sc));
}
/* Resume path continues here */
+#ifdef HIBERNATE
+ /* Free piglet and other pages allocated during suspend */
+ if (state == ACPI_STATE_S4)
+ hibernate_free();
+#endif
+
/* Reset the vector */
sc->sc_facs->wakeup_vector = 0;
diff --git a/sys/arch/i386/i386/autoconf.c b/sys/arch/i386/i386/autoconf.c
index fa34ca1acd1..3ff07dd2cf4 100644
--- a/sys/arch/i386/i386/autoconf.c
+++ b/sys/arch/i386/i386/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.88 2011/06/26 23:19:11 tedu Exp $ */
+/* $OpenBSD: autoconf.c,v 1.89 2012/03/26 16:15:42 mlarkin Exp $ */
/* $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $ */
/*-
@@ -67,6 +67,7 @@
#include <machine/gdt.h>
#include <machine/biosvar.h>
#include <machine/kvm86.h>
+#include <sys/hibernate.h>
#include <dev/cons.h>
@@ -208,6 +209,10 @@ diskconf(void)
setroot(bootdv, part, RB_USERREQ);
dumpconf();
+
+#ifdef HIBERNATE
+ hibernate_resume();
+#endif /* HIBERNATE */
}
struct nam2blk nam2blk[] = {
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 4c3c9c7d06a..45ed48f1867 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.32 2011/11/29 05:21:08 deraadt Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.33 2012/03/26 16:15:42 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -565,10 +565,10 @@ uvm_pmr_free_piglet(vaddr_t va, vsize_t sz)
* Physmem RLE compression support.
*
* Given a physical page address, it will return the number of pages
- * starting at the address, that are free. Clamps to a max of 255 pages.
- * Returns 0 if the page at addr is not free.
+ * starting at the address, that are free. Clamps to the number of pages in
+ * HIBERNATE_CHUNK_SIZE. Returns 0 if the page at addr is not free.
*/
-u_char
+int
uvm_page_rle(paddr_t addr)
{
struct vm_page *pg, *pg_end;
@@ -592,7 +592,7 @@ uvm_page_rle(paddr_t addr)
for (pg_end = pg; pg_end <= vmp->lastpg &&
(pg_end->pg_flags & PQ_FREE) == PQ_FREE; pg_end++)
;
- return max(pg_end - pg, 255);
+ return min((pg_end - pg), HIBERNATE_CHUNK_SIZE/PAGE_SIZE);
}
/*
@@ -722,8 +722,7 @@ void
hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest,
paddr_t src, size_t size)
{
- int i;
- u_char rle;
+ int i, rle;
hibernate_state->hib_stream.next_in = (char *)src;
hibernate_state->hib_stream.avail_in = size;
@@ -1190,11 +1189,11 @@ int
hibernate_write_chunks(union hibernate_info *hiber_info)
{
paddr_t range_base, range_end, inaddr, temp_inaddr;
- size_t nblocks, out_remaining, used, offset = 0;
+ size_t nblocks, out_remaining, used;
struct hibernate_disk_chunk *chunks;
vaddr_t hibernate_io_page = hiber_info->piglet_va + PAGE_SIZE;
- daddr_t blkctr = hiber_info->image_offset;
- int i;
+ daddr_t blkctr = hiber_info->image_offset, offset = 0;
+ int i, rle;
hiber_info->chunk_ctr = 0;
@@ -1263,7 +1262,6 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
while (inaddr < range_end) {
out_remaining = PAGE_SIZE;
while (out_remaining > 0 && inaddr < range_end) {
- u_char rle;
/*
* Adjust for regions that are not evenly
@@ -1615,8 +1613,8 @@ hibernate_read_chunks(union hibernate_info *hib_info, paddr_t pig_start,
*/
for (i = 0; i < nchunks; i++) {
if (chunks[i].end <= pig_start || chunks[i].base >= pig_end) {
- ochunks[nochunks] = (u_int8_t)i;
- fchunks[nfchunks] = (u_int8_t)i;
+ ochunks[nochunks] = i;
+ fchunks[nfchunks] = i;
nochunks++;
nfchunks++;
chunks[i].flags |= HIBERNATE_CHUNK_USED;
@@ -1681,6 +1679,7 @@ hibernate_read_chunks(union hibernate_info *hib_info, paddr_t pig_start,
piglet_cur = piglet_base;
npchunks = 0;
j = i;
+
while (copy_start < copy_end && j < nochunks) {
piglet_cur += chunks[ochunks[j]].compressed_size;
pchunks[npchunks] = ochunks[j];
diff --git a/sys/sys/hibernate.h b/sys/sys/hibernate.h
index aa96f38d33a..17a56d65e0f 100644
--- a/sys/sys/hibernate.h
+++ b/sys/sys/hibernate.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate.h,v 1.19 2011/11/29 05:21:10 deraadt Exp $ */
+/* $OpenBSD: hibernate.h,v 1.20 2012/03/26 16:15:42 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -105,7 +105,7 @@ void uvm_pmr_dirty_everything(void);
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);
-u_char uvm_page_rle(paddr_t);
+int uvm_page_rle(paddr_t);
hibio_fn get_hibernate_io_function(void);
int get_hibernate_info(union hibernate_info *, int);