diff options
-rw-r--r-- | sys/arch/i386/i386/acpi_machdep.c | 14 | ||||
-rw-r--r-- | sys/arch/i386/i386/autoconf.c | 7 | ||||
-rw-r--r-- | sys/kern/subr_hibernate.c | 25 | ||||
-rw-r--r-- | sys/sys/hibernate.h | 4 |
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); |