]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOHibernateRestoreKernel.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / iokit / Kernel / IOHibernateRestoreKernel.c
CommitLineData
3a60a9f5 1/*
2d21ac55 2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3a60a9f5 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
3a60a9f5 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
3a60a9f5
A
27 */
28
29#include <stdint.h>
30#include <mach/mach_types.h>
31#include <mach/vm_param.h>
32#include <IOKit/IOHibernatePrivate.h>
0c530ab8 33#include <IOKit/IOLib.h>
3a60a9f5 34#include <pexpert/boot.h>
2d21ac55 35#include <libkern/libkern.h>
3a60a9f5 36
39236c6e 37#include <vm/WKdm_new.h>
3a60a9f5
A
38#include "IOHibernateInternal.h"
39
bd504ef0 40#include <machine/pal_hibernate.h>
6d2010ae 41
3a60a9f5
A
42/*
43This code is linked into the kernel but part of the "__HIB" section, which means
44its used by code running in the special context of restoring the kernel text and data
45from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
46it calls or references needs to be careful to only touch memory also in the "__HIB" section.
47*/
48
49uint32_t gIOHibernateState;
50
b0d623f7
A
51uint32_t gIOHibernateDebugFlags;
52
3a60a9f5
A
53static IOHibernateImageHeader _hibernateHeader;
54IOHibernateImageHeader * gIOHibernateCurrentHeader = &_hibernateHeader;
55
6d2010ae
A
56ppnum_t gIOHibernateHandoffPages[64];
57uint32_t gIOHibernateHandoffPageCount = sizeof(gIOHibernateHandoffPages)
58 / sizeof(gIOHibernateHandoffPages[0]);
3a60a9f5 59
6d2010ae
A
60#if CONFIG_DEBUG
61void hibprintf(const char *fmt, ...);
62#else
63#define hibprintf(x...)
64#endif
0c530ab8 65
b0d623f7
A
66
67#if CONFIG_SLEEP
68#if defined(__i386__) || defined(__x86_64__)
69extern void acpi_wake_prot_entry(void);
70#endif
71#endif
72
73/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
74
75#if defined(__i386__) || defined(__x86_64__)
76
bd504ef0
A
77#define rdtsc(lo,hi) \
78 __asm__ volatile("lfence; rdtsc; lfence" : "=a" (lo), "=d" (hi))
79
80static 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
89static 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
b0d623f7
A
98#define DBGLOG 1
99
100#include <architecture/i386/pio.h>
101
102/* standard port addresses */
103enum {
104 COM1_PORT_ADDR = 0x3f8,
105 COM2_PORT_ADDR = 0x2f8
106};
107
108/* UART register offsets */
109enum {
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
124enum {
125 UART_LCR_8BITS = 0x03,
126 UART_LCR_DLAB = 0x80
127};
128
129enum {
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
137enum {
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
145static 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
152static 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
163static 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;
6d2010ae 174 else if (leading && bit)
b0d623f7
A
175 continue;
176 if (c <= 9)
177 c += '0';
178 else
179 c+= 'a' - 10;
180 uart_putc(c);
181 }
182}
183
184static 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) {}
3a60a9f5
A
209#endif
210
b0d623f7
A
211enum
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',
7ddcb079
A
222 kIOHibernateRestoreCodeNoMemory = 'nomm',
223 kIOHibernateRestoreCodeTag = 'tag ',
224 kIOHibernateRestoreCodeSignature = 'sign',
225 kIOHibernateRestoreCodeMapVirt = 'mapV',
226 kIOHibernateRestoreCodeHandoffPages = 'hand',
227 kIOHibernateRestoreCodeHandoffCount = 'hndc',
b0d623f7
A
228};
229
230/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
231
232
233static void fatal(void)
234{
235#if defined(__i386__) || defined(__x86_64__)
236 outb(0xcf9, 6);
237#else
238 while (true) {}
239#endif
240}
241
3a60a9f5
A
242/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
243
3a60a9f5 244uint32_t
0b4c1975 245hibernate_sum_page(uint8_t *buf, uint32_t ppnum)
3a60a9f5 246{
0b4c1975 247 return (((uint32_t *)buf)[((PAGE_SIZE >> 2) - 1) & ppnum]);
3a60a9f5
A
248}
249
250/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
251
0c530ab8
A
252static hibernate_bitmap_t *
253hibernate_page_bitmap(hibernate_page_list_t * list, uint32_t page)
89b3af67 254{
6601e61a 255 uint32_t bank;
21362eb3 256 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
89b3af67 257
21362eb3 258 for (bank = 0; bank < list->bank_count; bank++)
89b3af67 259 {
6601e61a 260 if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
21362eb3 261 break;
21362eb3 262 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
89b3af67 263 }
0c530ab8 264 if (bank == list->bank_count)
2d21ac55 265 bitmap = NULL;
0c530ab8
A
266
267 return (bitmap);
4452a7af
A
268}
269
0c530ab8
A
270hibernate_bitmap_t *
271hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * pPage)
4452a7af 272{
0c530ab8 273 uint32_t bank, page = *pPage;
6601e61a 274 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
4452a7af 275
6601e61a 276 for (bank = 0; bank < list->bank_count; bank++)
4452a7af 277 {
0c530ab8 278 if (page <= bitmap->first_page)
6601e61a 279 {
0c530ab8 280 *pPage = bitmap->first_page;
6601e61a
A
281 break;
282 }
0c530ab8
A
283 if (page <= bitmap->last_page)
284 break;
6601e61a 285 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
4452a7af 286 }
0c530ab8 287 if (bank == list->bank_count)
2d21ac55 288 bitmap = NULL;
0c530ab8
A
289
290 return (bitmap);
291}
292
293void
294hibernate_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
311boolean_t
312hibernate_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 }
3a60a9f5
A
323 return (result);
324}
325
0c530ab8 326// count bits clear or set (set == TRUE) starting at page.
3a60a9f5 327uint32_t
0c530ab8 328hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page)
3a60a9f5 329{
0c530ab8
A
330 uint32_t index, bit, bits;
331 uint32_t count;
3a60a9f5 332
0c530ab8 333 count = 0;
4452a7af 334
0c530ab8
A
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
3a60a9f5 345 {
0c530ab8
A
346 count += 32 - bit;
347 while (++index < bitmap->bitmapwords)
3a60a9f5 348 {
0c530ab8
A
349 bits = bitmap->bitmap[index];
350 if (set)
351 bits = ~bits;
352 if (bits)
3a60a9f5 353 {
0c530ab8
A
354 count += __builtin_clz(bits);
355 break;
3a60a9f5 356 }
0c530ab8 357 count += 32;
3a60a9f5 358 }
3a60a9f5
A
359 }
360
7ddcb079
A
361 if ((page + count) > (bitmap->last_page + 1)) count = (bitmap->last_page + 1) - page;
362
3a60a9f5
A
363 return (count);
364}
365
6d2010ae 366static ppnum_t
0c530ab8 367hibernate_page_list_grab(hibernate_page_list_t * list, uint32_t * pNextFree)
3a60a9f5 368{
0c530ab8
A
369 uint32_t nextFree = *pNextFree;
370 uint32_t nextFreeInBank;
371 hibernate_bitmap_t * bitmap;
3a60a9f5 372
0c530ab8
A
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 }
3a60a9f5 383
b0d623f7
A
384 if (!bitmap)
385 {
386 debug_code(kIOHibernateRestoreCodeNoMemory, nextFree);
387 fatal();
388 nextFree = 0;
389 }
390
3a60a9f5
A
391 return (nextFree);
392}
393
394static uint32_t
395store_one_page(uint32_t procFlags, uint32_t * src, uint32_t compressedSize,
396 uint32_t * buffer, uint32_t ppnum)
397{
6d2010ae 398 uint64_t dst = ptoa_64(ppnum);
39037602 399 uint8_t scratch[WKdm_SCRATCH_BUF_SIZE_INTERNAL] __attribute__ ((aligned (16)));
3a60a9f5 400
6d2010ae
A
401 if (compressedSize != PAGE_SIZE)
402 {
403 dst = pal_hib_map(DEST_COPY_AREA, dst);
3e170ce0 404 if (compressedSize != 4) WKdm_decompress_new((WK_word*) src, (WK_word*)(uintptr_t)dst, (WK_word*) &scratch[0], compressedSize);
743345f9
A
405 else
406 {
407 size_t i;
408 uint32_t s, *d;
3e170ce0 409
743345f9
A
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;
3e170ce0 414 }
6d2010ae
A
415 }
416 else
417 {
418 dst = hibernate_restore_phys_page((uint64_t) (uintptr_t) src, dst, PAGE_SIZE, procFlags);
419 }
3a60a9f5 420
6d2010ae 421 return hibernate_sum_page((uint8_t *)(uintptr_t)dst, ppnum);
3a60a9f5
A
422}
423
3a60a9f5 424long
7ddcb079
A
425hibernate_kernel_entrypoint(uint32_t p1,
426 uint32_t p2, uint32_t p3, uint32_t p4)
3a60a9f5 427{
7ddcb079
A
428 uint64_t headerPhys;
429 uint64_t mapPhys;
430 uint64_t srcPhys;
431 uint64_t imageReadPhys;
432 uint64_t pageIndexPhys;
3a60a9f5
A
433 uint32_t * pageIndexSource;
434 hibernate_page_list_t * map;
6d2010ae 435 uint32_t stage;
3a60a9f5
A
436 uint32_t count;
437 uint32_t ppnum;
438 uint32_t page;
439 uint32_t conflictCount;
440 uint32_t compressedSize;
441 uint32_t uncompressedPages;
7ddcb079
A
442 uint32_t copyPageListHeadPage;
443 uint32_t pageListPage;
3a60a9f5 444 uint32_t * copyPageList;
7ddcb079 445 uint32_t * src;
3a60a9f5
A
446 uint32_t copyPageIndex;
447 uint32_t sum;
6d2010ae 448 uint32_t pageSum;
3a60a9f5
A
449 uint32_t nextFree;
450 uint32_t lastImagePage;
451 uint32_t lastMapPage;
452 uint32_t lastPageIndexPage;
6d2010ae
A
453 uint32_t handoffPages;
454 uint32_t handoffPageCount;
3a60a9f5 455
39236c6e 456 uint64_t timeStart;
bd504ef0
A
457 timeStart = rdtsc64();
458
39037602 459 static_assert(sizeof(IOHibernateImageHeader) == 512);
3a60a9f5 460
7ddcb079
A
461 headerPhys = ptoa_64(p1);
462
b0d623f7
A
463 if ((kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags) && !debug_probe())
464 gIOHibernateDebugFlags &= ~kIOHibernateDebugRestoreLogs;
465
7ddcb079
A
466 debug_code(kIOHibernateRestoreCodeImageStart, headerPhys);
467
39236c6e
A
468 memcpy(gIOHibernateCurrentHeader,
469 (void *) pal_hib_map(IMAGE_AREA, headerPhys),
470 sizeof(IOHibernateImageHeader));
b0d623f7 471
7ddcb079 472 debug_code(kIOHibernateRestoreCodeSignature, gIOHibernateCurrentHeader->signature);
3a60a9f5 473
7ddcb079
A
474 mapPhys = headerPhys
475 + (offsetof(IOHibernateImageHeader, fileExtentMap)
476 + gIOHibernateCurrentHeader->fileExtentMapSize
477 + ptoa_32(gIOHibernateCurrentHeader->restore1PageCount)
478 + gIOHibernateCurrentHeader->previewSize);
b0d623f7 479
7ddcb079 480 map = (hibernate_page_list_t *) pal_hib_map(BITMAP_AREA, mapPhys);
3a60a9f5 481
7ddcb079
A
482 lastImagePage = atop_64(headerPhys + gIOHibernateCurrentHeader->image1Size);
483 lastMapPage = atop_64(mapPhys + gIOHibernateCurrentHeader->bitmapSize);
3a60a9f5 484
7ddcb079
A
485 handoffPages = gIOHibernateCurrentHeader->handoffPages;
486 handoffPageCount = gIOHibernateCurrentHeader->handoffPageCount;
6d2010ae 487
b0d623f7 488 debug_code(kIOHibernateRestoreCodeImageEnd, ptoa_64(lastImagePage));
7ddcb079 489 debug_code(kIOHibernateRestoreCodeMapStart, mapPhys);
b0d623f7 490 debug_code(kIOHibernateRestoreCodeMapEnd, ptoa_64(lastMapPage));
3a60a9f5 491
7ddcb079
A
492 debug_code(kIOHibernateRestoreCodeMapVirt, (uintptr_t) map);
493 debug_code(kIOHibernateRestoreCodeHandoffPages, ptoa_64(handoffPages));
494 debug_code(kIOHibernateRestoreCodeHandoffCount, handoffPageCount);
6d2010ae 495
3a60a9f5 496 // knock all the image pages to be used out of free map
7ddcb079 497 for (ppnum = atop_64(headerPhys); ppnum <= lastImagePage; ppnum++)
3a60a9f5
A
498 {
499 hibernate_page_bitset(map, FALSE, ppnum);
500 }
6d2010ae
A
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 }
3a60a9f5
A
506
507 nextFree = 0;
0c530ab8 508 hibernate_page_list_grab(map, &nextFree);
3a60a9f5 509
7ddcb079
A
510 sum = gIOHibernateCurrentHeader->actualRestore1Sum;
511 gIOHibernateCurrentHeader->diag[0] = atop_64(headerPhys);
3a60a9f5 512 gIOHibernateCurrentHeader->diag[1] = sum;
39236c6e 513 gIOHibernateCurrentHeader->trampolineTime = 0;
3a60a9f5 514
7ddcb079
A
515 uncompressedPages = 0;
516 conflictCount = 0;
517 copyPageListHeadPage = 0;
518 copyPageList = 0;
519 copyPageIndex = PAGE_SIZE >> 2;
3a60a9f5 520
7ddcb079
A
521 compressedSize = PAGE_SIZE;
522 stage = 2;
523 count = 0;
524 srcPhys = 0;
6d2010ae
A
525
526 if (gIOHibernateCurrentHeader->previewSize)
527 {
7ddcb079
A
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);
6d2010ae
A
535 }
536 else
537 {
7ddcb079 538 pageIndexPhys = 0;
6d2010ae 539 lastPageIndexPage = 0;
7ddcb079 540 imageReadPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
6d2010ae
A
541 }
542
7ddcb079 543 debug_code(kIOHibernateRestoreCodePageIndexStart, pageIndexPhys);
6d2010ae 544 debug_code(kIOHibernateRestoreCodePageIndexEnd, ptoa_64(lastPageIndexPage));
3a60a9f5
A
545
546 while (1)
547 {
6d2010ae
A
548 switch (stage)
549 {
550 case 2:
551 // copy handoff data
7ddcb079 552 count = srcPhys ? 0 : handoffPageCount;
6d2010ae
A
553 if (!count)
554 break;
7ddcb079
A
555 if (count > gIOHibernateHandoffPageCount) count = gIOHibernateHandoffPageCount;
556 srcPhys = ptoa_64(handoffPages);
6d2010ae
A
557 break;
558
559 case 1:
560 // copy pageIndexSource pages == preview image data
7ddcb079 561 if (!srcPhys)
6d2010ae 562 {
7ddcb079
A
563 if (!pageIndexPhys) break;
564 srcPhys = imageReadPhys;
6d2010ae
A
565 }
566 ppnum = pageIndexSource[0];
567 count = pageIndexSource[1];
568 pageIndexSource += 2;
7ddcb079
A
569 pageIndexPhys += 2 * sizeof(pageIndexSource[0]);
570 imageReadPhys = srcPhys;
6d2010ae
A
571 break;
572
573 case 0:
574 // copy pages
7ddcb079
A
575 if (!srcPhys) srcPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
576 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
6d2010ae
A
577 ppnum = src[0];
578 count = src[1];
7ddcb079
A
579 srcPhys += 2 * sizeof(*src);
580 imageReadPhys = srcPhys;
6d2010ae
A
581 break;
582 }
583
584
585 if (!count)
586 {
587 if (!stage)
588 break;
589 stage--;
7ddcb079 590 srcPhys = 0;
6d2010ae 591 continue;
3a60a9f5
A
592 }
593
594 for (page = 0; page < count; page++, ppnum++)
595 {
6d2010ae 596 uint32_t tag;
3a60a9f5
A
597 int conflicts;
598
7ddcb079
A
599 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
600
601 if (2 == stage) ppnum = gIOHibernateHandoffPages[page];
6d2010ae
A
602 else if (!stage)
603 {
604 tag = *src++;
7ddcb079
A
605// debug_code(kIOHibernateRestoreCodeTag, (uintptr_t) tag);
606 srcPhys += sizeof(*src);
6d2010ae
A
607 compressedSize = kIOHibernateTagLength & tag;
608 }
609
7ddcb079 610 conflicts = (ppnum >= atop_64(mapPhys)) && (ppnum <= lastMapPage);
3a60a9f5 611
7ddcb079 612 conflicts |= ((ppnum >= atop_64(imageReadPhys)) && (ppnum <= lastImagePage));
3a60a9f5 613
6d2010ae 614 if (stage >= 2)
7ddcb079 615 conflicts |= ((ppnum >= atop_64(srcPhys)) && (ppnum <= (handoffPages + handoffPageCount - 1)));
6d2010ae
A
616
617 if (stage >= 1)
7ddcb079 618 conflicts |= ((ppnum >= atop_64(pageIndexPhys)) && (ppnum <= lastPageIndexPage));
3a60a9f5
A
619
620 if (!conflicts)
621 {
6d2010ae
A
622 pageSum = store_one_page(gIOHibernateCurrentHeader->processorFlags,
623 src, compressedSize, 0, ppnum);
624 if (stage != 2)
625 sum += pageSum;
3a60a9f5
A
626 uncompressedPages++;
627 }
628 else
629 {
39236c6e 630 uint32_t bufferPage = 0;
3a60a9f5
A
631 uint32_t * dst;
632
b0d623f7
A
633// debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
634// debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
3a60a9f5 635 conflictCount++;
39236c6e
A
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 }
3a60a9f5
A
643 if (copyPageIndex > ((PAGE_SIZE >> 2) - 3))
644 {
645 // alloc new copy list page
7ddcb079 646 pageListPage = hibernate_page_list_grab(map, &nextFree);
3a60a9f5 647 // link to current
6d2010ae
A
648 if (copyPageList) {
649 copyPageList[1] = pageListPage;
650 } else {
7ddcb079 651 copyPageListHeadPage = pageListPage;
6d2010ae
A
652 }
653 copyPageList = (uint32_t *)pal_hib_map(SRC_COPY_AREA,
7ddcb079 654 ptoa_64(pageListPage));
3a60a9f5
A
655 copyPageList[1] = 0;
656 copyPageIndex = 2;
657 }
3a60a9f5
A
658 copyPageList[copyPageIndex++] = ppnum;
659 copyPageList[copyPageIndex++] = bufferPage;
6d2010ae 660 copyPageList[copyPageIndex++] = (compressedSize | (stage << 24));
3a60a9f5 661 copyPageList[0] = copyPageIndex;
3a60a9f5 662 }
7ddcb079
A
663 srcPhys += ((compressedSize + 3) & ~3);
664 src += ((compressedSize + 3) >> 2);
3a60a9f5
A
665 }
666 }
667
6d2010ae
A
668 /* src points to the last page restored, so we need to skip over that */
669 hibernateRestorePALState(src);
670
3a60a9f5
A
671 // -- copy back conflicts
672
7ddcb079
A
673 pageListPage = copyPageListHeadPage;
674 while (pageListPage)
3a60a9f5 675 {
7ddcb079 676 copyPageList = (uint32_t *)pal_hib_map(COPY_PAGE_AREA, ptoa_64(pageListPage));
3a60a9f5
A
677 for (copyPageIndex = 2; copyPageIndex < copyPageList[0]; copyPageIndex += 3)
678 {
6d2010ae 679 ppnum = copyPageList[copyPageIndex + 0];
7ddcb079
A
680 srcPhys = ptoa_64(copyPageList[copyPageIndex + 1]);
681 src = (uint32_t *) pal_hib_map(SRC_COPY_AREA, srcPhys);
6d2010ae
A
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;
3a60a9f5
A
689 uncompressedPages++;
690 }
7ddcb079 691 pageListPage = copyPageList[1];
3a60a9f5
A
692 }
693
6d2010ae
A
694 pal_hib_patchup();
695
3a60a9f5
A
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
39236c6e 705 gIOHibernateCurrentHeader->trampolineTime = (((rdtsc64() - timeStart)) >> 8);
bd504ef0 706
3e170ce0
A
707// debug_code('done', 0);
708
b0d623f7 709#if CONFIG_SLEEP
6d2010ae 710#if defined(__i386__) || defined(__x86_64__)
b0d623f7
A
711 typedef void (*ResetProc)(void);
712 ResetProc proc;
6d2010ae 713 proc = HIB_ENTRYPOINT;
0c530ab8
A
714 // flush caches
715 __asm__("wbinvd");
3a60a9f5 716 proc();
b0d623f7
A
717#else
718// implement me
719#endif
3a60a9f5 720#endif
b0d623f7 721
3a60a9f5
A
722 return -1;
723}
6d2010ae
A
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
763typedef long ptrdiff_t;
764char const hibhex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
765#define hibhex2ascii(hex) (hibhex2ascii_data[hex])
766#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
767static size_t
768hibstrlen(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 */
785static char *
786ksprintn(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 */
834static int
835hibkvprintf(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;
874reswitch: 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;
1053handle_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;
1072handle_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);
1089number:
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
1147static void
1148putchar(int c, void *arg)
1149{
1150 (void)arg;
1151 uart_putc(c);
1152}
1153
1154void
1155hibprintf(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