summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2011-07-09 00:08:05 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2011-07-09 00:08:05 +0000
commit71d9ed83235b87bb3d516fd3240644d2b2e4c19a (patch)
treef67a4d1c76d89fd285085529215b683becec0255 /sys/kern
parent089899b53c8bcb1f95d767d0e01da67d3700cca6 (diff)
Separate some MD and MI bits and a bit of refactoring to make subsequent
commits easier. Work in progress, hibernate will still not work for you. ok deraadt@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/subr_hibernate.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 056eb882009..41767cc3abf 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.7 2011/07/08 21:02:49 ariane Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.8 2011/07/09 00:08:04 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -21,8 +21,12 @@
#include <sys/tree.h>
#include <sys/types.h>
#include <sys/systm.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
#include <uvm/uvm.h>
+#include <machine/hibernate.h>
+extern char *disk_readlabel(struct disklabel *, dev_t, char *, size_t);
/*
* Hib alloc enforced alignment.
@@ -287,7 +291,7 @@ uvm_pmr_dirty_everything(void)
}
/* Dirty multi page ranges. */
- while ((pg = RB_ROOT(&pmr->size[UVM_PMR_MEMTYPE_ZEOR]))
+ while ((pg = RB_ROOT(&pmr->size[UVM_PMR_MEMTYPE_ZERO]))
!= NULL) {
pg--; /* Size tree always has second page. */
uvm_pmr_remove(pmr, pg);
@@ -522,3 +526,71 @@ uvm_page_rle(paddr_t addr)
(pg_end->pg_flags & PQ_FREE) == PQ_FREE; pg_end++);
return pg_end - pg;
}
+
+/*
+ * get_hibernate_info
+ *
+ * Fills out the hibernate_info union pointed to by hiber_info
+ * with information about this machine (swap signature block
+ * offsets, number of memory ranges, kernel in use, etc)
+ *
+ */
+int
+get_hibernate_info(union hibernate_info *hiber_info)
+{
+ int chunktable_size;
+ struct disklabel dl;
+ char err_string[128], *dl_ret;
+
+ /* Determine I/O function to use */
+ hiber_info->io_func = get_hibernate_io_function();
+ if (hiber_info->io_func == NULL)
+ return (1);
+
+ /* Calculate hibernate device */
+ hiber_info->device = swdevt[0].sw_dev;
+
+ /* Read disklabel (used to calculate signature and image offsets) */
+ dl_ret = disk_readlabel(&dl, hiber_info->device, err_string, 128);
+
+ if (dl_ret) {
+ printf("Hibernate error reading disklabel: %s\n", dl_ret);
+ return (1);
+ }
+
+ hiber_info->secsize = dl.d_secsize;
+
+ /* Make sure the signature can fit in one block */
+ KASSERT(sizeof(union hibernate_info)/hiber_info->secsize == 1);
+
+ /* Calculate swap offset from start of disk */
+ hiber_info->swap_offset = dl.d_partitions[1].p_offset;
+
+ /* Calculate signature block location */
+ hiber_info->sig_offset = dl.d_partitions[1].p_offset +
+ dl.d_partitions[1].p_size -
+ sizeof(union hibernate_info)/hiber_info->secsize;
+
+ chunktable_size = HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize;
+
+ /* Calculate memory image location */
+ hiber_info->image_offset = dl.d_partitions[1].p_offset +
+ dl.d_partitions[1].p_size -
+ (hiber_info->image_size / hiber_info->secsize) -
+ sizeof(union hibernate_info)/hiber_info->secsize -
+ chunktable_size;
+
+ /* Stash kernel version information */
+ bzero(&hiber_info->kernel_version, 128);
+ bcopy(version, &hiber_info->kernel_version,
+ min(strlen(version), sizeof(hiber_info->kernel_version)-1));
+
+ /* Allocate piglet region */
+ if (uvm_pmr_alloc_piglet(&hiber_info->piglet_base, HIBERNATE_CHUNK_SIZE,
+ HIBERNATE_CHUNK_SIZE)) {
+ printf("Hibernate failed to allocate the piglet\n");
+ return (1);
+ }
+
+ return get_hibernate_info_md(hiber_info);
+}