summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2013-11-05 06:02:44 +0000
committerderaadt <deraadt@openbsd.org>2013-11-05 06:02:44 +0000
commit73ac9b723569e28f6fc1f2fad8cc2131745ff17b (patch)
treeba7c05e430d0284e7cb3ed5aabe9757f7c5a962f
parentMention the TX checksum offload support. (diff)
downloadwireguard-openbsd-73ac9b723569e28f6fc1f2fad8cc2131745ff17b.tar.xz
wireguard-openbsd-73ac9b723569e28f6fc1f2fad8cc2131745ff17b.zip
new function uvm_hibswap() finds a the largest free zone in swap, which
hibernate can use place the data. ok mlarkin
-rw-r--r--sys/kern/subr_hibernate.c36
-rw-r--r--sys/uvm/uvm_swap.c53
-rw-r--r--sys/uvm/uvm_swap.h4
3 files changed, 50 insertions, 43 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index bab98e515f5..703934159b4 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.67 2013/11/05 00:51:58 krw Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.68 2013/11/05 06:02:44 deraadt Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -728,12 +728,6 @@ get_hibernate_info(union hibernate_info *hiber_info, int suspend)
if (get_hibernate_info_md(hiber_info))
goto fail;
- /* Calculate memory image location in swap */
- hiber_info->image_offset = DL_GETPOFFSET(&dl.d_partitions[1]) +
- DL_GETPSIZE(&dl.d_partitions[1]) -
- (hiber_info->image_size / hiber_info->secsize) -
- sizeof(union hibernate_info)/hiber_info->secsize -
- chunktable_size;
return (0);
fail:
@@ -1208,8 +1202,6 @@ hibernate_resume(void)
hibernate_quiesce_cpus();
#endif /* MULTIPROCESSOR */
- printf("Unhibernating...");
-
/* Read the image from disk into the image (pig) area */
if (hibernate_read_image(&disk_hiber_info))
goto fail;
@@ -1671,7 +1663,9 @@ hibernate_read_image(union hibernate_info *hiber_info)
disk_size = compressed_size;
- printf(" (image size: %zu)\n", compressed_size);
+ printf("unhibernating @ block %lld length %lu blocks\n",
+ hiber_info->sig_offset - chunktable_size,
+ compressed_size);
/* Allocate the pig area */
pig_sz = compressed_size + HIBERNATE_CHUNK_SIZE;
@@ -1927,7 +1921,7 @@ int
hibernate_suspend(void)
{
union hibernate_info hib_info;
- size_t swap_size;
+ u_long start, end;
/*
* Calculate memory ranges, swap offsets, etc.
@@ -1939,14 +1933,26 @@ hibernate_suspend(void)
return (1);
}
- swap_size = hib_info.image_size + hib_info.secsize +
- HIBERNATE_CHUNK_TABLE_SIZE;
+ /* Find a page-addressed region in swap [start,end] */
+ if (uvm_hibswap(hib_info.device, &start, &end)) {
+ printf("cannot find any swap\n");
+ return (1);
+ }
- if (uvm_swap_check_range(hib_info.device, swap_size)) {
- printf("insufficient swap space for hibernate\n");
+ if (end - start < 1000) {
+ printf("%lu\n is too small", end - start);
return (1);
}
+ /* Calculate block offsets in swap */
+ hib_info.image_offset = ctod(start) + hib_info.swap_offset;
+
+#if 0
+ /* XXX side effect */
+ printf("hibernate @ block %lld max-length %lu blocks\n",
+ hib_info.image_offset, ctod(end) - ctod(start));
+#endif
+
pmap_kenter_pa(HIBERNATE_HIBALLOC_PAGE, HIBERNATE_HIBALLOC_PAGE,
VM_PROT_ALL);
pmap_activate(curproc);
diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c
index 75362c5aaca..348a0a3623f 100644
--- a/sys/uvm/uvm_swap.c
+++ b/sys/uvm/uvm_swap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_swap.c,v 1.119 2013/11/04 19:42:47 deraadt Exp $ */
+/* $OpenBSD: uvm_swap.c,v 1.120 2013/11/05 06:02:45 deraadt Exp $ */
/* $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $ */
/*
@@ -2024,21 +2024,16 @@ gotit:
}
#ifdef HIBERNATE
-/*
- * Check if free swap available at end of swap dev swdev.
- * Used by hibernate to check for usable swap area before writing the image
- */
int
-uvm_swap_check_range(dev_t swdev, size_t size)
+uvm_hibswap(dev_t dev, u_long *sp, u_long *ep)
{
struct swapdev *sdp, *swd = NULL;
struct swappri *spp;
- struct extent *ex;
- struct extent_region *exr;
- int r = 0, start, npages = size / PAGE_SIZE;
+ struct extent_region *exr, *exrn;
+ u_long start = 0, end = 0, size = 0;
/* no swap devices configured yet? */
- if (uvmexp.nswapdev < 1)
+ if (uvmexp.nswapdev < 1 || dev != swdevt[0].sw_dev)
return (1);
for (spp = LIST_FIRST(&swap_priority); spp != NULL;
@@ -2046,28 +2041,34 @@ uvm_swap_check_range(dev_t swdev, size_t size)
for (sdp = CIRCLEQ_FIRST(&spp->spi_swapdev);
sdp != (void *)&spp->spi_swapdev;
sdp = CIRCLEQ_NEXT(sdp,swd_next)) {
- if (sdp->swd_dev == swdev)
+ if (sdp->swd_dev == dev)
swd = sdp;
}
- if (swd == NULL)
- return (1);
-
- if ((swd->swd_flags & SWF_ENABLE) == 0)
+ if (swd == NULL || (swd->swd_flags & SWF_ENABLE) == 0)
return (1);
- ex = swd->swd_ex;
- start = swd->swd_drumsize-npages;
-
- if (npages > swd->swd_drumsize)
- return (1);
-
- LIST_FOREACH(exr, &ex->ex_regions, er_link)
- {
- if (exr->er_end >= start)
- r = 1;
+ LIST_FOREACH(exr, &swd->swd_ex->ex_regions, er_link) {
+ u_long gapstart, gapend, gapsize;
+
+ gapstart = exr->er_end + 1;
+ exrn = LIST_NEXT(exr, er_link);
+ if (!exrn)
+ break;
+ gapend = exrn->er_start - 1;
+ gapsize = gapend - gapstart;
+ if (gapsize > size) {
+ start = gapstart;
+ end = gapend;
+ size = gapsize;
}
+ }
- return (r);
+ if (size) {
+ *sp = start;
+ *ep = end;
+ return (0);
+ }
+ return (1);
}
#endif /* HIBERNATE */
diff --git a/sys/uvm/uvm_swap.h b/sys/uvm/uvm_swap.h
index 0dbcf23c60f..bd3ff0a1809 100644
--- a/sys/uvm/uvm_swap.h
+++ b/sys/uvm/uvm_swap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_swap.h,v 1.15 2012/07/11 16:00:15 mlarkin Exp $ */
+/* $OpenBSD: uvm_swap.h,v 1.16 2013/11/05 06:02:45 deraadt Exp $ */
/* $NetBSD: uvm_swap.h,v 1.5 2000/01/11 06:57:51 chs Exp $ */
/*
@@ -45,7 +45,7 @@ void uvm_swap_free(int, int);
void uvm_swap_markbad(int, int);
void uvm_swap_freepages(struct vm_page **, int);
#ifdef HIBERNATE
-int uvm_swap_check_range(dev_t, size_t);
+int uvm_hibswap(dev_t, u_long *, u_long *);
#endif /* HIBERNATE */
#ifdef UVM_SWAP_ENCRYPT
void uvm_swap_initcrypt_all(void);