diff options
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/hibernate_machdep.c | 109 | ||||
-rw-r--r-- | sys/arch/i386/include/hibernate.h | 17 | ||||
-rw-r--r-- | sys/arch/i386/include/hibernate_var.h | 29 |
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)) |