summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/acpi_wakecode.S120
-rw-r--r--sys/arch/i386/i386/hibernate_machdep.c416
-rw-r--r--sys/arch/i386/i386/machdep.c14
-rw-r--r--sys/arch/i386/include/hibernate.h38
-rw-r--r--sys/arch/i386/include/hibernate_var.h31
-rw-r--r--sys/arch/i386/include/kcore.h25
7 files changed, 638 insertions, 9 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index cadf84b36fa..b4943512159 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.201 2011/04/05 12:50:15 guenther Exp $
+# $OpenBSD: files.i386,v 1.202 2011/04/30 15:33:18 mlarkin Exp $
#
# new style config file for i386 architecture
#
@@ -24,6 +24,7 @@ file arch/i386/i386/est.c !small_kernel
file arch/i386/i386/gdt.c
file arch/i386/i386/in_cksum.s inet
file arch/i386/i386/machdep.c
+file arch/i386/i386/hibernate_machdep.c
file arch/i386/i386/via.c
file arch/i386/i386/amd64errata.c !small_kernel
file arch/i386/i386/kgdb_machdep.c kgdb
diff --git a/sys/arch/i386/i386/acpi_wakecode.S b/sys/arch/i386/i386/acpi_wakecode.S
index 6c810cf180a..9940f409303 100644
--- a/sys/arch/i386/i386/acpi_wakecode.S
+++ b/sys/arch/i386/i386/acpi_wakecode.S
@@ -44,6 +44,7 @@
#include "assym.h"
#include <machine/asm.h>
+#include <machine/hibernate_var.h>
#include <machine/specialreg.h>
#include <machine/param.h>
#include <machine/segments.h>
@@ -52,6 +53,7 @@
#define _ACPI_TRMP_LABEL(a) a = . - _C_LABEL(acpi_real_mode_resume) + ACPI_TRAMPOLINE
#define _ACPI_TRMP_OFFSET(a) a = . - _C_LABEL(acpi_real_mode_resume)
#define _ACPI_RM_SEGMENT (ACPI_TRAMPOLINE >> 4)
+#define HIBERNATE_STACK_OFFSET 0x0F00
/*
* On wakeup, we'll start executing at acpi_real_mode_resume.
@@ -80,6 +82,7 @@
.global _C_LABEL(acpi_resume_end)
.global _C_LABEL(do_real_mode_post)
_C_LABEL(acpi_real_mode_resume):
+_ACPI_TRMP_OFFSET(acpi_s3_vector_real)
nop
cli
cld
@@ -317,6 +320,72 @@ _C_LABEL(acpi_protected_mode_resume):
xorl %eax, %eax
jmp *acpi_saved_ret
+ /*
+ * hibernate_resume_machine drops to real mode and
+ * restarts the OS using the saved S3 resume vector
+ */
+ .code32
+NENTRY(hibernate_resume_machine)
+ cli
+ /* Jump to the identity mapped version of ourself */
+ mov $hibernate_resume_vector_2, %eax
+ jmp *%eax
+_ACPI_TRMP_LABEL(hibernate_resume_vector_2)
+
+ /* Get out of 32 bit CS */
+ lgdt gdt_16
+ ljmp $0x8, $hibernate_resume_vector_3
+
+_ACPI_TRMP_LABEL(hibernate_resume_vector_3)
+ .code16
+ movl %cr0, %eax
+ /* Disable CR0.PG - no paging */
+ andl $(~CR0_PG), %eax
+ /* Disable CR0.PE - real mode */
+ andl $(~CR0_PE), %eax
+ movl %eax, %cr0
+
+ /* Flush TLB */
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ /* Set up real mode segment selectors */
+ movw $0x0400, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movl $0x0FFE, %esp
+ lidtl clean_idt
+
+ /* Jump to the S3 resume vector */
+ ljmp $0x0400, $acpi_s3_vector_real
+
+ .code32
+ /* Switch to hibernate resume pagetable */
+NENTRY(hibernate_activate_resume_pt)
+ /* Enable large pages */
+ movl %eax, %cr4
+ orl $(CR4_PSE), %eax
+ movl %eax, %cr4
+
+ movl $HIBERNATE_PT_PAGE, %eax
+ movl %eax, %cr3
+ jmp 1f
+
+1: nop
+ ret
+
+NENTRY(hibernate_switch_stack)
+ movl (%esp), %eax
+ movl %eax, HIBERNATE_STACK_PAGE + HIBERNATE_STACK_OFFSET
+ movl $(HIBERNATE_STACK_PAGE + HIBERNATE_STACK_OFFSET), %eax
+ movl %eax, %esp
+
+ /* On our own stack from here onward */
+ ret
+
+ .code16
.align 8
_ACPI_TRMP_OFFSET(tmp_gdt)
.word tmp_gdt_end - tmp_gdtable
@@ -368,6 +437,56 @@ _ACPI_TRMP_OFFSET(clean_idt)
.long 0
.word 0
+ /*
+ * gdt_16 is the gdt used when returning to real mode for bios
+ * reads/writes (sets up a 16 bit segment)
+ */
+ .align 8
+_ACPI_TRMP_LABEL(gdt_16)
+ .word gdt_16_end - gdt_16_table
+ .long gdt_16_table
+
+ .align 8
+_ACPI_TRMP_LABEL(gdt_16_table)
+ /*
+ * null
+ */
+ .word 0, 0
+ .byte 0, 0, 0, 0
+ /*
+ * Code
+ * Limit: 0xffffffff
+ * Base: 0x00000000
+ * Descriptor Type: Code
+ * Segment Type: CRA
+ * Present: True
+ * Priv: 0
+ * AVL: False
+ * 64-bit: False
+ * 32-bit: False
+ *
+ */
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0x8f, 0
+
+ /*
+ * Data
+ * Limit: 0xffffffff
+ * Base: 0x00000000
+ * Descriptor Type:
+ * Segment Type: W
+ * Present: True
+ * Priv: 0
+ * AVL: False
+ * 64-bit: False
+ * 32-bit: False
+ *
+ */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0x8f, 0
+
+_ACPI_TRMP_LABEL(gdt_16_end)
+
.align 4
_C_LABEL(do_real_mode_post):
_ACPI_TRMP_OFFSET(do_real_mode_post_off)
@@ -437,6 +556,7 @@ _C_LABEL(acpi_resume_end):
* for use during the ACPI suspend/resume process.
*/
+ .code32
NENTRY(acpi_savecpu)
movl (%esp), %eax
movl %eax, acpi_saved_ret
diff --git a/sys/arch/i386/i386/hibernate_machdep.c b/sys/arch/i386/i386/hibernate_machdep.c
new file mode 100644
index 00000000000..6c574ee3b62
--- /dev/null
+++ b/sys/arch/i386/i386/hibernate_machdep.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/timeout.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+#include <uvm/uvm_pmemrange.h>
+
+#include <machine/hibernate.h>
+#include <machine/kcore.h>
+#include <machine/pmap.h>
+
+#include <dev/ata/atavar.h>
+#include <dev/ata/wdvar.h>
+
+#ifdef MULTIPROCESSOR
+#include <machine/mpbiosvar.h>
+#endif /* MULTIPROCESSOR */
+
+#include "wd.h"
+
+#ifndef SMALL_KERNEL
+/* Hibernate support */
+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 *);
+struct hibernate_info *global_hiber_info;
+paddr_t global_image_start;
+
+extern void hibernate_resume_machine(void);
+extern void hibernate_activate_resume_pt(void);
+extern void hibernate_switch_stack(void);
+extern char *disk_readlabel(struct disklabel *, dev_t, char *, size_t);
+extern caddr_t start, end;
+extern int ndumpmem;
+extern struct dumpmem dumpmem[];
+
+
+/*
+ * i386 MD Hibernate functions
+ */
+
+void *
+get_hibernate_io_function()
+{
+
+#if NWD > 0
+ /* XXX - Only support wd hibernate presently */
+ if (strcmp(findblkname(major(swapdev)), "wd") == 0)
+ return wd_hibernate_io;
+ else
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+int
+get_hibernate_info(struct 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;
+ hiber_info->image_size = 0;
+
+ for(i=0; i<ndumpmem; i++) {
+ hiber_info->ranges[i].base = dumpmem[i].start;
+ hiber_info->ranges[i].end =
+ (dumpmem[i].start + dumpmem[i].end * PAGE_SIZE);
+ hiber_info->image_size +=
+ hiber_info->ranges[i].end - hiber_info->ranges[i].base;
+ }
+
+#if NACPI > 0
+ hiber_info->ranges[hiber_info->nranges].base = ACPI_TRAMPOLINE;
+ hiber_info->ranges[hiber_info->nranges].end =
+ hiber_info->ranges[hiber_info->nranges].base + PAGE_SIZE;
+ hiber_info->image_size += PAGE_SIZE;
+ hiber_info->nranges ++;
+#endif
+#ifdef MULTIPROCESSOR
+ hiber_info->ranges[hiber_info->nranges].base = MP_TRAMPOLINE;
+ hiber_info->ranges[hiber_info->nranges].end =
+ hiber_info->ranges[hiber_info->nranges].base + PAGE_SIZE;
+ 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);
+}
+
+/*
+ * Enter a 4MB PTE mapping for the supplied VA/PA
+ * into the resume-time page table.
+ */
+void
+hibernate_enter_resume_pte(vaddr_t va, paddr_t pa)
+{
+ pt_entry_t *pte, npte;
+
+ pte = s4pte_4m(va);
+ npte = (pa & PMAP_PA_MASK_4M) | PG_RW | PG_V | PG_U | PG_M | PG_PS;
+ *pte = npte;
+}
+
+/*
+ * Create the resume-time page table. This table maps the image(pig) area,
+ * the kernel text area, and various utility pages located in low memory for
+ * use during resume, since we cannot overwrite the resuming kernel's
+ * page table and expect things to work properly.
+ */
+void
+hibernate_populate_resume_pt(paddr_t *image_start, paddr_t *image_end)
+{
+ int phys_page_number;
+ paddr_t pa, pig_start, pig_end;
+ psize_t pig_sz;
+ 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)
+ panic("Insufficient memory for resume");
+
+ *image_start = pig_start;
+ *image_end = pig_end;
+
+ bzero((caddr_t)HIBERNATE_PT_PAGE, PAGE_SIZE);
+
+ /*
+ * Identity map first 4M physical for tramps and special utility
+ * pages
+ */
+ hibernate_enter_resume_pte(0, 0);
+
+ /*
+ * Map current kernel VA range using 4M pages
+ */
+ kern_start_4m_va = (paddr_t)&start & ~(PAGE_MASK_4M);
+ kern_end_4m_va = (paddr_t)&end & ~(PAGE_MASK_4M);
+ phys_page_number = 0;
+
+ for (page = kern_start_4m_va ; page <= kern_end_4m_va ;
+ page += NBPD, phys_page_number++) {
+
+ pa = (paddr_t)(phys_page_number * NBPD);
+ hibernate_enter_resume_pte(page, pa);
+ }
+
+ /*
+ * Identity map the image (pig) area
+ */
+ phys_page_number = pig_start / NBPD;
+ pig_start &= ~(PAGE_MASK_4M);
+ pig_end &= ~(PAGE_MASK_4M);
+ for (page = pig_start; page <= pig_end ;
+ page += NBPD, phys_page_number++) {
+
+ pa = (paddr_t)(phys_page_number * NBPD);
+ hibernate_enter_resume_pte(page, pa);
+ }
+}
+
+int
+hibernate_write_image()
+{
+ struct 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);
+
+ pmap_kenter_pa(HIBERNATE_TEMP_PAGE, HIBERNATE_TEMP_PAGE, VM_PROT_ALL);
+ pmap_kenter_pa(HIBERNATE_ALLOC_PAGE, HIBERNATE_ALLOC_PAGE, VM_PROT_ALL);
+
+ blkctr = hiber_info.image_offset;
+
+ for (i=0; i < hiber_info.nranges; i++) {
+ range_base = hiber_info.ranges[i].base;
+ range_end = hiber_info.ranges[i].end;
+
+ for (j=0; j < (range_end - range_base)/NBPG;
+ blkctr += (NBPG/512), j += NBPG) {
+ addr = range_base + j;
+ pmap_kenter_pa(HIBERNATE_TEMP_PAGE, addr,
+ VM_PROT_ALL);
+ bcopy((caddr_t)HIBERNATE_TEMP_PAGE,
+ (caddr_t)HIBERNATE_IO_PAGE,
+ NBPG);
+ hiber_info.io_func(hiber_info.device, blkctr,
+ (vaddr_t)HIBERNATE_IO_PAGE, NBPG, 1,
+ (void *)HIBERNATE_ALLOC_PAGE);
+ }
+ }
+
+ return (1);
+}
+
+int
+hibernate_read_image()
+{
+ struct 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);
+
+ pmap_kenter_pa(HIBERNATE_TEMP_PAGE, HIBERNATE_TEMP_PAGE, VM_PROT_ALL);
+ pmap_kenter_pa(HIBERNATE_ALLOC_PAGE, HIBERNATE_ALLOC_PAGE, VM_PROT_ALL);
+
+ blkctr = hiber_info.image_offset;
+
+ /* Prepare the resume-time pagetable */
+ hibernate_populate_resume_pt(&image_start, &image_end);
+
+ for (i=0; i < hiber_info.nranges; i++) {
+ range_base = hiber_info.ranges[i].base;
+ range_end = hiber_info.ranges[i].end;
+
+ for (j=0; j < (range_end - range_base)/NBPG;
+ blkctr += (NBPG/512), j += NBPG) {
+ addr = range_base + j;
+ pmap_kenter_pa(HIBERNATE_TEMP_PAGE, addr,
+ VM_PROT_ALL);
+ hiber_info.io_func(hiber_info.device, blkctr,
+ (vaddr_t)HIBERNATE_IO_PAGE, NBPG, 1,
+ (void *)HIBERNATE_ALLOC_PAGE);
+ bcopy((caddr_t)HIBERNATE_IO_PAGE,
+ (caddr_t)HIBERNATE_TEMP_PAGE,
+ NBPG);
+
+ }
+ }
+
+ return (1);
+}
+
+int
+hibernate_suspend()
+{
+ /*
+ * On i386, the only thing to do on hibernate suspend is
+ * to write the image.
+ */
+
+ return hibernate_write_image();
+}
+
+/* Unpack image from resumed image to real location */
+void
+hibernate_unpack_image()
+{
+ struct hibernate_info *hiber_info = global_hiber_info;
+ int i, j;
+ paddr_t base, end, pig_base;
+
+ hibernate_activate_resume_pt();
+
+ for (i=0; i<hiber_info->nranges; i++) {
+ base = hiber_info->ranges[i].base;
+ end = hiber_info->ranges[i].end;
+ pig_base = base + global_image_start;
+
+ for (j=base; j< (end - base)/NBPD; j++) {
+ hibernate_enter_resume_pte(base, base);
+ bcopy((caddr_t)pig_base, (caddr_t)base, NBPD);
+ }
+ }
+}
+
+void
+hibernate_resume()
+{
+ struct 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))
+ return;
+
+ io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+ if (!io_page)
+ return;
+
+ /* Read hibernate info from disk */
+ s = splbio();
+ hiber_info.io_func(hiber_info.device, hiber_info.sig_offset,
+ (vaddr_t)&disk_hiber_info, 512, 0, io_page);
+
+ free(io_page, M_DEVBUF);
+
+ if (memcmp(&hiber_info, &disk_hiber_info,
+ sizeof(struct hibernate_info)) !=0) {
+ return;
+ }
+
+ /*
+ * On-disk and in-memory hibernate signatures match,
+ * this means we should do a resume from hibernate.
+ */
+
+ disable_intr();
+ cold = 1;
+
+ /*
+ * Add mappings for resume stack and PT page tables
+ * into the "resuming" kernel. We use these mappings
+ * during image read and copy
+ */
+ pmap_activate(curproc);
+ pmap_kenter_pa((vaddr_t)HIBERNATE_STACK_PAGE,
+ (paddr_t)HIBERNATE_STACK_PAGE,
+ VM_PROT_ALL);
+ pmap_kenter_pa((vaddr_t)HIBERNATE_PT_PAGE,
+ (paddr_t)HIBERNATE_PT_PAGE,
+ VM_PROT_ALL);
+
+ /*
+ * Create the resume-time page table (ahead of when we actually
+ * need it)
+ */
+ hibernate_populate_resume_pt(&image_start, &image_end);
+
+
+ /*
+ * We can't access any of this function's local variables (via
+ * stack) after we switch stacks, so we stash hiber_info and
+ * the image start area into temporary global variables first.
+ */
+ global_hiber_info = &hiber_info;
+ global_image_start = image_start;
+
+ /* Switch stacks */
+ hibernate_switch_stack();
+
+ /* Read the image from disk into the image (pig) area */
+ if (!hibernate_read_image())
+ panic("Failed to restore the hibernate image");
+
+ /*
+ * Image is now in high memory (pig area), copy to "correct"
+ * location in memory. We'll eventually end up copying on top
+ * of ourself, but we are assured the kernel code here is
+ * the same between the hibernated and resuming kernel,
+ * and we are running on our own stack
+ */
+ hibernate_unpack_image();
+
+ /*
+ * Resume the loaded kernel by jumping to the S3 resume vector
+ */
+ hibernate_resume_machine();
+}
+#endif /* !SMALL_KERNEL */
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index f542ed57bae..41d902601ac 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.493 2011/04/19 22:14:54 jsg Exp $ */
+/* $OpenBSD: machdep.c,v 1.494 2011/04/30 15:33:18 mlarkin Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -108,6 +108,7 @@
#include <machine/cpufunc.h>
#include <machine/cpuvar.h>
#include <machine/gdt.h>
+#include <machine/kcore.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <machine/psl.h>
@@ -206,10 +207,7 @@ struct uvm_constraint_range *uvm_md_constraints[] = {
extern int boothowto;
int physmem;
-struct dumpmem {
- paddr_t start;
- paddr_t end;
-} dumpmem[VM_PHYSSEG_MAX];
+struct dumpmem dumpmem[VM_PHYSSEG_MAX];
u_int ndumpmem;
/*
@@ -3070,9 +3068,9 @@ init386(paddr_t first_avail)
e = 0xfffff000;
}
- /* skip first eight pages */
- if (a < 8 * NBPG)
- a = 8 * NBPG;
+ /* skip first 16 pages for tramps and hibernate */
+ if (a < 16 * NBPG)
+ a = 16 * NBPG;
/* skip shorter than page regions */
if (a >= e || (e - a) < NBPG) {
diff --git a/sys/arch/i386/include/hibernate.h b/sys/arch/i386/include/hibernate.h
new file mode 100644
index 00000000000..9a38cb77081
--- /dev/null
+++ b/sys/arch/i386/include/hibernate.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/hibernate_var.h>
+
+/* 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 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
new file mode 100644
index 00000000000..b7aed052c7c
--- /dev/null
+++ b/sys/arch/i386/include/hibernate_var.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* i386 hibernate support definitions */
+
+#define PAGE_SHIFT_4M 22
+#define PAGE_MASK_4M (NBPD - 1)
+#define PMAP_PA_MASK_4M ~((paddr_t)PAGE_MASK_4M)
+
+#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_STACK_OFFSET 0x0F00
+
+#define atop_4m(x) ((x) >> PAGE_SHIFT_4M)
+#define s4pte_4m(va) ((pt_entry_t *)HIBERNATE_PT_PAGE + atop_4m(va))
diff --git a/sys/arch/i386/include/kcore.h b/sys/arch/i386/include/kcore.h
new file mode 100644
index 00000000000..f10f9c31271
--- /dev/null
+++ b/sys/arch/i386/include/kcore.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_KCORE_H_
+#define _MACHINE_KCORE_H_
+
+struct dumpmem {
+ paddr_t start;
+ paddr_t end;
+};
+
+#endif /* _MACHINE_KCORE_H_ */