xref: /openbsd-src/sys/kern/subr_hibernate.c (revision 9ecd98c6005380dddc2ef65cdaf97e13ee7ca812)
1 /*	$OpenBSD: subr_hibernate.c,v 1.57 2013/05/31 20:00:00 mlarkin Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
5  * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/hibernate.h>
21 #include <sys/malloc.h>
22 #include <sys/param.h>
23 #include <sys/tree.h>
24 #include <sys/systm.h>
25 #include <sys/disklabel.h>
26 #include <sys/disk.h>
27 #include <sys/conf.h>
28 #include <sys/buf.h>
29 #include <sys/fcntl.h>
30 #include <sys/stat.h>
31 #include <uvm/uvm.h>
32 #include <uvm/uvm_swap.h>
33 #include <machine/hibernate.h>
34 
35 /*
36  * Hibernate piglet layout information
37  *
38  * The piglet is a scratch area of memory allocated by the suspending kernel.
39  * Its phys and virt addrs are recorded in the signature block. The piglet is
40  * used to guarantee an unused area of memory that can be used by the resuming
41  * kernel for various things. The piglet is excluded during unpack operations.
42  * The piglet size is presently 3*HIBERNATE_CHUNK_SIZE (typically 3*4MB).
43  *
44  * Offset from piglet_base	Purpose
45  * ----------------------------------------------------------------------------
46  * 0				I/O page used during resume
47  * 1*PAGE_SIZE		 	I/O page used during hibernate suspend
48  * 2*PAGE_SIZE			unused
49  * 3*PAGE_SIZE			copy page used during hibernate suspend
50  * 4*PAGE_SIZE			final chunk ordering list (8 pages)
51  * 12*PAGE_SIZE			piglet chunk ordering list (8 pages)
52  * 20*PAGE_SIZE			temp chunk ordering list (8 pages)
53  * 28*PAGE_SIZE			start of hiballoc area
54  * 108*PAGE_SIZE		end of hiballoc area (80 pages)
55  * ...				unused
56  * HIBERNATE_CHUNK_SIZE		start of hibernate chunk table
57  * 2*HIBERNATE_CHUNK_SIZE	bounce area for chunks being unpacked
58  * 3*HIBERNATE_CHUNK_SIZE	end of piglet
59  */
60 
61 /* Temporary vaddr ranges used during hibernate */
62 vaddr_t hibernate_temp_page;
63 vaddr_t hibernate_copy_page;
64 
65 /* Hibernate info as read from disk during resume */
66 union hibernate_info disk_hiber_info;
67 paddr_t global_pig_start;
68 vaddr_t global_piglet_va;
69 
70 void hibernate_copy_chunk_to_piglet(paddr_t, vaddr_t, size_t);
71 
72 /*
73  * Hib alloc enforced alignment.
74  */
75 #define HIB_ALIGN		8 /* bytes alignment */
76 
77 /*
78  * sizeof builtin operation, but with alignment constraint.
79  */
80 #define HIB_SIZEOF(_type)	roundup(sizeof(_type), HIB_ALIGN)
81 
82 struct hiballoc_entry {
83 	size_t			hibe_use;
84 	size_t			hibe_space;
85 	RB_ENTRY(hiballoc_entry) hibe_entry;
86 };
87 
88 /*
89  * Compare hiballoc entries based on the address they manage.
90  *
91  * Since the address is fixed, relative to struct hiballoc_entry,
92  * we just compare the hiballoc_entry pointers.
93  */
94 static __inline int
95 hibe_cmp(struct hiballoc_entry *l, struct hiballoc_entry *r)
96 {
97 	return l < r ? -1 : (l > r);
98 }
99 
100 RB_PROTOTYPE(hiballoc_addr, hiballoc_entry, hibe_entry, hibe_cmp)
101 
102 /*
103  * Given a hiballoc entry, return the address it manages.
104  */
105 static __inline void *
106 hib_entry_to_addr(struct hiballoc_entry *entry)
107 {
108 	caddr_t addr;
109 
110 	addr = (caddr_t)entry;
111 	addr += HIB_SIZEOF(struct hiballoc_entry);
112 	return addr;
113 }
114 
115 /*
116  * Given an address, find the hiballoc that corresponds.
117  */
118 static __inline struct hiballoc_entry*
119 hib_addr_to_entry(void *addr_param)
120 {
121 	caddr_t addr;
122 
123 	addr = (caddr_t)addr_param;
124 	addr -= HIB_SIZEOF(struct hiballoc_entry);
125 	return (struct hiballoc_entry*)addr;
126 }
127 
128 RB_GENERATE(hiballoc_addr, hiballoc_entry, hibe_entry, hibe_cmp)
129 
130 /*
131  * Allocate memory from the arena.
132  *
133  * Returns NULL if no memory is available.
134  */
135 void *
136 hib_alloc(struct hiballoc_arena *arena, size_t alloc_sz)
137 {
138 	struct hiballoc_entry *entry, *new_entry;
139 	size_t find_sz;
140 
141 	/*
142 	 * Enforce alignment of HIB_ALIGN bytes.
143 	 *
144 	 * Note that, because the entry is put in front of the allocation,
145 	 * 0-byte allocations are guaranteed a unique address.
146 	 */
147 	alloc_sz = roundup(alloc_sz, HIB_ALIGN);
148 
149 	/*
150 	 * Find an entry with hibe_space >= find_sz.
151 	 *
152 	 * If the root node is not large enough, we switch to tree traversal.
153 	 * Because all entries are made at the bottom of the free space,
154 	 * traversal from the end has a slightly better chance of yielding
155 	 * a sufficiently large space.
156 	 */
157 	find_sz = alloc_sz + HIB_SIZEOF(struct hiballoc_entry);
158 	entry = RB_ROOT(&arena->hib_addrs);
159 	if (entry != NULL && entry->hibe_space < find_sz) {
160 		RB_FOREACH_REVERSE(entry, hiballoc_addr, &arena->hib_addrs) {
161 			if (entry->hibe_space >= find_sz)
162 				break;
163 		}
164 	}
165 
166 	/*
167 	 * Insufficient or too fragmented memory.
168 	 */
169 	if (entry == NULL)
170 		return NULL;
171 
172 	/*
173 	 * Create new entry in allocated space.
174 	 */
175 	new_entry = (struct hiballoc_entry*)(
176 	    (caddr_t)hib_entry_to_addr(entry) + entry->hibe_use);
177 	new_entry->hibe_space = entry->hibe_space - find_sz;
178 	new_entry->hibe_use = alloc_sz;
179 
180 	/*
181 	 * Insert entry.
182 	 */
183 	if (RB_INSERT(hiballoc_addr, &arena->hib_addrs, new_entry) != NULL)
184 		panic("hib_alloc: insert failure");
185 	entry->hibe_space = 0;
186 
187 	/* Return address managed by entry. */
188 	return hib_entry_to_addr(new_entry);
189 }
190 
191 /*
192  * Free a pointer previously allocated from this arena.
193  *
194  * If addr is NULL, this will be silently accepted.
195  */
196 void
197 hib_free(struct hiballoc_arena *arena, void *addr)
198 {
199 	struct hiballoc_entry *entry, *prev;
200 
201 	if (addr == NULL)
202 		return;
203 
204 	/*
205 	 * Derive entry from addr and check it is really in this arena.
206 	 */
207 	entry = hib_addr_to_entry(addr);
208 	if (RB_FIND(hiballoc_addr, &arena->hib_addrs, entry) != entry)
209 		panic("hib_free: freed item %p not in hib arena", addr);
210 
211 	/*
212 	 * Give the space in entry to its predecessor.
213 	 *
214 	 * If entry has no predecessor, change its used space into free space
215 	 * instead.
216 	 */
217 	prev = RB_PREV(hiballoc_addr, &arena->hib_addrs, entry);
218 	if (prev != NULL &&
219 	    (void *)((caddr_t)prev + HIB_SIZEOF(struct hiballoc_entry) +
220 	    prev->hibe_use + prev->hibe_space) == entry) {
221 		/* Merge entry. */
222 		RB_REMOVE(hiballoc_addr, &arena->hib_addrs, entry);
223 		prev->hibe_space += HIB_SIZEOF(struct hiballoc_entry) +
224 		    entry->hibe_use + entry->hibe_space;
225 	} else {
226 		/* Flip used memory to free space. */
227 		entry->hibe_space += entry->hibe_use;
228 		entry->hibe_use = 0;
229 	}
230 }
231 
232 /*
233  * Initialize hiballoc.
234  *
235  * The allocator will manage memmory at ptr, which is len bytes.
236  */
237 int
238 hiballoc_init(struct hiballoc_arena *arena, void *p_ptr, size_t p_len)
239 {
240 	struct hiballoc_entry *entry;
241 	caddr_t ptr;
242 	size_t len;
243 
244 	RB_INIT(&arena->hib_addrs);
245 
246 	/*
247 	 * Hib allocator enforces HIB_ALIGN alignment.
248 	 * Fixup ptr and len.
249 	 */
250 	ptr = (caddr_t)roundup((vaddr_t)p_ptr, HIB_ALIGN);
251 	len = p_len - ((size_t)ptr - (size_t)p_ptr);
252 	len &= ~((size_t)HIB_ALIGN - 1);
253 
254 	/*
255 	 * Insufficient memory to be able to allocate and also do bookkeeping.
256 	 */
257 	if (len <= HIB_SIZEOF(struct hiballoc_entry))
258 		return ENOMEM;
259 
260 	/*
261 	 * Create entry describing space.
262 	 */
263 	entry = (struct hiballoc_entry*)ptr;
264 	entry->hibe_use = 0;
265 	entry->hibe_space = len - HIB_SIZEOF(struct hiballoc_entry);
266 	RB_INSERT(hiballoc_addr, &arena->hib_addrs, entry);
267 
268 	return 0;
269 }
270 
271 /*
272  * Zero all free memory.
273  */
274 void
275 uvm_pmr_zero_everything(void)
276 {
277 	struct uvm_pmemrange	*pmr;
278 	struct vm_page		*pg;
279 	int			 i;
280 
281 	uvm_lock_fpageq();
282 	TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) {
283 		/* Zero single pages. */
284 		while ((pg = TAILQ_FIRST(&pmr->single[UVM_PMR_MEMTYPE_DIRTY]))
285 		    != NULL) {
286 			uvm_pmr_remove(pmr, pg);
287 			uvm_pagezero(pg);
288 			atomic_setbits_int(&pg->pg_flags, PG_ZERO);
289 			uvmexp.zeropages++;
290 			uvm_pmr_insert(pmr, pg, 0);
291 		}
292 
293 		/* Zero multi page ranges. */
294 		while ((pg = RB_ROOT(&pmr->size[UVM_PMR_MEMTYPE_DIRTY]))
295 		    != NULL) {
296 			pg--; /* Size tree always has second page. */
297 			uvm_pmr_remove(pmr, pg);
298 			for (i = 0; i < pg->fpgsz; i++) {
299 				uvm_pagezero(&pg[i]);
300 				atomic_setbits_int(&pg[i].pg_flags, PG_ZERO);
301 				uvmexp.zeropages++;
302 			}
303 			uvm_pmr_insert(pmr, pg, 0);
304 		}
305 	}
306 	uvm_unlock_fpageq();
307 }
308 
309 /*
310  * Mark all memory as dirty.
311  *
312  * Used to inform the system that the clean memory isn't clean for some
313  * reason, for example because we just came back from hibernate.
314  */
315 void
316 uvm_pmr_dirty_everything(void)
317 {
318 	struct uvm_pmemrange	*pmr;
319 	struct vm_page		*pg;
320 	int			 i;
321 
322 	uvm_lock_fpageq();
323 	TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) {
324 		/* Dirty single pages. */
325 		while ((pg = TAILQ_FIRST(&pmr->single[UVM_PMR_MEMTYPE_ZERO]))
326 		    != NULL) {
327 			uvm_pmr_remove(pmr, pg);
328 			atomic_clearbits_int(&pg->pg_flags, PG_ZERO);
329 			uvm_pmr_insert(pmr, pg, 0);
330 		}
331 
332 		/* Dirty multi page ranges. */
333 		while ((pg = RB_ROOT(&pmr->size[UVM_PMR_MEMTYPE_ZERO]))
334 		    != NULL) {
335 			pg--; /* Size tree always has second page. */
336 			uvm_pmr_remove(pmr, pg);
337 			for (i = 0; i < pg->fpgsz; i++)
338 				atomic_clearbits_int(&pg[i].pg_flags, PG_ZERO);
339 			uvm_pmr_insert(pmr, pg, 0);
340 		}
341 	}
342 
343 	uvmexp.zeropages = 0;
344 	uvm_unlock_fpageq();
345 }
346 
347 /*
348  * Allocate the highest address that can hold sz.
349  *
350  * sz in bytes.
351  */
352 int
353 uvm_pmr_alloc_pig(paddr_t *addr, psize_t sz)
354 {
355 	struct uvm_pmemrange	*pmr;
356 	struct vm_page		*pig_pg, *pg;
357 
358 	/*
359 	 * Convert sz to pages, since that is what pmemrange uses internally.
360 	 */
361 	sz = atop(round_page(sz));
362 
363 	uvm_lock_fpageq();
364 
365 	TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) {
366 		RB_FOREACH_REVERSE(pig_pg, uvm_pmr_addr, &pmr->addr) {
367 			if (pig_pg->fpgsz >= sz) {
368 				goto found;
369 			}
370 		}
371 	}
372 
373 	/*
374 	 * Allocation failure.
375 	 */
376 	uvm_unlock_fpageq();
377 	return ENOMEM;
378 
379 found:
380 	/* Remove page from freelist. */
381 	uvm_pmr_remove_size(pmr, pig_pg);
382 	pig_pg->fpgsz -= sz;
383 	pg = pig_pg + pig_pg->fpgsz;
384 	if (pig_pg->fpgsz == 0)
385 		uvm_pmr_remove_addr(pmr, pig_pg);
386 	else
387 		uvm_pmr_insert_size(pmr, pig_pg);
388 
389 	uvmexp.free -= sz;
390 	*addr = VM_PAGE_TO_PHYS(pg);
391 
392 	/*
393 	 * Update pg flags.
394 	 *
395 	 * Note that we trash the sz argument now.
396 	 */
397 	while (sz > 0) {
398 		KASSERT(pg->pg_flags & PQ_FREE);
399 
400 		atomic_clearbits_int(&pg->pg_flags,
401 		    PG_PMAP0|PG_PMAP1|PG_PMAP2|PG_PMAP3);
402 
403 		if (pg->pg_flags & PG_ZERO)
404 			uvmexp.zeropages -= sz;
405 		atomic_clearbits_int(&pg->pg_flags,
406 		    PG_ZERO|PQ_FREE);
407 
408 		pg->uobject = NULL;
409 		pg->uanon = NULL;
410 		pg->pg_version++;
411 
412 		/*
413 		 * Next.
414 		 */
415 		pg++;
416 		sz--;
417 	}
418 
419 	/* Return. */
420 	uvm_unlock_fpageq();
421 	return 0;
422 }
423 
424 /*
425  * Allocate a piglet area.
426  *
427  * This is as low as possible.
428  * Piglets are aligned.
429  *
430  * sz and align in bytes.
431  *
432  * The call will sleep for the pagedaemon to attempt to free memory.
433  * The pagedaemon may decide its not possible to free enough memory, causing
434  * the allocation to fail.
435  */
436 int
437 uvm_pmr_alloc_piglet(vaddr_t *va, paddr_t *pa, vsize_t sz, paddr_t align)
438 {
439 	paddr_t			 pg_addr, piglet_addr;
440 	struct uvm_pmemrange	*pmr;
441 	struct vm_page		*pig_pg, *pg;
442 	struct pglist		 pageq;
443 	int			 pdaemon_woken;
444 	vaddr_t			 piglet_va;
445 
446 	/* Ensure align is a power of 2 */
447 	KASSERT((align & (align - 1)) == 0);
448 
449 	pdaemon_woken = 0; /* Didn't wake the pagedaemon. */
450 
451 	/*
452 	 * Fixup arguments: align must be at least PAGE_SIZE,
453 	 * sz will be converted to pagecount, since that is what
454 	 * pmemrange uses internally.
455 	 */
456 	if (align < PAGE_SIZE)
457 		align = PAGE_SIZE;
458 	sz = round_page(sz);
459 
460 	uvm_lock_fpageq();
461 
462 	TAILQ_FOREACH_REVERSE(pmr, &uvm.pmr_control.use, uvm_pmemrange_use,
463 	    pmr_use) {
464 retry:
465 		/*
466 		 * Search for a range with enough space.
467 		 * Use the address tree, to ensure the range is as low as
468 		 * possible.
469 		 */
470 		RB_FOREACH(pig_pg, uvm_pmr_addr, &pmr->addr) {
471 			pg_addr = VM_PAGE_TO_PHYS(pig_pg);
472 			piglet_addr = (pg_addr + (align - 1)) & ~(align - 1);
473 
474 			if (atop(pg_addr) + pig_pg->fpgsz >=
475 			    atop(piglet_addr) + atop(sz))
476 				goto found;
477 		}
478 	}
479 
480 	/*
481 	 * Try to coerce the pagedaemon into freeing memory
482 	 * for the piglet.
483 	 *
484 	 * pdaemon_woken is set to prevent the code from
485 	 * falling into an endless loop.
486 	 */
487 	if (!pdaemon_woken) {
488 		pdaemon_woken = 1;
489 		if (uvm_wait_pla(ptoa(pmr->low), ptoa(pmr->high) - 1,
490 		    sz, UVM_PLA_FAILOK) == 0)
491 			goto retry;
492 	}
493 
494 	/* Return failure. */
495 	uvm_unlock_fpageq();
496 	return ENOMEM;
497 
498 found:
499 	/*
500 	 * Extract piglet from pigpen.
501 	 */
502 	TAILQ_INIT(&pageq);
503 	uvm_pmr_extract_range(pmr, pig_pg,
504 	    atop(piglet_addr), atop(piglet_addr) + atop(sz), &pageq);
505 
506 	*pa = piglet_addr;
507 	uvmexp.free -= atop(sz);
508 
509 	/*
510 	 * Update pg flags.
511 	 *
512 	 * Note that we trash the sz argument now.
513 	 */
514 	TAILQ_FOREACH(pg, &pageq, pageq) {
515 		KASSERT(pg->pg_flags & PQ_FREE);
516 
517 		atomic_clearbits_int(&pg->pg_flags,
518 		    PG_PMAP0|PG_PMAP1|PG_PMAP2|PG_PMAP3);
519 
520 		if (pg->pg_flags & PG_ZERO)
521 			uvmexp.zeropages--;
522 		atomic_clearbits_int(&pg->pg_flags,
523 		    PG_ZERO|PQ_FREE);
524 
525 		pg->uobject = NULL;
526 		pg->uanon = NULL;
527 		pg->pg_version++;
528 	}
529 
530 	uvm_unlock_fpageq();
531 
532 	/*
533 	 * Now allocate a va.
534 	 * Use direct mappings for the pages.
535 	 */
536 
537 	piglet_va = *va = (vaddr_t)km_alloc(sz, &kv_any, &kp_none, &kd_waitok);
538 	if (!piglet_va) {
539 		uvm_pglistfree(&pageq);
540 		return ENOMEM;
541 	}
542 
543 	/*
544 	 * Map piglet to va.
545 	 */
546 	TAILQ_FOREACH(pg, &pageq, pageq) {
547 		pmap_kenter_pa(piglet_va, VM_PAGE_TO_PHYS(pg), UVM_PROT_RW);
548 		piglet_va += PAGE_SIZE;
549 	}
550 	pmap_update(pmap_kernel());
551 
552 	return 0;
553 }
554 
555 /*
556  * Free a piglet area.
557  */
558 void
559 uvm_pmr_free_piglet(vaddr_t va, vsize_t sz)
560 {
561 	paddr_t			 pa;
562 	struct vm_page		*pg;
563 
564 	/*
565 	 * Fix parameters.
566 	 */
567 	sz = round_page(sz);
568 
569 	/*
570 	 * Find the first page in piglet.
571 	 * Since piglets are contiguous, the first pg is all we need.
572 	 */
573 	if (!pmap_extract(pmap_kernel(), va, &pa))
574 		panic("uvm_pmr_free_piglet: piglet 0x%lx has no pages", va);
575 	pg = PHYS_TO_VM_PAGE(pa);
576 	if (pg == NULL)
577 		panic("uvm_pmr_free_piglet: unmanaged page 0x%lx", pa);
578 
579 	/*
580 	 * Unmap.
581 	 */
582 	pmap_kremove(va, sz);
583 	pmap_update(pmap_kernel());
584 
585 	/*
586 	 * Free the physical and virtual memory.
587 	 */
588 	uvm_pmr_freepages(pg, atop(sz));
589 	km_free((void *)va, sz, &kv_any, &kp_none);
590 }
591 
592 /*
593  * Physmem RLE compression support.
594  *
595  * Given a physical page address, return the number of pages starting at the
596  * address that are free.  Clamps to the number of pages in
597  * HIBERNATE_CHUNK_SIZE. Returns 0 if the page at addr is not free.
598  */
599 int
600 uvm_page_rle(paddr_t addr)
601 {
602 	struct vm_page		*pg, *pg_end;
603 	struct vm_physseg	*vmp;
604 	int			 pseg_idx, off_idx;
605 
606 	pseg_idx = vm_physseg_find(atop(addr), &off_idx);
607 	if (pseg_idx == -1)
608 		return 0;
609 
610 	vmp = &vm_physmem[pseg_idx];
611 	pg = &vmp->pgs[off_idx];
612 	if (!(pg->pg_flags & PQ_FREE))
613 		return 0;
614 
615 	/*
616 	 * Search for the first non-free page after pg.
617 	 * Note that the page may not be the first page in a free pmemrange,
618 	 * therefore pg->fpgsz cannot be used.
619 	 */
620 	for (pg_end = pg; pg_end <= vmp->lastpg &&
621 	    (pg_end->pg_flags & PQ_FREE) == PQ_FREE; pg_end++)
622 		;
623 	return min((pg_end - pg), HIBERNATE_CHUNK_SIZE/PAGE_SIZE);
624 }
625 
626 /*
627  * Fills out the hibernate_info union pointed to by hiber_info
628  * with information about this machine (swap signature block
629  * offsets, number of memory ranges, kernel in use, etc)
630  */
631 int
632 get_hibernate_info(union hibernate_info *hiber_info, int suspend)
633 {
634 	int chunktable_size;
635 	struct disklabel dl;
636 	char err_string[128], *dl_ret;
637 
638 	/* Determine I/O function to use */
639 	hiber_info->io_func = get_hibernate_io_function();
640 	if (hiber_info->io_func == NULL)
641 		return (1);
642 
643 	/* Calculate hibernate device */
644 	hiber_info->device = swdevt[0].sw_dev;
645 
646 	/* Read disklabel (used to calculate signature and image offsets) */
647 	dl_ret = disk_readlabel(&dl, hiber_info->device, err_string, 128);
648 
649 	if (dl_ret) {
650 		printf("Hibernate error reading disklabel: %s\n", dl_ret);
651 		return (1);
652 	}
653 
654 	/* Make sure we have a swap partition. */
655 	if (dl.d_partitions[1].p_fstype != FS_SWAP ||
656 	    dl.d_partitions[1].p_size == 0)
657 		return (1);
658 
659 	hiber_info->secsize = dl.d_secsize;
660 
661 	/* Make sure the signature can fit in one block */
662 	if(sizeof(union hibernate_info) > hiber_info->secsize)
663 		return (1);
664 
665 	/* Magic number */
666 	hiber_info->magic = HIBERNATE_MAGIC;
667 
668 	/* Calculate swap offset from start of disk */
669 	hiber_info->swap_offset = dl.d_partitions[1].p_offset;
670 
671 	/* Calculate signature block location */
672 	hiber_info->sig_offset = dl.d_partitions[1].p_offset +
673 	    dl.d_partitions[1].p_size -
674 	    sizeof(union hibernate_info)/hiber_info->secsize;
675 
676 	chunktable_size = HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize;
677 
678 	/* Stash kernel version information */
679 	bzero(&hiber_info->kernel_version, 128);
680 	bcopy(version, &hiber_info->kernel_version,
681 	    min(strlen(version), sizeof(hiber_info->kernel_version)-1));
682 
683 	if (suspend) {
684 		/* Allocate piglet region */
685 		if (uvm_pmr_alloc_piglet(&hiber_info->piglet_va,
686 		    &hiber_info->piglet_pa, HIBERNATE_CHUNK_SIZE*3,
687 		    HIBERNATE_CHUNK_SIZE)) {
688 			printf("Hibernate failed to allocate the piglet\n");
689 			return (1);
690 		}
691 		hiber_info->io_page = (void *)hiber_info->piglet_va;
692 
693 		/*
694 		 * Initialization of the hibernate IO function for drivers
695 		 * that need to do prep work (such as allocating memory or
696 		 * setting up data structures that cannot safely be done
697 		 * during suspend without causing side effects). There is
698 		 * a matching HIB_DONE call performed after the write is
699 		 * completed.
700 		 */
701 		if (hiber_info->io_func(hiber_info->device, 0,
702 		    (vaddr_t)NULL, 0, HIB_INIT, hiber_info->io_page))
703 			goto fail;
704 
705 	} else {
706 		/*
707 		 * Resuming kernels use a regular I/O page since we won't
708 		 * have access to the suspended kernel's piglet VA at this
709 		 * point. No need to free this I/O page as it will vanish
710 		 * as part of the resume.
711 		 */
712 		hiber_info->io_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
713 		if (!hiber_info->io_page)
714 			return (1);
715 	}
716 
717 
718 	if (get_hibernate_info_md(hiber_info))
719 		goto fail;
720 
721 	/* Calculate memory image location in swap */
722 	hiber_info->image_offset = dl.d_partitions[1].p_offset +
723 	    dl.d_partitions[1].p_size -
724 	    (hiber_info->image_size / hiber_info->secsize) -
725 	    sizeof(union hibernate_info)/hiber_info->secsize -
726 	    chunktable_size;
727 
728 	return (0);
729 fail:
730 	if (suspend)
731 		uvm_pmr_free_piglet(hiber_info->piglet_va,
732 		    HIBERNATE_CHUNK_SIZE * 3);
733 
734 	return (1);
735 }
736 
737 /*
738  * Allocate nitems*size bytes from the hiballoc area presently in use
739  */
740 void *
741 hibernate_zlib_alloc(void *unused, int nitems, int size)
742 {
743 	struct hibernate_zlib_state *hibernate_state;
744 
745 	hibernate_state =
746 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
747 
748 	return hib_alloc(&hibernate_state->hiballoc_arena, nitems*size);
749 }
750 
751 /*
752  * Free the memory pointed to by addr in the hiballoc area presently in
753  * use
754  */
755 void
756 hibernate_zlib_free(void *unused, void *addr)
757 {
758 	struct hibernate_zlib_state *hibernate_state;
759 
760 	hibernate_state =
761 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
762 
763 	hib_free(&hibernate_state->hiballoc_arena, addr);
764 }
765 
766 /*
767  * Gets the next RLE value from the image stream
768  */
769 int
770 hibernate_get_next_rle(void)
771 {
772 	int rle, i;
773 	struct hibernate_zlib_state *hibernate_state;
774 
775 	hibernate_state =
776 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
777 
778 	/* Read RLE code */
779 	hibernate_state->hib_stream.next_out = (char *)&rle;
780 	hibernate_state->hib_stream.avail_out = sizeof(rle);
781 
782 	i = inflate(&hibernate_state->hib_stream, Z_FULL_FLUSH);
783 	if (i != Z_OK && i != Z_STREAM_END) {
784 		/*
785 		 * XXX - this will likely reboot/hang most machines
786 		 *       since the console output buffer will be unmapped,
787 		 *       but there's not much else we can do here.
788 		 */
789 		panic("inflate rle error");
790 	}
791 
792 	/* Sanity check what RLE value we got */
793 	if (rle > HIBERNATE_CHUNK_SIZE/PAGE_SIZE || rle < 0)
794 		panic("invalid RLE code");
795 
796 	if (i == Z_STREAM_END)
797 		rle = -1;
798 
799 	return rle;
800 }
801 
802 /*
803  * Inflate next page of data from the image stream
804  */
805 int
806 hibernate_inflate_page(void)
807 {
808 	struct hibernate_zlib_state *hibernate_state;
809 	int i;
810 
811 	hibernate_state =
812 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
813 
814 	/* Set up the stream for inflate */
815 	hibernate_state->hib_stream.next_out = (char *)HIBERNATE_INFLATE_PAGE;
816 	hibernate_state->hib_stream.avail_out = PAGE_SIZE;
817 
818 	/* Process next block of data */
819 	i = inflate(&hibernate_state->hib_stream, Z_PARTIAL_FLUSH);
820 	if (i != Z_OK && i != Z_STREAM_END) {
821 		/*
822 		 * XXX - this will likely reboot/hang most machines
823 		 *       since the console output buffer will be unmapped,
824 		 *       but there's not much else we can do here.
825 		 */
826 		panic("inflate error");
827 	}
828 
829 	/* We should always have extracted a full page ... */
830 	if (hibernate_state->hib_stream.avail_out != 0) {
831 		/*
832 		 * XXX - this will likely reboot/hang most machines
833 		 *       since the console output buffer will be unmapped,
834 		 *       but there's not much else we can do here.
835 		 */
836 		panic("incomplete page");
837 	}
838 
839 	return (i == Z_STREAM_END);
840 }
841 
842 /*
843  * Inflate size bytes from src into dest, skipping any pages in
844  * [src..dest] that are special (see hibernate_inflate_skip)
845  *
846  * This function executes while using the resume-time stack
847  * and pmap, and therefore cannot use ddb/printf/etc. Doing so
848  * will likely hang or reset the machine since the console output buffer
849  * will be unmapped.
850  */
851 void
852 hibernate_inflate_region(union hibernate_info *hiber_info, paddr_t dest,
853     paddr_t src, size_t size)
854 {
855 	int end_stream = 0 ;
856 	struct hibernate_zlib_state *hibernate_state;
857 
858 	hibernate_state =
859 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
860 
861 	hibernate_state->hib_stream.next_in = (char *)src;
862 	hibernate_state->hib_stream.avail_in = size;
863 
864 	do {
865 		/* Flush cache and TLB */
866 		hibernate_flush();
867 
868 		/*
869 		 * Is this a special page? If yes, redirect the
870 		 * inflate output to a scratch page (eg, discard it)
871 		 */
872 		if (hibernate_inflate_skip(hiber_info, dest)) {
873 			hibernate_enter_resume_mapping(
874 			    HIBERNATE_INFLATE_PAGE,
875 			    HIBERNATE_INFLATE_PAGE, 0);
876 		} else {
877 			hibernate_enter_resume_mapping(
878 			    HIBERNATE_INFLATE_PAGE, dest, 0);
879 		}
880 
881 		hibernate_flush();
882 		end_stream = hibernate_inflate_page();
883 
884 		dest += PAGE_SIZE;
885 	} while (!end_stream);
886 }
887 
888 /*
889  * deflate from src into the I/O page, up to 'remaining' bytes
890  *
891  * Returns number of input bytes consumed, and may reset
892  * the 'remaining' parameter if not all the output space was consumed
893  * (this information is needed to know how much to write to disk
894  */
895 size_t
896 hibernate_deflate(union hibernate_info *hiber_info, paddr_t src,
897     size_t *remaining)
898 {
899 	vaddr_t hibernate_io_page = hiber_info->piglet_va + PAGE_SIZE;
900 	struct hibernate_zlib_state *hibernate_state;
901 
902 	hibernate_state =
903 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
904 
905 	/* Set up the stream for deflate */
906 	hibernate_state->hib_stream.next_in = (caddr_t)src;
907 	hibernate_state->hib_stream.avail_in = PAGE_SIZE - (src & PAGE_MASK);
908 	hibernate_state->hib_stream.next_out = (caddr_t)hibernate_io_page +
909 	    (PAGE_SIZE - *remaining);
910 	hibernate_state->hib_stream.avail_out = *remaining;
911 
912 	/* Process next block of data */
913 	if (deflate(&hibernate_state->hib_stream, Z_PARTIAL_FLUSH) != Z_OK)
914 		panic("hibernate zlib deflate error");
915 
916 	/* Update pointers and return number of bytes consumed */
917 	*remaining = hibernate_state->hib_stream.avail_out;
918 	return (PAGE_SIZE - (src & PAGE_MASK)) -
919 	    hibernate_state->hib_stream.avail_in;
920 }
921 
922 /*
923  * Write the hibernation information specified in hiber_info
924  * to the location in swap previously calculated (last block of
925  * swap), called the "signature block".
926  */
927 int
928 hibernate_write_signature(union hibernate_info *hiber_info)
929 {
930 	/* Write hibernate info to disk */
931 	return (hiber_info->io_func(hiber_info->device, hiber_info->sig_offset,
932 	    (vaddr_t)hiber_info, hiber_info->secsize, HIB_W,
933 	    hiber_info->io_page));
934 }
935 
936 /*
937  * Write the memory chunk table to the area in swap immediately
938  * preceding the signature block. The chunk table is stored
939  * in the piglet when this function is called.
940  */
941 int
942 hibernate_write_chunktable(union hibernate_info *hiber_info)
943 {
944 	struct hibernate_disk_chunk *chunks;
945 	vaddr_t hibernate_chunk_table_start;
946 	size_t hibernate_chunk_table_size;
947 	daddr_t chunkbase;
948 	int i;
949 
950 	hibernate_chunk_table_size = HIBERNATE_CHUNK_TABLE_SIZE;
951 
952 	chunkbase = hiber_info->sig_offset -
953 	    (hibernate_chunk_table_size / hiber_info->secsize);
954 
955 	hibernate_chunk_table_start = hiber_info->piglet_va +
956 	    HIBERNATE_CHUNK_SIZE;
957 
958 	chunks = (struct hibernate_disk_chunk *)(hiber_info->piglet_va +
959 	    HIBERNATE_CHUNK_SIZE);
960 
961 	/* Write chunk table */
962 	for (i = 0; i < hibernate_chunk_table_size; i += MAXPHYS) {
963 		if (hiber_info->io_func(hiber_info->device,
964 		    chunkbase + (i/hiber_info->secsize),
965 		    (vaddr_t)(hibernate_chunk_table_start + i),
966 		    MAXPHYS, HIB_W, hiber_info->io_page))
967 			return (1);
968 	}
969 
970 	return (0);
971 }
972 
973 /*
974  * Write an empty hiber_info to the swap signature block, which is
975  * guaranteed to not match any valid hiber_info.
976  */
977 int
978 hibernate_clear_signature(void)
979 {
980 	union hibernate_info blank_hiber_info;
981 	union hibernate_info hiber_info;
982 
983 	/* Zero out a blank hiber_info */
984 	bzero(&blank_hiber_info, sizeof(union hibernate_info));
985 
986 	/* Get the signature block location */
987 	if (get_hibernate_info(&hiber_info, 0))
988 		return (1);
989 
990 	/* Write (zeroed) hibernate info to disk */
991 #ifdef HIBERNATE_DEBUG
992 	printf("clearing hibernate signature block location: %lld\n",
993 		hiber_info.sig_offset - hiber_info.swap_offset);
994 #endif /* HIBERNATE_DEBUG */
995 	if (hibernate_block_io(&hiber_info,
996 	    hiber_info.sig_offset - hiber_info.swap_offset,
997 	    hiber_info.secsize, (vaddr_t)&blank_hiber_info, 1))
998 		printf("Warning: could not clear hibernate signature\n");
999 
1000 	return (0);
1001 }
1002 
1003 /*
1004  * Check chunk range overlap when calculating whether or not to copy a
1005  * compressed chunk to the piglet area before decompressing.
1006  *
1007  * returns zero if the ranges do not overlap, non-zero otherwise.
1008  */
1009 int
1010 hibernate_check_overlap(paddr_t r1s, paddr_t r1e, paddr_t r2s, paddr_t r2e)
1011 {
1012 	/* case A : end of r1 overlaps start of r2 */
1013 	if (r1s < r2s && r1e > r2s)
1014 		return (1);
1015 
1016 	/* case B : r1 entirely inside r2 */
1017 	if (r1s >= r2s && r1e <= r2e)
1018 		return (1);
1019 
1020 	/* case C : r2 entirely inside r1 */
1021 	if (r2s >= r1s && r2e <= r1e)
1022 		return (1);
1023 
1024 	/* case D : end of r2 overlaps start of r1 */
1025 	if (r2s < r1s && r2e > r1s)
1026 		return (1);
1027 
1028 	return (0);
1029 }
1030 
1031 /*
1032  * Compare two hibernate_infos to determine if they are the same (eg,
1033  * we should be performing a hibernate resume on this machine.
1034  * Not all fields are checked - just enough to verify that the machine
1035  * has the same memory configuration and kernel as the one that
1036  * wrote the signature previously.
1037  */
1038 int
1039 hibernate_compare_signature(union hibernate_info *mine,
1040     union hibernate_info *disk)
1041 {
1042 	u_int i;
1043 
1044 	if (mine->nranges != disk->nranges) {
1045 #ifdef HIBERNATE_DEBUG
1046 		printf("hibernate memory range count mismatch\n");
1047 #endif
1048 		return (1);
1049 	}
1050 
1051 	if (strcmp(mine->kernel_version, disk->kernel_version) != 0) {
1052 #ifdef HIBERNATE_DEBUG
1053 		printf("hibernate kernel version mismatch\n");
1054 #endif
1055 		return (1);
1056 	}
1057 
1058 	for (i = 0; i < mine->nranges; i++) {
1059 		if ((mine->ranges[i].base != disk->ranges[i].base) ||
1060 		    (mine->ranges[i].end != disk->ranges[i].end) ) {
1061 #ifdef HIBERNATE_DEBUG
1062 			printf("hib range %d mismatch [%p-%p != %p-%p]\n",
1063 				i, mine->ranges[i].base, mine->ranges[i].end,
1064 				disk->ranges[i].base, disk->ranges[i].end);
1065 #endif
1066 			return (1);
1067 		}
1068 	}
1069 
1070 	return (0);
1071 }
1072 
1073 /*
1074  * Transfers xfer_size bytes between the hibernate device specified in
1075  * hib_info at offset blkctr and the vaddr specified at dest.
1076  *
1077  * Separate offsets and pages are used to handle misaligned reads (reads
1078  * that span a page boundary).
1079  *
1080  * blkctr specifies a relative offset (relative to the start of swap),
1081  * not an absolute disk offset
1082  *
1083  */
1084 int
1085 hibernate_block_io(union hibernate_info *hib_info, daddr_t blkctr,
1086     size_t xfer_size, vaddr_t dest, int iswrite)
1087 {
1088 	struct buf *bp;
1089 	struct bdevsw *bdsw;
1090 	int error;
1091 
1092 	bp = geteblk(xfer_size);
1093 	bdsw = &bdevsw[major(hib_info->device)];
1094 
1095 	error = (*bdsw->d_open)(hib_info->device, FREAD, S_IFCHR, curproc);
1096 	if (error) {
1097 		printf("hibernate_block_io open failed\n");
1098 		return (1);
1099 	}
1100 
1101 	if (iswrite)
1102 		bcopy((caddr_t)dest, bp->b_data, xfer_size);
1103 
1104 	bp->b_bcount = xfer_size;
1105 	bp->b_blkno = blkctr;
1106 	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
1107 	SET(bp->b_flags, B_BUSY | (iswrite ? B_WRITE : B_READ) | B_RAW);
1108 	bp->b_dev = hib_info->device;
1109 	bp->b_cylinder = 0;
1110 	(*bdsw->d_strategy)(bp);
1111 
1112 	error = biowait(bp);
1113 	if (error) {
1114 		printf("hibernate_block_io biowait failed %d\n", error);
1115 		error = (*bdsw->d_close)(hib_info->device, 0, S_IFCHR,
1116 		    curproc);
1117 		if (error)
1118 			printf("hibernate_block_io error close failed\n");
1119 		return (1);
1120 	}
1121 
1122 	error = (*bdsw->d_close)(hib_info->device, FREAD, S_IFCHR, curproc);
1123 	if (error) {
1124 		printf("hibernate_block_io close failed\n");
1125 		return (1);
1126 	}
1127 
1128 	if (!iswrite)
1129 		bcopy(bp->b_data, (caddr_t)dest, xfer_size);
1130 
1131 	bp->b_flags |= B_INVAL;
1132 	brelse(bp);
1133 
1134 	return (0);
1135 }
1136 
1137 /*
1138  * Reads the signature block from swap, checks against the current machine's
1139  * information. If the information matches, perform a resume by reading the
1140  * saved image into the pig area, and unpacking.
1141  */
1142 void
1143 hibernate_resume(void)
1144 {
1145 	union hibernate_info hiber_info;
1146 	int s;
1147 
1148 	/* Get current running machine's hibernate info */
1149 	bzero(&hiber_info, sizeof(hiber_info));
1150 	if (get_hibernate_info(&hiber_info, 0))
1151 		return;
1152 
1153 	/* Read hibernate info from disk */
1154 	s = splbio();
1155 
1156 #ifdef HIBERNATE_DEBUG
1157 	printf("reading hibernate signature block location: %lld\n",
1158 		hiber_info.sig_offset - hiber_info.swap_offset);
1159 #endif /* HIBERNATE_DEBUG */
1160 
1161 	if (hibernate_block_io(&hiber_info,
1162 	    hiber_info.sig_offset - hiber_info.swap_offset,
1163 	    hiber_info.secsize, (vaddr_t)&disk_hiber_info, 0))
1164 		panic("error in hibernate read");
1165 
1166 	/* Check magic number */
1167 	if (disk_hiber_info.magic != HIBERNATE_MAGIC) {
1168 		splx(s);
1169 		return;
1170 	}
1171 
1172 	/*
1173 	 * We (possibly) found a hibernate signature. Clear signature first,
1174 	 * to prevent accidental resume or endless resume cycles later.
1175 	 */
1176 	if (hibernate_clear_signature()) {
1177 		splx(s);
1178 		return;
1179 	}
1180 
1181 	/*
1182 	 * If on-disk and in-memory hibernate signatures match,
1183 	 * this means we should do a resume from hibernate.
1184 	 */
1185 	if (hibernate_compare_signature(&hiber_info, &disk_hiber_info)) {
1186 		splx(s);
1187 		return;
1188 	}
1189 
1190 #ifdef MULTIPROCESSOR
1191 	hibernate_quiesce_cpus();
1192 #endif /* MULTIPROCESSOR */
1193 
1194 	printf("Unhibernating...\n");
1195 
1196 	/* Read the image from disk into the image (pig) area */
1197 	if (hibernate_read_image(&disk_hiber_info))
1198 		goto fail;
1199 
1200 	if (config_suspend(TAILQ_FIRST(&alldevs), DVACT_QUIESCE) != 0)
1201 		goto fail;
1202 
1203 	(void) splhigh();
1204 	hibernate_disable_intr_machdep();
1205 	cold = 1;
1206 
1207 	if (config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND) != 0) {
1208 		cold = 0;
1209 		hibernate_enable_intr_machdep();
1210 		goto fail;
1211 	}
1212 
1213 	pmap_kenter_pa(HIBERNATE_HIBALLOC_PAGE, HIBERNATE_HIBALLOC_PAGE,
1214 	    VM_PROT_ALL);
1215 	pmap_activate(curproc);
1216 
1217 	/* Switch stacks */
1218 	hibernate_switch_stack_machdep();
1219 
1220 	/*
1221 	 * Point of no return. Once we pass this point, only kernel code can
1222 	 * be accessed. No global variables or other kernel data structures
1223 	 * are guaranteed to be coherent after unpack starts.
1224 	 *
1225 	 * The image is now in high memory (pig area), we unpack from the pig
1226 	 * to the correct location in memory. We'll eventually end up copying
1227 	 * on top of ourself, but we are assured the kernel code here is the
1228 	 * same between the hibernated and resuming kernel, and we are running
1229 	 * on our own stack, so the overwrite is ok.
1230 	 */
1231 	hibernate_unpack_image(&disk_hiber_info);
1232 
1233 	/*
1234 	 * Resume the loaded kernel by jumping to the MD resume vector.
1235 	 * We won't be returning from this call.
1236 	 */
1237 	hibernate_resume_machdep();
1238 
1239 fail:
1240 	splx(s);
1241 	printf("Unable to resume hibernated image\n");
1242 }
1243 
1244 /*
1245  * Unpack image from pig area to original location by looping through the
1246  * list of output chunks in the order they should be restored (fchunks).
1247  */
1248 void
1249 hibernate_unpack_image(union hibernate_info *hiber_info)
1250 {
1251 	struct hibernate_disk_chunk *chunks;
1252 	union hibernate_info local_hiber_info;
1253 	paddr_t image_cur = global_pig_start;
1254 	short i, *fchunks;
1255 	char *pva = (char *)hiber_info->piglet_va;
1256 	struct hibernate_zlib_state *hibernate_state;
1257 
1258 	hibernate_state =
1259 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
1260 
1261 	/* Mask off based on arch-specific piglet page size */
1262 	pva = (char *)((paddr_t)pva & (PIGLET_PAGE_MASK));
1263 	fchunks = (short *)(pva + (4 * PAGE_SIZE));
1264 
1265 	chunks = (struct hibernate_disk_chunk *)(pva +  HIBERNATE_CHUNK_SIZE);
1266 
1267 	/* Can't use hiber_info that's passed in after this point */
1268 	bcopy(hiber_info, &local_hiber_info, sizeof(union hibernate_info));
1269 
1270 	hibernate_activate_resume_pt_machdep();
1271 
1272 	for (i = 0; i < local_hiber_info.chunk_ctr; i++) {
1273 		/* Reset zlib for inflate */
1274 		if (hibernate_zlib_reset(&local_hiber_info, 0) != Z_OK)
1275 			panic("hibernate failed to reset zlib for inflate");
1276 
1277 		hibernate_process_chunk(&local_hiber_info, &chunks[fchunks[i]],
1278 		    image_cur);
1279 
1280 		image_cur += chunks[fchunks[i]].compressed_size;
1281 
1282 	}
1283 }
1284 
1285 /*
1286  * Bounce a compressed image chunk to the piglet, entering mappings for the
1287  * copied pages as needed
1288  */
1289 void
1290 hibernate_copy_chunk_to_piglet(paddr_t img_cur, vaddr_t piglet, size_t size)
1291 {
1292 	size_t ct, ofs;
1293 	paddr_t src = img_cur;
1294 	vaddr_t dest = piglet;
1295 
1296 	/* Copy first partial page */
1297 	ct = (PAGE_SIZE) - (src & PAGE_MASK);
1298 	ofs = (src & PAGE_MASK);
1299 
1300 	if (ct < PAGE_SIZE) {
1301 		hibernate_enter_resume_mapping(HIBERNATE_INFLATE_PAGE,
1302 			(src - ofs), 0);
1303 		hibernate_flush();
1304 		bcopy((caddr_t)(HIBERNATE_INFLATE_PAGE + ofs), (caddr_t)dest, ct);
1305 		src += ct;
1306 		dest += ct;
1307 	}
1308 
1309 	/* Copy remaining pages */
1310 	while (src < size + img_cur) {
1311 		hibernate_enter_resume_mapping(HIBERNATE_INFLATE_PAGE, src, 0);
1312 		hibernate_flush();
1313 		ct = PAGE_SIZE;
1314 		bcopy((caddr_t)(HIBERNATE_INFLATE_PAGE), (caddr_t)dest, ct);
1315 		hibernate_flush();
1316 		src += ct;
1317 		dest += ct;
1318 	}
1319 }
1320 
1321 /*
1322  * Process a chunk by bouncing it to the piglet, followed by unpacking
1323  */
1324 void
1325 hibernate_process_chunk(union hibernate_info *hiber_info,
1326     struct hibernate_disk_chunk *chunk, paddr_t img_cur)
1327 {
1328 	char *pva = (char *)hiber_info->piglet_va;
1329 
1330 	hibernate_copy_chunk_to_piglet(img_cur,
1331 	 (vaddr_t)(pva + (HIBERNATE_CHUNK_SIZE * 2)), chunk->compressed_size);
1332 
1333 	hibernate_inflate_region(hiber_info, chunk->base,
1334 	    (vaddr_t)(pva + (HIBERNATE_CHUNK_SIZE * 2)),
1335 	    chunk->compressed_size);
1336 }
1337 
1338 /*
1339  * Write a compressed version of this machine's memory to disk, at the
1340  * precalculated swap offset:
1341  *
1342  * end of swap - signature block size - chunk table size - memory size
1343  *
1344  * The function begins by looping through each phys mem range, cutting each
1345  * one into MD sized chunks. These chunks are then compressed individually
1346  * and written out to disk, in phys mem order. Some chunks might compress
1347  * more than others, and for this reason, each chunk's size is recorded
1348  * in the chunk table, which is written to disk after the image has
1349  * properly been compressed and written (in hibernate_write_chunktable).
1350  *
1351  * When this function is called, the machine is nearly suspended - most
1352  * devices are quiesced/suspended, interrupts are off, and cold has
1353  * been set. This means that there can be no side effects once the
1354  * write has started, and the write function itself can also have no
1355  * side effects. This also means no printfs are permitted (since printf
1356  * has side effects.)
1357  */
1358 int
1359 hibernate_write_chunks(union hibernate_info *hiber_info)
1360 {
1361 	paddr_t range_base, range_end, inaddr, temp_inaddr;
1362 	size_t nblocks, out_remaining, used;
1363 	struct hibernate_disk_chunk *chunks;
1364 	vaddr_t hibernate_io_page = hiber_info->piglet_va + PAGE_SIZE;
1365 	daddr_t blkctr = hiber_info->image_offset, offset = 0;
1366 	int i;
1367 	struct hibernate_zlib_state *hibernate_state;
1368 
1369 	hibernate_state =
1370 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
1371 
1372 	hiber_info->chunk_ctr = 0;
1373 
1374 	/*
1375 	 * Allocate VA for the temp and copy page.
1376 	 *
1377 	 * These will become part of the suspended kernel and will
1378 	 * be freed in hibernate_free, upon resume.
1379 	 */
1380 	hibernate_temp_page = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any,
1381 	    &kp_none, &kd_nowait);
1382 	if (!hibernate_temp_page)
1383 		return (1);
1384 
1385 	hibernate_copy_page = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any,
1386 	    &kp_none, &kd_nowait);
1387 	if (!hibernate_copy_page)
1388 		return (1);
1389 
1390 	pmap_kenter_pa(hibernate_copy_page,
1391 	    (hiber_info->piglet_pa + 3*PAGE_SIZE), VM_PROT_ALL);
1392 
1393 	/* XXX - not needed on all archs */
1394 	pmap_activate(curproc);
1395 
1396 	chunks = (struct hibernate_disk_chunk *)(hiber_info->piglet_va +
1397 	    HIBERNATE_CHUNK_SIZE);
1398 
1399 	/* Calculate the chunk regions */
1400 	for (i = 0; i < hiber_info->nranges; i++) {
1401 		range_base = hiber_info->ranges[i].base;
1402 		range_end = hiber_info->ranges[i].end;
1403 
1404 		inaddr = range_base;
1405 
1406 		while (inaddr < range_end) {
1407 			chunks[hiber_info->chunk_ctr].base = inaddr;
1408 			if (inaddr + HIBERNATE_CHUNK_SIZE < range_end)
1409 				chunks[hiber_info->chunk_ctr].end = inaddr +
1410 				    HIBERNATE_CHUNK_SIZE;
1411 			else
1412 				chunks[hiber_info->chunk_ctr].end = range_end;
1413 
1414 			inaddr += HIBERNATE_CHUNK_SIZE;
1415 			hiber_info->chunk_ctr ++;
1416 		}
1417 	}
1418 
1419 	/* Compress and write the chunks in the chunktable */
1420 	for (i = 0; i < hiber_info->chunk_ctr; i++) {
1421 		range_base = chunks[i].base;
1422 		range_end = chunks[i].end;
1423 
1424 		chunks[i].offset = blkctr;
1425 
1426 		/* Reset zlib for deflate */
1427 		if (hibernate_zlib_reset(hiber_info, 1) != Z_OK)
1428 			return (1);
1429 
1430 		inaddr = range_base;
1431 
1432 		/*
1433 		 * For each range, loop through its phys mem region
1434 		 * and write out the chunks (the last chunk might be
1435 		 * smaller than the chunk size).
1436 		 */
1437 		while (inaddr < range_end) {
1438 			out_remaining = PAGE_SIZE;
1439 			while (out_remaining > 0 && inaddr < range_end) {
1440 
1441 				/*
1442 				 * Adjust for regions that are not evenly
1443 				 * divisible by PAGE_SIZE or overflowed
1444 				 * pages from the previous iteration.
1445 				 */
1446 				temp_inaddr = (inaddr & PAGE_MASK) +
1447 				    hibernate_copy_page;
1448 
1449 				/* Deflate from temp_inaddr to IO page */
1450 				if (inaddr != range_end) {
1451 					pmap_kenter_pa(hibernate_temp_page,
1452 					    inaddr & PMAP_PA_MASK, VM_PROT_ALL);
1453 
1454 					/* XXX - not needed on all archs */
1455 					pmap_activate(curproc);
1456 
1457 					bcopy((caddr_t)hibernate_temp_page,
1458 					    (caddr_t)hibernate_copy_page,
1459 					    PAGE_SIZE);
1460 					inaddr += hibernate_deflate(hiber_info,
1461 					    temp_inaddr, &out_remaining);
1462 				}
1463 
1464 				if (out_remaining == 0) {
1465 					/* Filled up the page */
1466 					nblocks =
1467 					    PAGE_SIZE / hiber_info->secsize;
1468 
1469 					if (hiber_info->io_func(
1470 					    hiber_info->device,
1471 					    blkctr, (vaddr_t)hibernate_io_page,
1472 					    PAGE_SIZE, HIB_W,
1473 					    hiber_info->io_page))
1474 						return (1);
1475 
1476 					blkctr += nblocks;
1477 				}
1478 			}
1479 		}
1480 
1481 		if (inaddr != range_end)
1482 			return (1);
1483 
1484 		/*
1485 		 * End of range. Round up to next secsize bytes
1486 		 * after finishing compress
1487 		 */
1488 		if (out_remaining == 0)
1489 			out_remaining = PAGE_SIZE;
1490 
1491 		/* Finish compress */
1492 		hibernate_state->hib_stream.next_in = (caddr_t)inaddr;
1493 		hibernate_state->hib_stream.avail_in = 0;
1494 		hibernate_state->hib_stream.next_out =
1495 		    (caddr_t)hibernate_io_page + (PAGE_SIZE - out_remaining);
1496 		hibernate_state->hib_stream.avail_out = out_remaining;
1497 
1498 		if (deflate(&hibernate_state->hib_stream, Z_FINISH) !=
1499 		    Z_STREAM_END)
1500 			return (1);
1501 
1502 		out_remaining = hibernate_state->hib_stream.avail_out;
1503 
1504 		used = PAGE_SIZE - out_remaining;
1505 		nblocks = used / hiber_info->secsize;
1506 
1507 		/* Round up to next block if needed */
1508 		if (used % hiber_info->secsize != 0)
1509 			nblocks ++;
1510 
1511 		/* Write final block(s) for this chunk */
1512 		if (hiber_info->io_func(hiber_info->device, blkctr,
1513 		    (vaddr_t)hibernate_io_page, nblocks*hiber_info->secsize,
1514 		    HIB_W, hiber_info->io_page))
1515 			return (1);
1516 
1517 		blkctr += nblocks;
1518 
1519 		offset = blkctr;
1520 		chunks[i].compressed_size = (offset - chunks[i].offset) *
1521 		    hiber_info->secsize;
1522 	}
1523 
1524 	return (0);
1525 }
1526 
1527 /*
1528  * Reset the zlib stream state and allocate a new hiballoc area for either
1529  * inflate or deflate. This function is called once for each hibernate chunk.
1530  * Calling hiballoc_init multiple times is acceptable since the memory it is
1531  * provided is unmanaged memory (stolen). We use the memory provided to us
1532  * by the piglet allocated via the supplied hiber_info.
1533  */
1534 int
1535 hibernate_zlib_reset(union hibernate_info *hiber_info, int deflate)
1536 {
1537 	vaddr_t hibernate_zlib_start;
1538 	size_t hibernate_zlib_size;
1539 	char *pva = (char *)hiber_info->piglet_va;
1540 	struct hibernate_zlib_state *hibernate_state;
1541 
1542 	hibernate_state =
1543 	    (struct hibernate_zlib_state *)HIBERNATE_HIBALLOC_PAGE;
1544 
1545 	if(!deflate)
1546 		pva = (char *)((paddr_t)pva & (PIGLET_PAGE_MASK));
1547 
1548 	hibernate_zlib_start = (vaddr_t)(pva + (28 * PAGE_SIZE));
1549 	hibernate_zlib_size = 80 * PAGE_SIZE;
1550 
1551 	bzero((caddr_t)hibernate_zlib_start, hibernate_zlib_size);
1552 	bzero((caddr_t)hibernate_state, PAGE_SIZE);
1553 
1554 	/* Set up stream structure */
1555 	hibernate_state->hib_stream.zalloc = (alloc_func)hibernate_zlib_alloc;
1556 	hibernate_state->hib_stream.zfree = (free_func)hibernate_zlib_free;
1557 
1558 	/* Initialize the hiballoc arena for zlib allocs/frees */
1559 	hiballoc_init(&hibernate_state->hiballoc_arena,
1560 	    (caddr_t)hibernate_zlib_start, hibernate_zlib_size);
1561 
1562 	if (deflate) {
1563 		return deflateInit(&hibernate_state->hib_stream,
1564 		    Z_BEST_SPEED);
1565 	} else
1566 		return inflateInit(&hibernate_state->hib_stream);
1567 }
1568 
1569 /*
1570  * Reads the hibernated memory image from disk, whose location and
1571  * size are recorded in hiber_info. Begin by reading the persisted
1572  * chunk table, which records the original chunk placement location
1573  * and compressed size for each. Next, allocate a pig region of
1574  * sufficient size to hold the compressed image. Next, read the
1575  * chunks into the pig area (calling hibernate_read_chunks to do this),
1576  * and finally, if all of the above succeeds, clear the hibernate signature.
1577  * The function will then return to hibernate_resume, which will proceed
1578  * to unpack the pig image to the correct place in memory.
1579  */
1580 int
1581 hibernate_read_image(union hibernate_info *hiber_info)
1582 {
1583 	size_t compressed_size, disk_size, chunktable_size, pig_sz;
1584 	paddr_t image_start, image_end, pig_start, pig_end;
1585 	struct hibernate_disk_chunk *chunks;
1586 	daddr_t blkctr;
1587 	vaddr_t chunktable = (vaddr_t)NULL;
1588 	paddr_t piglet_chunktable = hiber_info->piglet_pa +
1589 	    HIBERNATE_CHUNK_SIZE;
1590 	int i;
1591 
1592 	pmap_activate(curproc);
1593 
1594 	/* Calculate total chunk table size in disk blocks */
1595 	chunktable_size = HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize;
1596 
1597 	blkctr = hiber_info->sig_offset - chunktable_size -
1598 			hiber_info->swap_offset;
1599 
1600 	chunktable = (vaddr_t)km_alloc(HIBERNATE_CHUNK_TABLE_SIZE, &kv_any,
1601 	    &kp_none, &kd_nowait);
1602 
1603 	if (!chunktable)
1604 		return (1);
1605 
1606 	/* Read the chunktable from disk into the piglet chunktable */
1607 	for (i = 0; i < HIBERNATE_CHUNK_TABLE_SIZE;
1608 	    i += PAGE_SIZE, blkctr += PAGE_SIZE/hiber_info->secsize) {
1609 		pmap_kenter_pa(chunktable + i, piglet_chunktable + i,
1610 		    VM_PROT_ALL);
1611 		pmap_update(pmap_kernel());
1612 		hibernate_block_io(hiber_info, blkctr, PAGE_SIZE,
1613 		    chunktable + i, 0);
1614 	}
1615 
1616 	blkctr = hiber_info->image_offset;
1617 	compressed_size = 0;
1618 
1619 	chunks = (struct hibernate_disk_chunk *)chunktable;
1620 
1621 	for (i = 0; i < hiber_info->chunk_ctr; i++)
1622 		compressed_size += chunks[i].compressed_size;
1623 
1624 	disk_size = compressed_size;
1625 
1626 	/* Allocate the pig area */
1627 	pig_sz = compressed_size + HIBERNATE_CHUNK_SIZE;
1628 	if (uvm_pmr_alloc_pig(&pig_start, pig_sz) == ENOMEM)
1629 		return (1);
1630 
1631 	pig_end = pig_start + pig_sz;
1632 
1633 	/* Calculate image extents. Pig image must end on a chunk boundary. */
1634 	image_end = pig_end & ~(HIBERNATE_CHUNK_SIZE - 1);
1635 	image_start = pig_start;
1636 
1637 	image_start = image_end - disk_size;
1638 
1639 	hibernate_read_chunks(hiber_info, image_start, image_end, disk_size,
1640 	    chunks);
1641 
1642 	pmap_kremove(chunktable, PAGE_SIZE);
1643 	pmap_update(pmap_kernel());
1644 
1645 	/* Prepare the resume time pmap/page table */
1646 	hibernate_populate_resume_pt(hiber_info, image_start, image_end);
1647 
1648 	return (0);
1649 }
1650 
1651 /*
1652  * Read the hibernated memory chunks from disk (chunk information at this
1653  * point is stored in the piglet) into the pig area specified by
1654  * [pig_start .. pig_end]. Order the chunks so that the final chunk is the
1655  * only chunk with overlap possibilities.
1656  */
1657 int
1658 hibernate_read_chunks(union hibernate_info *hib_info, paddr_t pig_start,
1659     paddr_t pig_end, size_t image_compr_size,
1660     struct hibernate_disk_chunk *chunks)
1661 {
1662 	paddr_t img_index, img_cur, r1s, r1e, r2s, r2e;
1663 	paddr_t copy_start, copy_end, piglet_cur;
1664 	paddr_t piglet_base = hib_info->piglet_pa;
1665 	paddr_t piglet_end = piglet_base + HIBERNATE_CHUNK_SIZE;
1666 	daddr_t blkctr;
1667 	size_t processed, compressed_size, read_size;
1668 	int overlap, found, nchunks, nochunks = 0, nfchunks = 0, npchunks = 0;
1669 	short *ochunks, *pchunks, *fchunks, i, j;
1670 	vaddr_t tempva = (vaddr_t)NULL, hibernate_fchunk_area = (vaddr_t)NULL;
1671 
1672 	global_pig_start = pig_start;
1673 
1674 	/* XXX - dont need this on all archs */
1675 	pmap_activate(curproc);
1676 
1677 	/*
1678 	 * These mappings go into the resuming kernel's page table, and are
1679 	 * used only during image read. They dissappear from existence
1680 	 * when the suspended kernel is unpacked on top of us.
1681 	 */
1682 	tempva = (vaddr_t)km_alloc(2*PAGE_SIZE, &kv_any, &kp_none, &kd_nowait);
1683 	if (!tempva)
1684 		return (1);
1685 	hibernate_fchunk_area = (vaddr_t)km_alloc(24*PAGE_SIZE, &kv_any,
1686 	    &kp_none, &kd_nowait);
1687 	if (!hibernate_fchunk_area)
1688 		return (1);
1689 
1690 	/* Final output chunk ordering VA */
1691 	fchunks = (short *)hibernate_fchunk_area;
1692 
1693 	/* Piglet chunk ordering VA */
1694 	pchunks = (short *)(hibernate_fchunk_area + (8*PAGE_SIZE));
1695 
1696 	/* Final chunk ordering VA */
1697 	ochunks = (short *)(hibernate_fchunk_area + (16*PAGE_SIZE));
1698 
1699 	/* Map the chunk ordering region */
1700 	for(i=0; i<24 ; i++) {
1701 		pmap_kenter_pa(hibernate_fchunk_area + (i*PAGE_SIZE),
1702 			piglet_base + ((4+i)*PAGE_SIZE), VM_PROT_ALL);
1703 		pmap_update(pmap_kernel());
1704 	}
1705 
1706 	nchunks = hib_info->chunk_ctr;
1707 
1708 	/* Initially start all chunks as unplaced */
1709 	for (i = 0; i < nchunks; i++)
1710 		chunks[i].flags = 0;
1711 
1712 	/*
1713 	 * Search the list for chunks that are outside the pig area. These
1714 	 * can be placed first in the final output list.
1715 	 */
1716 	for (i = 0; i < nchunks; i++) {
1717 		if (chunks[i].end <= pig_start || chunks[i].base >= pig_end) {
1718 			ochunks[nochunks] = i;
1719 			fchunks[nfchunks] = i;
1720 			nochunks++;
1721 			nfchunks++;
1722 			chunks[i].flags |= HIBERNATE_CHUNK_USED;
1723 		}
1724 	}
1725 
1726 	/*
1727 	 * Walk the ordering, place the chunks in ascending memory order.
1728 	 * Conflicts might arise, these are handled next.
1729 	 */
1730 	do {
1731 		img_index = -1;
1732 		found = 0;
1733 		j = -1;
1734 		for (i = 0; i < nchunks; i++)
1735 			if (chunks[i].base < img_index &&
1736 			    chunks[i].flags == 0 ) {
1737 				j = i;
1738 				img_index = chunks[i].base;
1739 			}
1740 
1741 		if (j != -1) {
1742 			found = 1;
1743 			ochunks[nochunks] = j;
1744 			nochunks++;
1745 			chunks[j].flags |= HIBERNATE_CHUNK_PLACED;
1746 		}
1747 	} while (found);
1748 
1749 	img_index = pig_start;
1750 
1751 	/*
1752 	 * Identify chunk output conflicts (chunks whose pig load area
1753 	 * corresponds to their original memory placement location)
1754 	 */
1755 	for (i = 0; i < nochunks ; i++) {
1756 		overlap = 0;
1757 		r1s = img_index;
1758 		r1e = img_index + chunks[ochunks[i]].compressed_size;
1759 		r2s = chunks[ochunks[i]].base;
1760 		r2e = chunks[ochunks[i]].end;
1761 
1762 		overlap = hibernate_check_overlap(r1s, r1e, r2s, r2e);
1763 		if (overlap)
1764 			chunks[ochunks[i]].flags |= HIBERNATE_CHUNK_CONFLICT;
1765 		img_index += chunks[ochunks[i]].compressed_size;
1766 	}
1767 
1768 	/*
1769 	 * Prepare the final output chunk list. Calculate an output
1770 	 * inflate strategy for overlapping chunks if needed.
1771 	 */
1772 	img_index = pig_start;
1773 	for (i = 0; i < nochunks ; i++) {
1774 		/*
1775 		 * If a conflict is detected, consume enough compressed
1776 		 * output chunks to fill the piglet
1777 		 */
1778 		if (chunks[ochunks[i]].flags & HIBERNATE_CHUNK_CONFLICT) {
1779 			copy_start = piglet_base;
1780 			copy_end = piglet_end;
1781 			piglet_cur = piglet_base;
1782 			npchunks = 0;
1783 			j = i;
1784 
1785 			while (copy_start < copy_end && j < nochunks) {
1786 				piglet_cur +=
1787 				    chunks[ochunks[j]].compressed_size;
1788 				pchunks[npchunks] = ochunks[j];
1789 				npchunks++;
1790 				copy_start +=
1791 				    chunks[ochunks[j]].compressed_size;
1792 				img_index += chunks[ochunks[j]].compressed_size;
1793 				i++;
1794 				j++;
1795 			}
1796 
1797 			piglet_cur = piglet_base;
1798 			for (j = 0; j < npchunks; j++) {
1799 				piglet_cur +=
1800 				    chunks[pchunks[j]].compressed_size;
1801 				fchunks[nfchunks] = pchunks[j];
1802 				chunks[pchunks[j]].flags |=
1803 				    HIBERNATE_CHUNK_USED;
1804 				nfchunks++;
1805 			}
1806 		} else {
1807 			/*
1808 			 * No conflict, chunk can be added without copying
1809 			 */
1810 			if ((chunks[ochunks[i]].flags &
1811 			    HIBERNATE_CHUNK_USED) == 0) {
1812 				fchunks[nfchunks] = ochunks[i];
1813 				chunks[ochunks[i]].flags |=
1814 				    HIBERNATE_CHUNK_USED;
1815 				nfchunks++;
1816 			}
1817 			img_index += chunks[ochunks[i]].compressed_size;
1818 		}
1819 	}
1820 
1821 	img_index = pig_start;
1822 	for (i = 0; i < nfchunks; i++) {
1823 		piglet_cur = piglet_base;
1824 		img_index += chunks[fchunks[i]].compressed_size;
1825 	}
1826 
1827 	img_cur = pig_start;
1828 
1829 	for (i = 0; i < nfchunks; i++) {
1830 		blkctr = chunks[fchunks[i]].offset - hib_info->swap_offset;
1831 		processed = 0;
1832 		compressed_size = chunks[fchunks[i]].compressed_size;
1833 
1834 		while (processed < compressed_size) {
1835 			pmap_kenter_pa(tempva, img_cur, VM_PROT_ALL);
1836 			pmap_kenter_pa(tempva + PAGE_SIZE, img_cur+PAGE_SIZE,
1837 			    VM_PROT_ALL);
1838 			pmap_update(pmap_kernel());
1839 
1840 			if (compressed_size - processed >= PAGE_SIZE)
1841 				read_size = PAGE_SIZE;
1842 			else
1843 				read_size = compressed_size - processed;
1844 
1845 			hibernate_block_io(hib_info, blkctr, read_size,
1846 			    tempva + (img_cur & PAGE_MASK), 0);
1847 
1848 			blkctr += (read_size / hib_info->secsize);
1849 
1850 			hibernate_flush();
1851 			pmap_kremove(tempva, PAGE_SIZE);
1852 			pmap_kremove(tempva + PAGE_SIZE, PAGE_SIZE);
1853 			processed += read_size;
1854 			img_cur += read_size;
1855 		}
1856 	}
1857 
1858 	pmap_kremove(hibernate_fchunk_area, PAGE_SIZE);
1859 	pmap_kremove((vaddr_t)pchunks, PAGE_SIZE);
1860 	pmap_kremove((vaddr_t)fchunks, PAGE_SIZE);
1861 	pmap_update(pmap_kernel());
1862 
1863 	return (0);
1864 }
1865 
1866 /*
1867  * Hibernating a machine comprises the following operations:
1868  *  1. Calculating this machine's hibernate_info information
1869  *  2. Allocating a piglet and saving the piglet's physaddr
1870  *  3. Calculating the memory chunks
1871  *  4. Writing the compressed chunks to disk
1872  *  5. Writing the chunk table
1873  *  6. Writing the signature block (hibernate_info)
1874  *
1875  * On most architectures, the function calling hibernate_suspend would
1876  * then power off the machine using some MD-specific implementation.
1877  */
1878 int
1879 hibernate_suspend(void)
1880 {
1881 	union hibernate_info hib_info;
1882 	size_t swap_size;
1883 
1884 	/*
1885 	 * Calculate memory ranges, swap offsets, etc.
1886 	 * This also allocates a piglet whose physaddr is stored in
1887 	 * hib_info->piglet_pa and vaddr stored in hib_info->piglet_va
1888 	 */
1889 	if (get_hibernate_info(&hib_info, 1))
1890 		return (1);
1891 
1892 	swap_size = hib_info.image_size + hib_info.secsize +
1893 		HIBERNATE_CHUNK_TABLE_SIZE;
1894 
1895 	if (uvm_swap_check_range(hib_info.device, swap_size)) {
1896 		printf("insufficient swap space for hibernate\n");
1897 		return (1);
1898 	}
1899 
1900 	pmap_kenter_pa(HIBERNATE_HIBALLOC_PAGE, HIBERNATE_HIBALLOC_PAGE,
1901 		VM_PROT_ALL);
1902 	pmap_activate(curproc);
1903 
1904 	/* Stash the piglet VA so we can free it in the resuming kernel */
1905 	global_piglet_va = hib_info.piglet_va;
1906 
1907 	if (hibernate_write_chunks(&hib_info))
1908 		return (1);
1909 
1910 	if (hibernate_write_chunktable(&hib_info))
1911 		return (1);
1912 
1913 	if (hibernate_write_signature(&hib_info))
1914 		return (1);
1915 
1916 	/* Allow the disk to settle */
1917 	delay(500000);
1918 
1919 	/*
1920 	 * Give the device-specific I/O function a notification that we're
1921 	 * done, and that it can clean up or shutdown as needed.
1922 	 */
1923 	hib_info.io_func(hib_info.device, 0, (vaddr_t)NULL, 0,
1924 	    HIB_DONE, hib_info.io_page);
1925 
1926 	return (0);
1927 }
1928 
1929 /*
1930  * Free items allocated by hibernate_suspend()
1931  */
1932 void
1933 hibernate_free(void)
1934 {
1935 	if (global_piglet_va)
1936 		uvm_pmr_free_piglet(global_piglet_va,
1937 		    3*HIBERNATE_CHUNK_SIZE);
1938 
1939 	if (hibernate_copy_page)
1940 		pmap_kremove(hibernate_copy_page, PAGE_SIZE);
1941 	if (hibernate_temp_page)
1942 		pmap_kremove(hibernate_temp_page, PAGE_SIZE);
1943 
1944 	pmap_update(pmap_kernel());
1945 
1946 	if (hibernate_copy_page)
1947 		km_free((void *)hibernate_copy_page, PAGE_SIZE,
1948 		    &kv_any, &kp_none);
1949 	if (hibernate_temp_page)
1950 		km_free((void *)hibernate_temp_page, PAGE_SIZE,
1951 		    &kv_any, &kp_none);
1952 
1953 	global_piglet_va = 0;
1954 	hibernate_copy_page = 0;
1955 	hibernate_temp_page = 0;
1956 }
1957