summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_hibernate.c
diff options
context:
space:
mode:
authormlarkin <mlarkin@openbsd.org>2014-07-09 15:03:12 +0000
committermlarkin <mlarkin@openbsd.org>2014-07-09 15:03:12 +0000
commit31a590601f8f088433e8062521c0a7f5d043b502 (patch)
tree5b548f6e24d467b5dfd3dae592762c078a62c591 /sys/kern/subr_hibernate.c
parentDelete an obsolete comment (diff)
downloadwireguard-openbsd-31a590601f8f088433e8062521c0a7f5d043b502.tar.xz
wireguard-openbsd-31a590601f8f088433e8062521c0a7f5d043b502.zip
Don't use the suspending kernel's VA mapping for the piglet. It's far
easier and much less error-prone to just identity map it in the resuming kernel as we have more control over the VA space layout there (otherwise we are at the mercy of the suspending kernel's placement of the piglet VA). This diff also increases the size of the piglet to 4 chunks, to avoid an overwrite issue seen in m2k14 where the start of the kernel text was overwritten with a bounced chunk before unpack.
Diffstat (limited to 'sys/kern/subr_hibernate.c')
-rw-r--r--sys/kern/subr_hibernate.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 6dc6e5c7284..d2e9f8919e3 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.94 2014/07/09 14:10:25 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.95 2014/07/09 15:03:12 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -39,7 +39,7 @@
* Its phys and virt addrs are recorded in the signature block. The piglet is
* used to guarantee an unused area of memory that can be used by the resuming
* kernel for various things. The piglet is excluded during unpack operations.
- * The piglet size is presently 3*HIBERNATE_CHUNK_SIZE (typically 3*4MB).
+ * The piglet size is presently 4*HIBERNATE_CHUNK_SIZE (typically 4*4MB).
*
* Offset from piglet_base Purpose
* ----------------------------------------------------------------------------
@@ -55,7 +55,7 @@
* ... unused
* HIBERNATE_CHUNK_SIZE start of hibernate chunk table
* 2*HIBERNATE_CHUNK_SIZE bounce area for chunks being unpacked
- * 3*HIBERNATE_CHUNK_SIZE end of piglet
+ * 4*HIBERNATE_CHUNK_SIZE end of piglet
*/
/* Temporary vaddr ranges used during hibernate */
@@ -720,7 +720,7 @@ get_hibernate_info(union hibernate_info *hib, int suspend)
if (suspend) {
/* Allocate piglet region */
if (uvm_pmr_alloc_piglet(&hib->piglet_va,
- &hib->piglet_pa, HIBERNATE_CHUNK_SIZE*3,
+ &hib->piglet_pa, HIBERNATE_CHUNK_SIZE * 4,
HIBERNATE_CHUNK_SIZE)) {
printf("Hibernate failed to allocate the piglet\n");
return (1);
@@ -761,7 +761,7 @@ get_hibernate_info(union hibernate_info *hib, int suspend)
fail:
if (suspend)
uvm_pmr_free_piglet(hib->piglet_va,
- HIBERNATE_CHUNK_SIZE * 3);
+ HIBERNATE_CHUNK_SIZE * 4);
return (1);
}
@@ -1237,21 +1237,25 @@ hibernate_unpack_image(union hibernate_info *hib)
union hibernate_info local_hib;
paddr_t image_cur = global_pig_start;
short i, *fchunks;
- char *pva = (char *)hib->piglet_va;
+ char *pva;
struct hibernate_zlib_state *hibernate_state;
hibernate_state =
(struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
- /* Mask off based on arch-specific piglet page size */
- pva = (char *)((paddr_t)pva & (PIGLET_PAGE_MASK));
+ /* Piglet will be identity mapped (VA == PA) */
+ pva = (char *)hib->piglet_pa;
+
fchunks = (short *)(pva + (4 * PAGE_SIZE));
- chunks = (struct hibernate_disk_chunk *)(pva + HIBERNATE_CHUNK_SIZE);
+ chunks = (struct hibernate_disk_chunk *)(pva + HIBERNATE_CHUNK_SIZE);
/* Can't use hiber_info that's passed in after this point */
bcopy(hib, &local_hib, sizeof(union hibernate_info));
+ /* VA == PA */
+ local_hib.piglet_va = local_hib.piglet_pa;
+
/*
* Point of no return. Once we pass this point, only kernel code can
* be accessed. No global variables or other kernel data structures
@@ -1898,7 +1902,7 @@ hibernate_free(void)
{
if (global_piglet_va)
uvm_pmr_free_piglet(global_piglet_va,
- 3*HIBERNATE_CHUNK_SIZE);
+ 4 * HIBERNATE_CHUNK_SIZE);
if (hibernate_copy_page)
pmap_kremove(hibernate_copy_page, PAGE_SIZE);