summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/hibernate_machdep.c109
-rw-r--r--sys/arch/i386/include/hibernate.h17
-rw-r--r--sys/arch/i386/include/hibernate_var.h29
3 files changed, 72 insertions, 83 deletions
diff --git a/sys/arch/i386/i386/hibernate_machdep.c b/sys/arch/i386/i386/hibernate_machdep.c
index f69a9e6ded2..c5a81b837bb 100644
--- a/sys/arch/i386/i386/hibernate_machdep.c
+++ b/sys/arch/i386/i386/hibernate_machdep.c
@@ -20,13 +20,17 @@
#include <sys/device.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
+#include <sys/hibernate.h>
#include <sys/timeout.h>
#include <sys/malloc.h>
+#include <dev/acpi/acpivar.h>
+
#include <uvm/uvm_extern.h>
#include <uvm/uvm_pmemrange.h>
#include <machine/hibernate.h>
+#include <machine/hibernate_var.h>
#include <machine/kcore.h>
#include <machine/pmap.h>
@@ -37,6 +41,7 @@
#include <machine/mpbiosvar.h>
#endif /* MULTIPROCESSOR */
+#include "acpi.h"
#include "wd.h"
#ifndef SMALL_KERNEL
@@ -44,13 +49,12 @@
int hibernate_write_image(void);
int hibernate_read_image(void);
void hibernate_unpack_image(void);
-void *get_hibernate_io_function(void);
-int get_hibernate_info(struct hibernate_info *);
void hibernate_enter_resume_pte(vaddr_t, paddr_t);
void hibernate_populate_resume_pt(paddr_t *, paddr_t *);
+int get_hibernate_info_md(union hibernate_info *);
int hibernate_write_signature(void);
int hibernate_clear_signature(void);
-struct hibernate_info *global_hiber_info;
+union hibernate_info *global_hiber_info;
paddr_t global_image_start;
extern void hibernate_resume_machine(void);
@@ -66,11 +70,16 @@ extern struct dumpmem dumpmem[];
* i386 MD Hibernate functions
*/
+/*
+ * get_hibernate_io_function
+ *
+ * Returns the hibernate write I/O function to use on this machine
+ *
+ */
void *
get_hibernate_io_function()
{
-
-#if NWD > 0
+#if NWD > 0
/* XXX - Only support wd hibernate presently */
if (strcmp(findblkname(major(swdevt[0].sw_dev)), "wd") == 0)
return wd_hibernate_io;
@@ -81,20 +90,15 @@ get_hibernate_io_function()
#endif
}
+/*
+ * get_hibernate_info_md
+ *
+ * Gather MD-specific data and store into hiber_info
+ */
int
-get_hibernate_info(struct hibernate_info *hiber_info)
+get_hibernate_info_md(union hibernate_info *hiber_info)
{
int i;
- 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 (0);
-
- /* Calculate hibernate device */
- hiber_info->device = swdevt[0].sw_dev;
/* Calculate memory ranges */
hiber_info->nranges = ndumpmem;
@@ -102,10 +106,9 @@ get_hibernate_info(struct hibernate_info *hiber_info)
for(i=0; i<ndumpmem; i++) {
hiber_info->ranges[i].base = dumpmem[i].start * PAGE_SIZE;
- hiber_info->ranges[i].end =
- (dumpmem[i].end * PAGE_SIZE);
- hiber_info->image_size +=
- hiber_info->ranges[i].end - hiber_info->ranges[i].base;
+ hiber_info->ranges[i].end = dumpmem[i].end * PAGE_SIZE;
+ hiber_info->image_size += hiber_info->ranges[i].end -
+ hiber_info->ranges[i].base;
}
#if NACPI > 0
@@ -122,29 +125,7 @@ get_hibernate_info(struct hibernate_info *hiber_info)
hiber_info->image_size += PAGE_SIZE;
#endif
- /* 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: %s\n", dl_ret);
- return (0);
- }
-
- /* Calculate signature block offset in swap */
- hiber_info->sig_offset = DL_BLKTOSEC(&dl,
- (dl.d_partitions[1].p_size - 1)) *
- DL_BLKSPERSEC(&dl);
-
- /* Calculate memory image offset in swap */
- hiber_info->image_offset = dl.d_partitions[1].p_offset +
- dl.d_partitions[1].p_size -
- (hiber_info->image_size / 512) -1;
-
- /* Stash kernel version information */
- bcopy(version, &hiber_info->kernel_version,
- min(strlen(version), sizeof(hiber_info->kernel_version)));
-
- return (1);
+ return (0);
}
/*
@@ -156,7 +137,7 @@ hibernate_enter_resume_pte(vaddr_t va, paddr_t pa)
{
pt_entry_t *pte, npte;
- pte = s4pte_4m(va);
+ pte = s4pde_4m(va);
npte = (pa & PMAP_PA_MASK_4M) | PG_RW | PG_V | PG_U | PG_M | PG_PS;
*pte = npte;
}
@@ -176,7 +157,7 @@ hibernate_populate_resume_pt(paddr_t *image_start, paddr_t *image_end)
vaddr_t kern_start_4m_va, kern_end_4m_va, page;
/* Get the pig (largest contiguous physical range) from uvm */
- if (uvm_pmr_alloc_pig(&pig_start, &pig_sz) == ENOMEM)
+ if (uvm_pmr_alloc_pig(&pig_start, pig_sz) == ENOMEM)
panic("Insufficient memory for resume");
*image_start = pig_start;
@@ -221,14 +202,14 @@ hibernate_populate_resume_pt(paddr_t *image_start, paddr_t *image_end)
int
hibernate_write_image()
{
- struct hibernate_info hiber_info;
+ union hibernate_info hiber_info;
int i, j;
paddr_t range_base, range_end, addr;
daddr_t blkctr;
/* Get current running machine's hibernate info */
- if (!get_hibernate_info(&hiber_info))
- return (0);
+ if (get_hibernate_info(&hiber_info))
+ return (1);
pmap_kenter_pa(HIBERNATE_TEMP_PAGE, HIBERNATE_TEMP_PAGE, VM_PROT_ALL);
pmap_kenter_pa(HIBERNATE_ALLOC_PAGE, HIBERNATE_ALLOC_PAGE, VM_PROT_ALL);
@@ -261,14 +242,14 @@ hibernate_write_image()
int
hibernate_read_image()
{
- struct hibernate_info hiber_info;
+ union hibernate_info hiber_info;
int i, j;
paddr_t range_base, range_end, addr, image_start, image_end;
daddr_t blkctr;
/* Get current running machine's hibernate info */
- if (!get_hibernate_info(&hiber_info))
- return (0);
+ if (get_hibernate_info(&hiber_info))
+ return (1);
pmap_kenter_pa(HIBERNATE_TEMP_PAGE, HIBERNATE_TEMP_PAGE, VM_PROT_ALL);
pmap_kenter_pa(HIBERNATE_ALLOC_PAGE, HIBERNATE_ALLOC_PAGE, VM_PROT_ALL);
@@ -316,7 +297,7 @@ hibernate_suspend()
void
hibernate_unpack_image()
{
- struct hibernate_info *hiber_info = global_hiber_info;
+ union hibernate_info *hiber_info = global_hiber_info;
int i, j;
paddr_t base, end, pig_base;
@@ -337,13 +318,13 @@ hibernate_unpack_image()
void
hibernate_resume()
{
- struct hibernate_info hiber_info, disk_hiber_info;
+ union hibernate_info hiber_info, disk_hiber_info;
u_int8_t *io_page;
int s;
paddr_t image_start, image_end;
/* Get current running machine's hibernate info */
- if (!get_hibernate_info(&hiber_info))
+ if (get_hibernate_info(&hiber_info))
return;
io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
@@ -358,7 +339,7 @@ hibernate_resume()
free(io_page, M_DEVBUF);
if (memcmp(&hiber_info, &disk_hiber_info,
- sizeof(struct hibernate_info)) !=0) {
+ sizeof(union hibernate_info)) !=0) {
return;
}
@@ -402,7 +383,7 @@ hibernate_resume()
hibernate_switch_stack();
/* Read the image from disk into the image (pig) area */
- if (!hibernate_read_image())
+ if (hibernate_read_image())
panic("Failed to restore the hibernate image");
/*
@@ -423,16 +404,16 @@ hibernate_resume()
int
hibernate_write_signature()
{
- struct hibernate_info hiber_info;
+ union hibernate_info hiber_info;
u_int8_t *io_page;
/* Get current running machine's hibernate info */
- if (!get_hibernate_info(&hiber_info))
- return (0);
+ if (get_hibernate_info(&hiber_info))
+ return (1);
io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
if (!io_page)
- return (0);
+ return (1);
/* Write hibernate info to disk */
hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
@@ -440,13 +421,13 @@ hibernate_write_signature()
free(io_page, M_DEVBUF);
- return (1);
+ return (0);
}
int
hibernate_clear_signature()
{
- struct hibernate_info hiber_info;
+ union hibernate_info hiber_info;
u_int8_t *io_page;
/* Zero out a blank hiber_info */
@@ -454,7 +435,7 @@ hibernate_clear_signature()
io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
if (!io_page)
- return (0);
+ return (1);
/* Write (zeroed) hibernate info to disk */
hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
@@ -462,6 +443,6 @@ hibernate_clear_signature()
free(io_page, M_DEVBUF);
- return (1);
+ return (0);
}
#endif /* !SMALL_KERNEL */
diff --git a/sys/arch/i386/include/hibernate.h b/sys/arch/i386/include/hibernate.h
index 9a38cb77081..352de896b7c 100644
--- a/sys/arch/i386/include/hibernate.h
+++ b/sys/arch/i386/include/hibernate.h
@@ -18,21 +18,6 @@
/* i386 hibernate support structures and functions */
-struct hibernate_memory_range {
- paddr_t base;
- paddr_t end;
-};
-
-struct hibernate_info {
- u_int nranges;
- u_int64_t image_size;
- dev_t device;
- daddr_t sig_offset;
- daddr_t image_offset;
- struct hibernate_memory_range ranges[VM_PHYSSEG_MAX];
- char kernel_version[128];
- int (*io_func)(dev_t, daddr_t, vaddr_t, size_t, int, void *);
-};
-
+int get_hibernate_info_md(union hibernate_info *);
int hibernate_suspend(void);
void hibernate_resume(void);
diff --git a/sys/arch/i386/include/hibernate_var.h b/sys/arch/i386/include/hibernate_var.h
index b7aed052c7c..07a14b9836f 100644
--- a/sys/arch/i386/include/hibernate_var.h
+++ b/sys/arch/i386/include/hibernate_var.h
@@ -23,9 +23,32 @@
#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 5)
#define HIBERNATE_IO_PAGE (PAGE_SIZE * 6)
#define HIBERNATE_TEMP_PAGE (PAGE_SIZE * 10)
-#define HIBERNATE_PT_PAGE (PAGE_SIZE * 11)
-#define HIBERNATE_ALLOC_PAGE (PAGE_SIZE * 12)
+#define HIBERNATE_TEMP_PAGE2 (PAGE_SIZE * 11)
+#define HIBERNATE_PD_PAGE (PAGE_SIZE * 12)
+#define HIBERNATE_PT_PAGE (PAGE_SIZE * 13)
+#define HIBERNATE_ALLOC_PAGE (PAGE_SIZE * 14)
+
+#define HIBERNATE_CHUNKS_PAGE (PAGE_SIZE * 15)
+
+/* Use 4MB hibernation chunks */
+#define HIBERNATE_CHUNK_SIZE 0x400000
+
+/* 1MB of chunk table from 1MB-2MB phys */
+#define HIBERNATE_CHUNK_TABLE_START 0x100000
+#define HIBERNATE_CHUNK_TABLE_END 0x200000
+#define HIBERNATE_CHUNK_TABLE_SIZE (HIBERNATE_CHUNK_TABLE_END - \
+ HIBERNATE_CHUNK_TABLE_START)
+
+/* 320KB (80 pages) for gzip allocator */
+#define HIBERNATE_ZLIB_SCRATCH (PAGE_SIZE * 20)
+#define HIBERNATE_ZLIB_START (PAGE_SIZE * 21)
+#define HIBERNATE_ZLIB_END (PAGE_SIZE * (21 + 80))
+#define HIBERNATE_ZLIB_SIZE (HIBERNATE_ZLIB_END - HIBERNATE_ZLIB_START)
+
#define HIBERNATE_STACK_OFFSET 0x0F00
#define atop_4m(x) ((x) >> PAGE_SHIFT_4M)
-#define s4pte_4m(va) ((pt_entry_t *)HIBERNATE_PT_PAGE + atop_4m(va))
+#define atop_4k(x) ((x) >> PAGE_SHIFT)
+#define s4pde_4m(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4m(va))
+#define s4pde_4k(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4k(va))
+#define s4pte_4k(va) ((pt_entry_t *)HIBERNATE_PT_PAGE + atop_4k(va))