]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOHibernateRestoreKernel.c
xnu-3789.51.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IOHibernateRestoreKernel.c
1 /*
2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <stdint.h>
30 #include <mach/mach_types.h>
31 #include <mach/vm_param.h>
32 #include <IOKit/IOHibernatePrivate.h>
33 #include <IOKit/IOLib.h>
34 #include <pexpert/boot.h>
35 #include <libkern/libkern.h>
36
37 #include <vm/WKdm_new.h>
38 #include "IOHibernateInternal.h"
39
40 #include <machine/pal_hibernate.h>
41
42 /*
43 This code is linked into the kernel but part of the "__HIB" section, which means
44 its used by code running in the special context of restoring the kernel text and data
45 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
46 it calls or references needs to be careful to only touch memory also in the "__HIB" section.
47 */
48
49 uint32_t gIOHibernateState;
50
51 uint32_t gIOHibernateDebugFlags;
52
53 static IOHibernateImageHeader _hibernateHeader;
54 IOHibernateImageHeader * gIOHibernateCurrentHeader = &_hibernateHeader;
55
56 ppnum_t gIOHibernateHandoffPages[64];
57 uint32_t gIOHibernateHandoffPageCount = sizeof(gIOHibernateHandoffPages)
58 / sizeof(gIOHibernateHandoffPages[0]);
59
60 #if CONFIG_DEBUG
61 void hibprintf(const char *fmt, ...);
62 #else
63 #define hibprintf(x...)
64 #endif
65
66
67 #if CONFIG_SLEEP
68 #if defined(__i386__) || defined(__x86_64__)
69 extern void acpi_wake_prot_entry(void);
70 #endif
71 #endif
72
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
74
75 #if defined(__i386__) || defined(__x86_64__)
76
77 #define rdtsc(lo,hi) \
78 __asm__ volatile("lfence; rdtsc; lfence" : "=a" (lo), "=d" (hi))
79
80 static inline uint64_t rdtsc64(void)
81 {
82 uint64_t lo, hi;
83 rdtsc(lo, hi);
84 return ((hi) << 32) | (lo);
85 }
86
87 #else
88
89 static inline uint64_t rdtsc64(void)
90 {
91 return (0);
92 }
93
94 #endif /* defined(__i386__) || defined(__x86_64__) */
95
96 #if defined(__i386__) || defined(__x86_64__)
97
98 #define DBGLOG 1
99
100 #include <architecture/i386/pio.h>
101
102 /* standard port addresses */
103 enum {
104 COM1_PORT_ADDR = 0x3f8,
105 COM2_PORT_ADDR = 0x2f8
106 };
107
108 /* UART register offsets */
109 enum {
110 UART_RBR = 0, /* receive buffer Register (R) */
111 UART_THR = 0, /* transmit holding register (W) */
112 UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */
113 UART_IER = 1, /* interrupt enable register */
114 UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */
115 UART_IIR = 2, /* interrupt ident register (R) */
116 UART_FCR = 2, /* fifo control register (W) */
117 UART_LCR = 3, /* line control register */
118 UART_MCR = 4, /* modem control register */
119 UART_LSR = 5, /* line status register */
120 UART_MSR = 6, /* modem status register */
121 UART_SCR = 7 /* scratch register */
122 };
123
124 enum {
125 UART_LCR_8BITS = 0x03,
126 UART_LCR_DLAB = 0x80
127 };
128
129 enum {
130 UART_MCR_DTR = 0x01,
131 UART_MCR_RTS = 0x02,
132 UART_MCR_OUT1 = 0x04,
133 UART_MCR_OUT2 = 0x08,
134 UART_MCR_LOOP = 0x10
135 };
136
137 enum {
138 UART_LSR_DR = 0x01,
139 UART_LSR_OE = 0x02,
140 UART_LSR_PE = 0x04,
141 UART_LSR_FE = 0x08,
142 UART_LSR_THRE = 0x20
143 };
144
145 static void uart_putc(char c)
146 {
147 while (!(inb(COM1_PORT_ADDR + UART_LSR) & UART_LSR_THRE))
148 {}
149 outb(COM1_PORT_ADDR + UART_THR, c);
150 }
151
152 static int debug_probe( void )
153 {
154 /* Verify that the Scratch Register is accessible */
155 outb(COM1_PORT_ADDR + UART_SCR, 0x5a);
156 if (inb(COM1_PORT_ADDR + UART_SCR) != 0x5a) return false;
157 outb(COM1_PORT_ADDR + UART_SCR, 0xa5);
158 if (inb(COM1_PORT_ADDR + UART_SCR) != 0xa5) return false;
159 uart_putc('\n');
160 return true;
161 }
162
163 static void uart_puthex(uint64_t num)
164 {
165 int bit;
166 char c;
167 bool leading = true;
168
169 for (bit = 60; bit >= 0; bit -= 4)
170 {
171 c = 0xf & (num >> bit);
172 if (c)
173 leading = false;
174 else if (leading && bit)
175 continue;
176 if (c <= 9)
177 c += '0';
178 else
179 c+= 'a' - 10;
180 uart_putc(c);
181 }
182 }
183
184 static void debug_code(uint32_t code, uint64_t value)
185 {
186 int bit;
187 char c;
188
189 if (!(kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags))
190 return;
191
192 for (bit = 24; bit >= 0; bit -= 8)
193 {
194 c = 0xFF & (code >> bit);
195 if (c)
196 uart_putc(c);
197 }
198 uart_putc('=');
199 uart_puthex(value);
200 uart_putc('\n');
201 uart_putc('\r');
202 }
203
204 #endif /* defined(__i386__) || defined(__x86_64__) */
205
206 #if !defined(DBGLOG)
207 #define debug_probe() (false)
208 #define debug_code(c, v) {}
209 #endif
210
211 enum
212 {
213 kIOHibernateRestoreCodeImageStart = 'imgS',
214 kIOHibernateRestoreCodeImageEnd = 'imgE',
215 kIOHibernateRestoreCodePageIndexStart = 'pgiS',
216 kIOHibernateRestoreCodePageIndexEnd = 'pgiE',
217 kIOHibernateRestoreCodeMapStart = 'mapS',
218 kIOHibernateRestoreCodeMapEnd = 'mapE',
219 kIOHibernateRestoreCodeWakeMapSize = 'wkms',
220 kIOHibernateRestoreCodeConflictPage = 'cfpg',
221 kIOHibernateRestoreCodeConflictSource = 'cfsr',
222 kIOHibernateRestoreCodeNoMemory = 'nomm',
223 kIOHibernateRestoreCodeTag = 'tag ',
224 kIOHibernateRestoreCodeSignature = 'sign',
225 kIOHibernateRestoreCodeMapVirt = 'mapV',
226 kIOHibernateRestoreCodeHandoffPages = 'hand',
227 kIOHibernateRestoreCodeHandoffCount = 'hndc',
228 };
229
230 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
231
232
233 static void fatal(void)
234 {
235 #if defined(__i386__) || defined(__x86_64__)
236 outb(0xcf9, 6);
237 #else
238 while (true) {}
239 #endif
240 }
241
242 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
243
244 uint32_t
245 hibernate_sum_page(uint8_t *buf, uint32_t ppnum)
246 {
247 return (((uint32_t *)buf)[((PAGE_SIZE >> 2) - 1) & ppnum]);
248 }
249
250 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
251
252 static hibernate_bitmap_t *
253 hibernate_page_bitmap(hibernate_page_list_t * list, uint32_t page)
254 {
255 uint32_t bank;
256 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
257
258 for (bank = 0; bank < list->bank_count; bank++)
259 {
260 if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
261 break;
262 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
263 }
264 if (bank == list->bank_count)
265 bitmap = NULL;
266
267 return (bitmap);
268 }
269
270 hibernate_bitmap_t *
271 hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * pPage)
272 {
273 uint32_t bank, page = *pPage;
274 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
275
276 for (bank = 0; bank < list->bank_count; bank++)
277 {
278 if (page <= bitmap->first_page)
279 {
280 *pPage = bitmap->first_page;
281 break;
282 }
283 if (page <= bitmap->last_page)
284 break;
285 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
286 }
287 if (bank == list->bank_count)
288 bitmap = NULL;
289
290 return (bitmap);
291 }
292
293 void
294 hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page)
295 {
296 hibernate_bitmap_t * bitmap;
297
298 bitmap = hibernate_page_bitmap(list, page);
299 if (bitmap)
300 {
301 page -= bitmap->first_page;
302 if (set)
303 bitmap->bitmap[page >> 5] |= (0x80000000 >> (page & 31));
304 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
305 else
306 bitmap->bitmap[page >> 5] &= ~(0x80000000 >> (page & 31));
307 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
308 }
309 }
310
311 boolean_t
312 hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page)
313 {
314 boolean_t result = TRUE;
315 hibernate_bitmap_t * bitmap;
316
317 bitmap = hibernate_page_bitmap(list, page);
318 if (bitmap)
319 {
320 page -= bitmap->first_page;
321 result = (0 != (bitmap->bitmap[page >> 5] & (0x80000000 >> (page & 31))));
322 }
323 return (result);
324 }
325
326 // count bits clear or set (set == TRUE) starting at page.
327 uint32_t
328 hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page)
329 {
330 uint32_t index, bit, bits;
331 uint32_t count;
332
333 count = 0;
334
335 index = (page - bitmap->first_page) >> 5;
336 bit = (page - bitmap->first_page) & 31;
337
338 bits = bitmap->bitmap[index];
339 if (set)
340 bits = ~bits;
341 bits = (bits << bit);
342 if (bits)
343 count += __builtin_clz(bits);
344 else
345 {
346 count += 32 - bit;
347 while (++index < bitmap->bitmapwords)
348 {
349 bits = bitmap->bitmap[index];
350 if (set)
351 bits = ~bits;
352 if (bits)
353 {
354 count += __builtin_clz(bits);
355 break;
356 }
357 count += 32;
358 }
359 }
360
361 if ((page + count) > (bitmap->last_page + 1)) count = (bitmap->last_page + 1) - page;
362
363 return (count);
364 }
365
366 static ppnum_t
367 hibernate_page_list_grab(hibernate_page_list_t * list, uint32_t * pNextFree)
368 {
369 uint32_t nextFree = *pNextFree;
370 uint32_t nextFreeInBank;
371 hibernate_bitmap_t * bitmap;
372
373 nextFreeInBank = nextFree + 1;
374 while ((bitmap = hibernate_page_bitmap_pin(list, &nextFreeInBank)))
375 {
376 nextFreeInBank += hibernate_page_bitmap_count(bitmap, FALSE, nextFreeInBank);
377 if (nextFreeInBank <= bitmap->last_page)
378 {
379 *pNextFree = nextFreeInBank;
380 break;
381 }
382 }
383
384 if (!bitmap)
385 {
386 debug_code(kIOHibernateRestoreCodeNoMemory, nextFree);
387 fatal();
388 nextFree = 0;
389 }
390
391 return (nextFree);
392 }
393
394 static uint32_t
395 store_one_page(uint32_t procFlags, uint32_t * src, uint32_t compressedSize,
396 uint32_t * buffer, uint32_t ppnum)
397 {
398 uint64_t dst = ptoa_64(ppnum);
399 uint8_t scratch[WKdm_SCRATCH_BUF_SIZE_INTERNAL] __attribute__ ((aligned (16)));
400
401 if (compressedSize != PAGE_SIZE)
402 {
403 dst = pal_hib_map(DEST_COPY_AREA, dst);
404 if (compressedSize != 4) WKdm_decompress_new((WK_word*) src, (WK_word*)(uintptr_t)dst, (WK_word*) &scratch[0], compressedSize);
405 else
406 {
407 size_t i;
408 uint32_t s, *d;
409
410 s = *src;
411 d = (uint32_t *)(uintptr_t)dst;
412 if (!s) bzero((void *) dst, PAGE_SIZE);
413 else for (i = 0; i < (PAGE_SIZE / sizeof(int32_t)); i++) *d++ = s;
414 }
415 }
416 else
417 {
418 dst = hibernate_restore_phys_page((uint64_t) (uintptr_t) src, dst, PAGE_SIZE, procFlags);
419 }
420
421 return hibernate_sum_page((uint8_t *)(uintptr_t)dst, ppnum);
422 }
423
424 long
425 hibernate_kernel_entrypoint(uint32_t p1,
426 uint32_t p2, uint32_t p3, uint32_t p4)
427 {
428 uint64_t headerPhys;
429 uint64_t mapPhys;
430 uint64_t srcPhys;
431 uint64_t imageReadPhys;
432 uint64_t pageIndexPhys;
433 uint32_t * pageIndexSource;
434 hibernate_page_list_t * map;
435 uint32_t stage;
436 uint32_t count;
437 uint32_t ppnum;
438 uint32_t page;
439 uint32_t conflictCount;
440 uint32_t compressedSize;
441 uint32_t uncompressedPages;
442 uint32_t copyPageListHeadPage;
443 uint32_t pageListPage;
444 uint32_t * copyPageList;
445 uint32_t * src;
446 uint32_t copyPageIndex;
447 uint32_t sum;
448 uint32_t pageSum;
449 uint32_t nextFree;
450 uint32_t lastImagePage;
451 uint32_t lastMapPage;
452 uint32_t lastPageIndexPage;
453 uint32_t handoffPages;
454 uint32_t handoffPageCount;
455
456 uint64_t timeStart;
457 timeStart = rdtsc64();
458
459 static_assert(sizeof(IOHibernateImageHeader) == 512);
460
461 headerPhys = ptoa_64(p1);
462
463 if ((kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags) && !debug_probe())
464 gIOHibernateDebugFlags &= ~kIOHibernateDebugRestoreLogs;
465
466 debug_code(kIOHibernateRestoreCodeImageStart, headerPhys);
467
468 memcpy(gIOHibernateCurrentHeader,
469 (void *) pal_hib_map(IMAGE_AREA, headerPhys),
470 sizeof(IOHibernateImageHeader));
471
472 debug_code(kIOHibernateRestoreCodeSignature, gIOHibernateCurrentHeader->signature);
473
474 mapPhys = headerPhys
475 + (offsetof(IOHibernateImageHeader, fileExtentMap)
476 + gIOHibernateCurrentHeader->fileExtentMapSize
477 + ptoa_32(gIOHibernateCurrentHeader->restore1PageCount)
478 + gIOHibernateCurrentHeader->previewSize);
479
480 map = (hibernate_page_list_t *) pal_hib_map(BITMAP_AREA, mapPhys);
481
482 lastImagePage = atop_64(headerPhys + gIOHibernateCurrentHeader->image1Size);
483 lastMapPage = atop_64(mapPhys + gIOHibernateCurrentHeader->bitmapSize);
484
485 handoffPages = gIOHibernateCurrentHeader->handoffPages;
486 handoffPageCount = gIOHibernateCurrentHeader->handoffPageCount;
487
488 debug_code(kIOHibernateRestoreCodeImageEnd, ptoa_64(lastImagePage));
489 debug_code(kIOHibernateRestoreCodeMapStart, mapPhys);
490 debug_code(kIOHibernateRestoreCodeMapEnd, ptoa_64(lastMapPage));
491
492 debug_code(kIOHibernateRestoreCodeMapVirt, (uintptr_t) map);
493 debug_code(kIOHibernateRestoreCodeHandoffPages, ptoa_64(handoffPages));
494 debug_code(kIOHibernateRestoreCodeHandoffCount, handoffPageCount);
495
496 // knock all the image pages to be used out of free map
497 for (ppnum = atop_64(headerPhys); ppnum <= lastImagePage; ppnum++)
498 {
499 hibernate_page_bitset(map, FALSE, ppnum);
500 }
501 // knock all the handoff pages to be used out of free map
502 for (ppnum = handoffPages; ppnum < (handoffPages + handoffPageCount); ppnum++)
503 {
504 hibernate_page_bitset(map, FALSE, ppnum);
505 }
506
507 nextFree = 0;
508 hibernate_page_list_grab(map, &nextFree);
509
510 sum = gIOHibernateCurrentHeader->actualRestore1Sum;
511 gIOHibernateCurrentHeader->diag[0] = atop_64(headerPhys);
512 gIOHibernateCurrentHeader->diag[1] = sum;
513 gIOHibernateCurrentHeader->trampolineTime = 0;
514
515 uncompressedPages = 0;
516 conflictCount = 0;
517 copyPageListHeadPage = 0;
518 copyPageList = 0;
519 copyPageIndex = PAGE_SIZE >> 2;
520
521 compressedSize = PAGE_SIZE;
522 stage = 2;
523 count = 0;
524 srcPhys = 0;
525
526 if (gIOHibernateCurrentHeader->previewSize)
527 {
528 pageIndexPhys = headerPhys
529 + (offsetof(IOHibernateImageHeader, fileExtentMap)
530 + gIOHibernateCurrentHeader->fileExtentMapSize
531 + ptoa_32(gIOHibernateCurrentHeader->restore1PageCount));
532 imageReadPhys = (pageIndexPhys + gIOHibernateCurrentHeader->previewPageListSize);
533 lastPageIndexPage = atop_64(imageReadPhys);
534 pageIndexSource = (uint32_t *) pal_hib_map(IMAGE2_AREA, pageIndexPhys);
535 }
536 else
537 {
538 pageIndexPhys = 0;
539 lastPageIndexPage = 0;
540 imageReadPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
541 }
542
543 debug_code(kIOHibernateRestoreCodePageIndexStart, pageIndexPhys);
544 debug_code(kIOHibernateRestoreCodePageIndexEnd, ptoa_64(lastPageIndexPage));
545
546 while (1)
547 {
548 switch (stage)
549 {
550 case 2:
551 // copy handoff data
552 count = srcPhys ? 0 : handoffPageCount;
553 if (!count)
554 break;
555 if (count > gIOHibernateHandoffPageCount) count = gIOHibernateHandoffPageCount;
556 srcPhys = ptoa_64(handoffPages);
557 break;
558
559 case 1:
560 // copy pageIndexSource pages == preview image data
561 if (!srcPhys)
562 {
563 if (!pageIndexPhys) break;
564 srcPhys = imageReadPhys;
565 }
566 ppnum = pageIndexSource[0];
567 count = pageIndexSource[1];
568 pageIndexSource += 2;
569 pageIndexPhys += 2 * sizeof(pageIndexSource[0]);
570 imageReadPhys = srcPhys;
571 break;
572
573 case 0:
574 // copy pages
575 if (!srcPhys) srcPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
576 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
577 ppnum = src[0];
578 count = src[1];
579 srcPhys += 2 * sizeof(*src);
580 imageReadPhys = srcPhys;
581 break;
582 }
583
584
585 if (!count)
586 {
587 if (!stage)
588 break;
589 stage--;
590 srcPhys = 0;
591 continue;
592 }
593
594 for (page = 0; page < count; page++, ppnum++)
595 {
596 uint32_t tag;
597 int conflicts;
598
599 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
600
601 if (2 == stage) ppnum = gIOHibernateHandoffPages[page];
602 else if (!stage)
603 {
604 tag = *src++;
605 // debug_code(kIOHibernateRestoreCodeTag, (uintptr_t) tag);
606 srcPhys += sizeof(*src);
607 compressedSize = kIOHibernateTagLength & tag;
608 }
609
610 conflicts = (ppnum >= atop_64(mapPhys)) && (ppnum <= lastMapPage);
611
612 conflicts |= ((ppnum >= atop_64(imageReadPhys)) && (ppnum <= lastImagePage));
613
614 if (stage >= 2)
615 conflicts |= ((ppnum >= atop_64(srcPhys)) && (ppnum <= (handoffPages + handoffPageCount - 1)));
616
617 if (stage >= 1)
618 conflicts |= ((ppnum >= atop_64(pageIndexPhys)) && (ppnum <= lastPageIndexPage));
619
620 if (!conflicts)
621 {
622 pageSum = store_one_page(gIOHibernateCurrentHeader->processorFlags,
623 src, compressedSize, 0, ppnum);
624 if (stage != 2)
625 sum += pageSum;
626 uncompressedPages++;
627 }
628 else
629 {
630 uint32_t bufferPage = 0;
631 uint32_t * dst;
632
633 // debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
634 // debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
635 conflictCount++;
636 if (compressedSize)
637 {
638 // alloc new buffer page
639 bufferPage = hibernate_page_list_grab(map, &nextFree);
640 dst = (uint32_t *)pal_hib_map(DEST_COPY_AREA, ptoa_64(bufferPage));
641 memcpy(dst, src, compressedSize);
642 }
643 if (copyPageIndex > ((PAGE_SIZE >> 2) - 3))
644 {
645 // alloc new copy list page
646 pageListPage = hibernate_page_list_grab(map, &nextFree);
647 // link to current
648 if (copyPageList) {
649 copyPageList[1] = pageListPage;
650 } else {
651 copyPageListHeadPage = pageListPage;
652 }
653 copyPageList = (uint32_t *)pal_hib_map(SRC_COPY_AREA,
654 ptoa_64(pageListPage));
655 copyPageList[1] = 0;
656 copyPageIndex = 2;
657 }
658 copyPageList[copyPageIndex++] = ppnum;
659 copyPageList[copyPageIndex++] = bufferPage;
660 copyPageList[copyPageIndex++] = (compressedSize | (stage << 24));
661 copyPageList[0] = copyPageIndex;
662 }
663 srcPhys += ((compressedSize + 3) & ~3);
664 src += ((compressedSize + 3) >> 2);
665 }
666 }
667
668 /* src points to the last page restored, so we need to skip over that */
669 hibernateRestorePALState(src);
670
671 // -- copy back conflicts
672
673 pageListPage = copyPageListHeadPage;
674 while (pageListPage)
675 {
676 copyPageList = (uint32_t *)pal_hib_map(COPY_PAGE_AREA, ptoa_64(pageListPage));
677 for (copyPageIndex = 2; copyPageIndex < copyPageList[0]; copyPageIndex += 3)
678 {
679 ppnum = copyPageList[copyPageIndex + 0];
680 srcPhys = ptoa_64(copyPageList[copyPageIndex + 1]);
681 src = (uint32_t *) pal_hib_map(SRC_COPY_AREA, srcPhys);
682 compressedSize = copyPageList[copyPageIndex + 2];
683 stage = compressedSize >> 24;
684 compressedSize &= 0x1FFF;
685 pageSum = store_one_page(gIOHibernateCurrentHeader->processorFlags,
686 src, compressedSize, 0, ppnum);
687 if (stage != 2)
688 sum += pageSum;
689 uncompressedPages++;
690 }
691 pageListPage = copyPageList[1];
692 }
693
694 pal_hib_patchup();
695
696 // -- image has been destroyed...
697
698 gIOHibernateCurrentHeader->actualImage1Sum = sum;
699 gIOHibernateCurrentHeader->actualUncompressedPages = uncompressedPages;
700 gIOHibernateCurrentHeader->conflictCount = conflictCount;
701 gIOHibernateCurrentHeader->nextFree = nextFree;
702
703 gIOHibernateState = kIOHibernateStateWakingFromHibernate;
704
705 gIOHibernateCurrentHeader->trampolineTime = (((rdtsc64() - timeStart)) >> 8);
706
707 // debug_code('done', 0);
708
709 #if CONFIG_SLEEP
710 #if defined(__i386__) || defined(__x86_64__)
711 typedef void (*ResetProc)(void);
712 ResetProc proc;
713 proc = HIB_ENTRYPOINT;
714 // flush caches
715 __asm__("wbinvd");
716 proc();
717 #else
718 // implement me
719 #endif
720 #endif
721
722 return -1;
723 }
724
725 #if CONFIG_DEBUG
726 /* standalone printf implementation */
727 /*-
728 * Copyright (c) 1986, 1988, 1991, 1993
729 * The Regents of the University of California. All rights reserved.
730 * (c) UNIX System Laboratories, Inc.
731 * All or some portions of this file are derived from material licensed
732 * to the University of California by American Telephone and Telegraph
733 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
734 * the permission of UNIX System Laboratories, Inc.
735 *
736 * Redistribution and use in source and binary forms, with or without
737 * modification, are permitted provided that the following conditions
738 * are met:
739 * 1. Redistributions of source code must retain the above copyright
740 * notice, this list of conditions and the following disclaimer.
741 * 2. Redistributions in binary form must reproduce the above copyright
742 * notice, this list of conditions and the following disclaimer in the
743 * documentation and/or other materials provided with the distribution.
744 * 4. Neither the name of the University nor the names of its contributors
745 * may be used to endorse or promote products derived from this software
746 * without specific prior written permission.
747 *
748 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
749 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
750 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
751 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
752 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
753 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
754 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
755 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
756 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
757 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
758 * SUCH DAMAGE.
759 *
760 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
761 */
762
763 typedef long ptrdiff_t;
764 char const hibhex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
765 #define hibhex2ascii(hex) (hibhex2ascii_data[hex])
766 #define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
767 static size_t
768 hibstrlen(const char *s)
769 {
770 size_t l = 0;
771 while (*s++)
772 l++;
773 return l;
774 }
775
776 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
777 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
778
779 /*
780 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
781 * order; return an optional length and a pointer to the last character
782 * written in the buffer (i.e., the first character of the string).
783 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
784 */
785 static char *
786 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
787 {
788 char *p, c;
789
790 /* Truncate so we don't call umoddi3, which isn't in __HIB */
791 #if !defined(__LP64__)
792 uint32_t num2 = (uint32_t) num;
793 #else
794 uintmax_t num2 = num;
795 #endif
796
797 p = nbuf;
798 *p = '\0';
799 do {
800 c = hibhex2ascii(num2 % base);
801 *++p = upper ? toupper(c) : c;
802 } while (num2 /= base);
803 if (lenp)
804 *lenp = (int)(p - nbuf);
805 return (p);
806 }
807
808 /*
809 * Scaled down version of printf(3).
810 *
811 * Two additional formats:
812 *
813 * The format %b is supported to decode error registers.
814 * Its usage is:
815 *
816 * printf("reg=%b\n", regval, "*");
817 *
818 * where is the output base expressed as a control character, e.g.
819 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
820 * the first of which gives the bit number to be inspected (origin 1), and
821 * the next characters (up to a control character, i.e. a character <= 32),
822 * give the name of the register. Thus:
823 *
824 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
825 *
826 * would produce output:
827 *
828 * reg=3
829 *
830 * XXX: %D -- Hexdump, takes pointer and separator string:
831 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
832 * ("%*D", len, ptr, " " -> XX XX XX XX ...
833 */
834 static int
835 hibkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
836 {
837 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
838 char nbuf[MAXNBUF];
839 char *d;
840 const char *p, *percent, *q;
841 u_char *up;
842 int ch, n;
843 uintmax_t num;
844 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
845 int cflag, hflag, jflag, tflag, zflag;
846 int dwidth, upper;
847 char padc;
848 int stop = 0, retval = 0;
849
850 num = 0;
851 if (!func)
852 d = (char *) arg;
853 else
854 d = NULL;
855
856 if (fmt == NULL)
857 fmt = "(fmt null)\n";
858
859 if (radix < 2 || radix > 36)
860 radix = 10;
861
862 for (;;) {
863 padc = ' ';
864 width = 0;
865 while ((ch = (u_char)*fmt++) != '%' || stop) {
866 if (ch == '\0')
867 return (retval);
868 PCHAR(ch);
869 }
870 percent = fmt - 1;
871 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
872 sign = 0; dot = 0; dwidth = 0; upper = 0;
873 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
874 reswitch: switch (ch = (u_char)*fmt++) {
875 case '.':
876 dot = 1;
877 goto reswitch;
878 case '#':
879 sharpflag = 1;
880 goto reswitch;
881 case '+':
882 sign = 1;
883 goto reswitch;
884 case '-':
885 ladjust = 1;
886 goto reswitch;
887 case '%':
888 PCHAR(ch);
889 break;
890 case '*':
891 if (!dot) {
892 width = va_arg(ap, int);
893 if (width < 0) {
894 ladjust = !ladjust;
895 width = -width;
896 }
897 } else {
898 dwidth = va_arg(ap, int);
899 }
900 goto reswitch;
901 case '0':
902 if (!dot) {
903 padc = '0';
904 goto reswitch;
905 }
906 case '1': case '2': case '3': case '4':
907 case '5': case '6': case '7': case '8': case '9':
908 for (n = 0;; ++fmt) {
909 n = n * 10 + ch - '0';
910 ch = *fmt;
911 if (ch < '0' || ch > '9')
912 break;
913 }
914 if (dot)
915 dwidth = n;
916 else
917 width = n;
918 goto reswitch;
919 case 'b':
920 num = (u_int)va_arg(ap, int);
921 p = va_arg(ap, char *);
922 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
923 PCHAR(*q--);
924
925 if (num == 0)
926 break;
927
928 for (tmp = 0; *p;) {
929 n = *p++;
930 if (num & (1 << (n - 1))) {
931 PCHAR(tmp ? ',' : '<');
932 for (; (n = *p) > ' '; ++p)
933 PCHAR(n);
934 tmp = 1;
935 } else
936 for (; *p > ' '; ++p)
937 continue;
938 }
939 if (tmp)
940 PCHAR('>');
941 break;
942 case 'c':
943 PCHAR(va_arg(ap, int));
944 break;
945 case 'D':
946 up = va_arg(ap, u_char *);
947 p = va_arg(ap, char *);
948 if (!width)
949 width = 16;
950 while(width--) {
951 PCHAR(hibhex2ascii(*up >> 4));
952 PCHAR(hibhex2ascii(*up & 0x0f));
953 up++;
954 if (width)
955 for (q=p;*q;q++)
956 PCHAR(*q);
957 }
958 break;
959 case 'd':
960 case 'i':
961 base = 10;
962 sign = 1;
963 goto handle_sign;
964 case 'h':
965 if (hflag) {
966 hflag = 0;
967 cflag = 1;
968 } else
969 hflag = 1;
970 goto reswitch;
971 case 'j':
972 jflag = 1;
973 goto reswitch;
974 case 'l':
975 if (lflag) {
976 lflag = 0;
977 qflag = 1;
978 } else
979 lflag = 1;
980 goto reswitch;
981 case 'n':
982 if (jflag)
983 *(va_arg(ap, intmax_t *)) = retval;
984 else if (qflag)
985 *(va_arg(ap, quad_t *)) = retval;
986 else if (lflag)
987 *(va_arg(ap, long *)) = retval;
988 else if (zflag)
989 *(va_arg(ap, size_t *)) = retval;
990 else if (hflag)
991 *(va_arg(ap, short *)) = retval;
992 else if (cflag)
993 *(va_arg(ap, char *)) = retval;
994 else
995 *(va_arg(ap, int *)) = retval;
996 break;
997 case 'o':
998 base = 8;
999 goto handle_nosign;
1000 case 'p':
1001 base = 16;
1002 sharpflag = (width == 0);
1003 sign = 0;
1004 num = (uintptr_t)va_arg(ap, void *);
1005 goto number;
1006 case 'q':
1007 qflag = 1;
1008 goto reswitch;
1009 case 'r':
1010 base = radix;
1011 if (sign)
1012 goto handle_sign;
1013 goto handle_nosign;
1014 case 's':
1015 p = va_arg(ap, char *);
1016 if (p == NULL)
1017 p = "(null)";
1018 if (!dot)
1019 n = (typeof(n))hibstrlen (p);
1020 else
1021 for (n = 0; n < dwidth && p[n]; n++)
1022 continue;
1023
1024 width -= n;
1025
1026 if (!ladjust && width > 0)
1027 while (width--)
1028 PCHAR(padc);
1029 while (n--)
1030 PCHAR(*p++);
1031 if (ladjust && width > 0)
1032 while (width--)
1033 PCHAR(padc);
1034 break;
1035 case 't':
1036 tflag = 1;
1037 goto reswitch;
1038 case 'u':
1039 base = 10;
1040 goto handle_nosign;
1041 case 'X':
1042 upper = 1;
1043 case 'x':
1044 base = 16;
1045 goto handle_nosign;
1046 case 'y':
1047 base = 16;
1048 sign = 1;
1049 goto handle_sign;
1050 case 'z':
1051 zflag = 1;
1052 goto reswitch;
1053 handle_nosign:
1054 sign = 0;
1055 if (jflag)
1056 num = va_arg(ap, uintmax_t);
1057 else if (qflag)
1058 num = va_arg(ap, u_quad_t);
1059 else if (tflag)
1060 num = va_arg(ap, ptrdiff_t);
1061 else if (lflag)
1062 num = va_arg(ap, u_long);
1063 else if (zflag)
1064 num = va_arg(ap, size_t);
1065 else if (hflag)
1066 num = (u_short)va_arg(ap, int);
1067 else if (cflag)
1068 num = (u_char)va_arg(ap, int);
1069 else
1070 num = va_arg(ap, u_int);
1071 goto number;
1072 handle_sign:
1073 if (jflag)
1074 num = va_arg(ap, intmax_t);
1075 else if (qflag)
1076 num = va_arg(ap, quad_t);
1077 else if (tflag)
1078 num = va_arg(ap, ptrdiff_t);
1079 else if (lflag)
1080 num = va_arg(ap, long);
1081 else if (zflag)
1082 num = va_arg(ap, ssize_t);
1083 else if (hflag)
1084 num = (short)va_arg(ap, int);
1085 else if (cflag)
1086 num = (char)va_arg(ap, int);
1087 else
1088 num = va_arg(ap, int);
1089 number:
1090 if (sign && (intmax_t)num < 0) {
1091 neg = 1;
1092 num = -(intmax_t)num;
1093 }
1094 p = ksprintn(nbuf, num, base, &tmp, upper);
1095 if (sharpflag && num != 0) {
1096 if (base == 8)
1097 tmp++;
1098 else if (base == 16)
1099 tmp += 2;
1100 }
1101 if (neg)
1102 tmp++;
1103
1104 if (!ladjust && padc != '0' && width
1105 && (width -= tmp) > 0)
1106 while (width--)
1107 PCHAR(padc);
1108 if (neg)
1109 PCHAR('-');
1110 if (sharpflag && num != 0) {
1111 if (base == 8) {
1112 PCHAR('0');
1113 } else if (base == 16) {
1114 PCHAR('0');
1115 PCHAR('x');
1116 }
1117 }
1118 if (!ladjust && width && (width -= tmp) > 0)
1119 while (width--)
1120 PCHAR(padc);
1121
1122 while (*p)
1123 PCHAR(*p--);
1124
1125 if (ladjust && width && (width -= tmp) > 0)
1126 while (width--)
1127 PCHAR(padc);
1128
1129 break;
1130 default:
1131 while (percent < fmt)
1132 PCHAR(*percent++);
1133 /*
1134 * Since we ignore an formatting argument it is no
1135 * longer safe to obey the remaining formatting
1136 * arguments as the arguments will no longer match
1137 * the format specs.
1138 */
1139 stop = 1;
1140 break;
1141 }
1142 }
1143 #undef PCHAR
1144 }
1145
1146
1147 static void
1148 putchar(int c, void *arg)
1149 {
1150 (void)arg;
1151 uart_putc(c);
1152 }
1153
1154 void
1155 hibprintf(const char *fmt, ...)
1156 {
1157 /* http://www.pagetable.com/?p=298 */
1158 va_list ap;
1159
1160 va_start(ap, fmt);
1161 hibkvprintf(fmt, putchar, NULL, 10, ap);
1162 va_end(ap);
1163 }
1164 #endif /* CONFIG_DEBUG */
1165