]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOHibernateRestoreKernel.c
280b8c430797371ea82b92a295faa70cff71f22d
[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 <crypto/aes.h>
36 #include <libkern/libkern.h>
37
38 #include "WKdm.h"
39 #include "IOHibernateInternal.h"
40
41 /*
42 This code is linked into the kernel but part of the "__HIB" section, which means
43 its used by code running in the special context of restoring the kernel text and data
44 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
45 it calls or references needs to be careful to only touch memory also in the "__HIB" section.
46 */
47
48 uint32_t gIOHibernateState;
49
50 uint32_t gIOHibernateDebugFlags;
51
52 static IOHibernateImageHeader _hibernateHeader;
53 IOHibernateImageHeader * gIOHibernateCurrentHeader = &_hibernateHeader;
54
55 static hibernate_graphics_t _hibernateGraphics;
56 hibernate_graphics_t * gIOHibernateGraphicsInfo = &_hibernateGraphics;
57
58 static hibernate_cryptwakevars_t _cryptWakeVars;
59 hibernate_cryptwakevars_t * gIOHibernateCryptWakeVars = &_cryptWakeVars;
60
61 vm_offset_t gIOHibernateWakeMap; // ppnum
62 vm_size_t gIOHibernateWakeMapSize;
63
64
65 #if CONFIG_SLEEP
66 #if defined(__i386__) || defined(__x86_64__)
67 extern void acpi_wake_prot_entry(void);
68 #endif
69 #endif
70
71 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
72
73 #if defined(__i386__) || defined(__x86_64__)
74
75 #define DBGLOG 1
76
77 #include <architecture/i386/pio.h>
78
79 /* standard port addresses */
80 enum {
81 COM1_PORT_ADDR = 0x3f8,
82 COM2_PORT_ADDR = 0x2f8
83 };
84
85 /* UART register offsets */
86 enum {
87 UART_RBR = 0, /* receive buffer Register (R) */
88 UART_THR = 0, /* transmit holding register (W) */
89 UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */
90 UART_IER = 1, /* interrupt enable register */
91 UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */
92 UART_IIR = 2, /* interrupt ident register (R) */
93 UART_FCR = 2, /* fifo control register (W) */
94 UART_LCR = 3, /* line control register */
95 UART_MCR = 4, /* modem control register */
96 UART_LSR = 5, /* line status register */
97 UART_MSR = 6, /* modem status register */
98 UART_SCR = 7 /* scratch register */
99 };
100
101 enum {
102 UART_LCR_8BITS = 0x03,
103 UART_LCR_DLAB = 0x80
104 };
105
106 enum {
107 UART_MCR_DTR = 0x01,
108 UART_MCR_RTS = 0x02,
109 UART_MCR_OUT1 = 0x04,
110 UART_MCR_OUT2 = 0x08,
111 UART_MCR_LOOP = 0x10
112 };
113
114 enum {
115 UART_LSR_DR = 0x01,
116 UART_LSR_OE = 0x02,
117 UART_LSR_PE = 0x04,
118 UART_LSR_FE = 0x08,
119 UART_LSR_THRE = 0x20
120 };
121
122 static void uart_putc(char c)
123 {
124 while (!(inb(COM1_PORT_ADDR + UART_LSR) & UART_LSR_THRE))
125 {}
126 outb(COM1_PORT_ADDR + UART_THR, c);
127 }
128
129 static int debug_probe( void )
130 {
131 /* Verify that the Scratch Register is accessible */
132 outb(COM1_PORT_ADDR + UART_SCR, 0x5a);
133 if (inb(COM1_PORT_ADDR + UART_SCR) != 0x5a) return false;
134 outb(COM1_PORT_ADDR + UART_SCR, 0xa5);
135 if (inb(COM1_PORT_ADDR + UART_SCR) != 0xa5) return false;
136 uart_putc('\n');
137 return true;
138 }
139
140 static void uart_puthex(uint64_t num)
141 {
142 int bit;
143 char c;
144 bool leading = true;
145
146 for (bit = 60; bit >= 0; bit -= 4)
147 {
148 c = 0xf & (num >> bit);
149 if (c)
150 leading = false;
151 else if (leading)
152 continue;
153 if (c <= 9)
154 c += '0';
155 else
156 c+= 'a' - 10;
157 uart_putc(c);
158 }
159 }
160
161 static void debug_code(uint32_t code, uint64_t value)
162 {
163 int bit;
164 char c;
165
166 if (!(kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags))
167 return;
168
169 for (bit = 24; bit >= 0; bit -= 8)
170 {
171 c = 0xFF & (code >> bit);
172 if (c)
173 uart_putc(c);
174 }
175 uart_putc('=');
176 uart_puthex(value);
177 uart_putc('\n');
178 uart_putc('\r');
179 }
180
181 #endif /* defined(__i386__) || defined(__x86_64__) */
182
183 #if !defined(DBGLOG)
184 #define debug_probe() (false)
185 #define debug_code(c, v) {}
186 #endif
187
188 enum
189 {
190 kIOHibernateRestoreCodeImageStart = 'imgS',
191 kIOHibernateRestoreCodeImageEnd = 'imgE',
192 kIOHibernateRestoreCodePageIndexStart = 'pgiS',
193 kIOHibernateRestoreCodePageIndexEnd = 'pgiE',
194 kIOHibernateRestoreCodeMapStart = 'mapS',
195 kIOHibernateRestoreCodeMapEnd = 'mapE',
196 kIOHibernateRestoreCodeWakeMapSize = 'wkms',
197 kIOHibernateRestoreCodeConflictPage = 'cfpg',
198 kIOHibernateRestoreCodeConflictSource = 'cfsr',
199 kIOHibernateRestoreCodeNoMemory = 'nomm'
200 };
201
202 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
203
204
205 static void fatal(void)
206 {
207 #if defined(__i386__) || defined(__x86_64__)
208 outb(0xcf9, 6);
209 #else
210 while (true) {}
211 #endif
212 }
213
214 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
215
216 uint32_t
217 hibernate_sum_page(uint8_t *buf, uint32_t ppnum)
218 {
219 return (((uint32_t *)buf)[((PAGE_SIZE >> 2) - 1) & ppnum]);
220 }
221
222 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
223
224 static hibernate_bitmap_t *
225 hibernate_page_bitmap(hibernate_page_list_t * list, uint32_t page)
226 {
227 uint32_t bank;
228 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
229
230 for (bank = 0; bank < list->bank_count; bank++)
231 {
232 if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
233 break;
234 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
235 }
236 if (bank == list->bank_count)
237 bitmap = NULL;
238
239 return (bitmap);
240 }
241
242 hibernate_bitmap_t *
243 hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * pPage)
244 {
245 uint32_t bank, page = *pPage;
246 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
247
248 for (bank = 0; bank < list->bank_count; bank++)
249 {
250 if (page <= bitmap->first_page)
251 {
252 *pPage = bitmap->first_page;
253 break;
254 }
255 if (page <= bitmap->last_page)
256 break;
257 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
258 }
259 if (bank == list->bank_count)
260 bitmap = NULL;
261
262 return (bitmap);
263 }
264
265 void
266 hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page)
267 {
268 hibernate_bitmap_t * bitmap;
269
270 bitmap = hibernate_page_bitmap(list, page);
271 if (bitmap)
272 {
273 page -= bitmap->first_page;
274 if (set)
275 bitmap->bitmap[page >> 5] |= (0x80000000 >> (page & 31));
276 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
277 else
278 bitmap->bitmap[page >> 5] &= ~(0x80000000 >> (page & 31));
279 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
280 }
281 }
282
283 boolean_t
284 hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page)
285 {
286 boolean_t result = TRUE;
287 hibernate_bitmap_t * bitmap;
288
289 bitmap = hibernate_page_bitmap(list, page);
290 if (bitmap)
291 {
292 page -= bitmap->first_page;
293 result = (0 != (bitmap->bitmap[page >> 5] & (0x80000000 >> (page & 31))));
294 }
295 return (result);
296 }
297
298 // count bits clear or set (set == TRUE) starting at page.
299 uint32_t
300 hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page)
301 {
302 uint32_t index, bit, bits;
303 uint32_t count;
304
305 count = 0;
306
307 index = (page - bitmap->first_page) >> 5;
308 bit = (page - bitmap->first_page) & 31;
309
310 bits = bitmap->bitmap[index];
311 if (set)
312 bits = ~bits;
313 bits = (bits << bit);
314 if (bits)
315 count += __builtin_clz(bits);
316 else
317 {
318 count += 32 - bit;
319 while (++index < bitmap->bitmapwords)
320 {
321 bits = bitmap->bitmap[index];
322 if (set)
323 bits = ~bits;
324 if (bits)
325 {
326 count += __builtin_clz(bits);
327 break;
328 }
329 count += 32;
330 }
331 }
332
333 return (count);
334 }
335
336 static vm_offset_t
337 hibernate_page_list_grab(hibernate_page_list_t * list, uint32_t * pNextFree)
338 {
339 uint32_t nextFree = *pNextFree;
340 uint32_t nextFreeInBank;
341 hibernate_bitmap_t * bitmap;
342
343 nextFreeInBank = nextFree + 1;
344 while ((bitmap = hibernate_page_bitmap_pin(list, &nextFreeInBank)))
345 {
346 nextFreeInBank += hibernate_page_bitmap_count(bitmap, FALSE, nextFreeInBank);
347 if (nextFreeInBank <= bitmap->last_page)
348 {
349 *pNextFree = nextFreeInBank;
350 break;
351 }
352 }
353
354 if (!bitmap)
355 {
356 debug_code(kIOHibernateRestoreCodeNoMemory, nextFree);
357 fatal();
358 nextFree = 0;
359 }
360
361 return (nextFree);
362 }
363
364 static uint32_t
365 store_one_page(uint32_t procFlags, uint32_t * src, uint32_t compressedSize,
366 uint32_t * buffer, uint32_t ppnum)
367 {
368 uint64_t dst;
369 uint32_t sum;
370
371 dst = ptoa_64(ppnum);
372 if (ppnum < 0x00100000)
373 buffer = (uint32_t *) (uintptr_t) dst;
374
375 if (compressedSize != PAGE_SIZE)
376 {
377 WKdm_decompress((WK_word*) src, (WK_word*) buffer, PAGE_SIZE >> 2);
378 src = buffer;
379 }
380
381 sum = hibernate_sum_page((uint8_t *) src, ppnum);
382
383 if (((uint64_t) (uintptr_t) src) == dst)
384 src = 0;
385
386 hibernate_restore_phys_page((uint64_t) (uintptr_t) src, dst, PAGE_SIZE, procFlags);
387
388 return (sum);
389 }
390
391 // used only for small struct copies
392 static void
393 bcopy_internal(const void *src, void *dst, uint32_t len)
394 {
395 const char *s = src;
396 char *d = dst;
397 uint32_t idx = 0;
398
399 while (idx < len)
400 {
401 d[idx] = s[idx];
402 idx++;
403 }
404 }
405
406 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
407
408 long
409 hibernate_kernel_entrypoint(IOHibernateImageHeader * header,
410 void * p2, void * p3, void * p4)
411 {
412 uint32_t idx;
413 uint32_t * src;
414 uint32_t * buffer;
415 uint32_t * pageIndexSource;
416 hibernate_page_list_t * map;
417 uint32_t count;
418 uint32_t ppnum;
419 uint32_t page;
420 uint32_t conflictCount;
421 uint32_t compressedSize;
422 uint32_t uncompressedPages;
423 uint32_t copyPageListHead;
424 uint32_t * copyPageList;
425 uint32_t copyPageIndex;
426 uint32_t sum;
427 uint32_t nextFree;
428 uint32_t lastImagePage;
429 uint32_t lastMapPage;
430 uint32_t lastPageIndexPage;
431
432 C_ASSERT(sizeof(IOHibernateImageHeader) == 512);
433
434 if ((kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags) && !debug_probe())
435 gIOHibernateDebugFlags &= ~kIOHibernateDebugRestoreLogs;
436
437 debug_code(kIOHibernateRestoreCodeImageStart, (uintptr_t) header);
438
439 bcopy_internal(header,
440 gIOHibernateCurrentHeader,
441 sizeof(IOHibernateImageHeader));
442
443 if (!p2)
444 {
445 count = header->graphicsInfoOffset;
446 if (count)
447 p2 = (void *)(((uintptr_t) header) - count);
448 }
449 if (p2)
450 bcopy_internal(p2,
451 gIOHibernateGraphicsInfo,
452 sizeof(hibernate_graphics_t));
453 else
454 gIOHibernateGraphicsInfo->physicalAddress = gIOHibernateGraphicsInfo->depth = 0;
455
456 if (!p3)
457 {
458 count = header->cryptVarsOffset;
459 if (count)
460 p3 = (void *)(((uintptr_t) header) - count);
461 }
462 if (p3)
463 bcopy_internal(p3,
464 gIOHibernateCryptWakeVars,
465 sizeof(hibernate_cryptwakevars_t));
466
467 src = (uint32_t *)
468 (((uintptr_t) &header->fileExtentMap[0])
469 + header->fileExtentMapSize
470 + ptoa_32(header->restore1PageCount));
471
472 if (header->previewSize)
473 {
474 pageIndexSource = src;
475 map = (hibernate_page_list_t *)(((uintptr_t) pageIndexSource) + header->previewSize);
476 src = (uint32_t *) (((uintptr_t) pageIndexSource) + header->previewPageListSize);
477 }
478 else
479 {
480 pageIndexSource = 0;
481 map = (hibernate_page_list_t *) src;
482 src = (uint32_t *) (((uintptr_t) map) + header->bitmapSize);
483 }
484
485 lastPageIndexPage = atop_32((uintptr_t) src);
486
487 lastImagePage = atop_32(((uintptr_t) header) + header->image1Size);
488
489 lastMapPage = atop_32(((uintptr_t) map) + header->bitmapSize);
490
491 debug_code(kIOHibernateRestoreCodeImageEnd, ptoa_64(lastImagePage));
492 debug_code(kIOHibernateRestoreCodePageIndexStart, (uintptr_t) pageIndexSource);
493 debug_code(kIOHibernateRestoreCodePageIndexEnd, ptoa_64(lastPageIndexPage));
494 debug_code(kIOHibernateRestoreCodeMapStart, (uintptr_t) map);
495 debug_code(kIOHibernateRestoreCodeMapEnd, ptoa_64(lastMapPage));
496
497 // knock all the image pages to be used out of free map
498 for (ppnum = atop_32((uintptr_t) header); ppnum <= lastImagePage; ppnum++)
499 {
500 hibernate_page_bitset(map, FALSE, ppnum);
501 }
502
503 nextFree = 0;
504 hibernate_page_list_grab(map, &nextFree);
505 buffer = (uint32_t *) (uintptr_t) ptoa_32(hibernate_page_list_grab(map, &nextFree));
506
507 if (header->memoryMapSize && (count = header->memoryMapOffset))
508 {
509 p4 = (void *)(((uintptr_t) header) - count);
510 gIOHibernateWakeMap = hibernate_page_list_grab(map, &nextFree);
511 gIOHibernateWakeMapSize = header->memoryMapSize;
512 debug_code(kIOHibernateRestoreCodeWakeMapSize, gIOHibernateWakeMapSize);
513 if (gIOHibernateWakeMapSize > PAGE_SIZE)
514 fatal();
515 bcopy_internal(p4, (void *) (uintptr_t) ptoa_32(gIOHibernateWakeMap), gIOHibernateWakeMapSize);
516 }
517 else
518 gIOHibernateWakeMapSize = 0;
519
520 sum = gIOHibernateCurrentHeader->actualRestore1Sum;
521 gIOHibernateCurrentHeader->diag[0] = (uint32_t)(uintptr_t) header;
522 gIOHibernateCurrentHeader->diag[1] = sum;
523
524 uncompressedPages = 0;
525 conflictCount = 0;
526 copyPageListHead = 0;
527 copyPageList = 0;
528 copyPageIndex = PAGE_SIZE >> 2;
529
530 compressedSize = PAGE_SIZE;
531
532 while (1)
533 {
534 if (pageIndexSource)
535 {
536 ppnum = pageIndexSource[0];
537 count = pageIndexSource[1];
538 pageIndexSource += 2;
539 if (!count)
540 {
541 pageIndexSource = 0;
542 src = (uint32_t *) (((uintptr_t) map) + gIOHibernateCurrentHeader->bitmapSize);
543 ppnum = src[0];
544 count = src[1];
545 src += 2;
546 }
547 }
548 else
549 {
550 ppnum = src[0];
551 count = src[1];
552 if (!count)
553 break;
554 src += 2;
555 }
556
557 for (page = 0; page < count; page++, ppnum++)
558 {
559 uint32_t tag;
560 int conflicts;
561
562 if (!pageIndexSource)
563 {
564 tag = *src++;
565 compressedSize = kIOHibernateTagLength & tag;
566 }
567
568 conflicts = (((ppnum >= atop_32((uintptr_t) map)) && (ppnum <= lastMapPage))
569 || ((ppnum >= atop_32((uintptr_t) src)) && (ppnum <= lastImagePage)));
570
571 if (pageIndexSource)
572 conflicts |= ((ppnum >= atop_32((uintptr_t) pageIndexSource)) && (ppnum <= lastPageIndexPage));
573
574 if (!conflicts)
575 {
576 if (compressedSize)
577 sum += store_one_page(gIOHibernateCurrentHeader->processorFlags,
578 src, compressedSize, buffer, ppnum);
579 uncompressedPages++;
580 }
581 else
582 {
583 uint32_t bufferPage;
584 uint32_t * dst;
585
586 // debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
587 // debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
588
589 conflictCount++;
590
591 // alloc new buffer page
592 bufferPage = hibernate_page_list_grab(map, &nextFree);
593
594 if (copyPageIndex > ((PAGE_SIZE >> 2) - 3))
595 {
596 // alloc new copy list page
597 uint32_t pageListPage = hibernate_page_list_grab(map, &nextFree);
598 // link to current
599 if (copyPageList)
600 copyPageList[1] = pageListPage;
601 else
602 copyPageListHead = pageListPage;
603 copyPageList = (uint32_t *) (uintptr_t) ptoa_32(pageListPage);
604 copyPageList[1] = 0;
605 copyPageIndex = 2;
606 }
607
608 copyPageList[copyPageIndex++] = ppnum;
609 copyPageList[copyPageIndex++] = bufferPage;
610 copyPageList[copyPageIndex++] = compressedSize;
611 copyPageList[0] = copyPageIndex;
612
613 dst = (uint32_t *) (uintptr_t) ptoa_32(bufferPage);
614 for (idx = 0; idx < ((compressedSize + 3) >> 2); idx++)
615 dst[idx] = src[idx];
616 }
617 src += ((compressedSize + 3) >> 2);
618 }
619 }
620
621 // -- copy back conflicts
622
623 copyPageList = (uint32_t *)(uintptr_t) ptoa_32(copyPageListHead);
624 while (copyPageList)
625 {
626 for (copyPageIndex = 2; copyPageIndex < copyPageList[0]; copyPageIndex += 3)
627 {
628 ppnum = copyPageList[copyPageIndex + 0];
629 src = (uint32_t *) (uintptr_t) ptoa_32(copyPageList[copyPageIndex + 1]);
630 compressedSize = copyPageList[copyPageIndex + 2];
631
632 sum += store_one_page(gIOHibernateCurrentHeader->processorFlags,
633 src, compressedSize, buffer, ppnum);
634 uncompressedPages++;
635 }
636 copyPageList = (uint32_t *) (uintptr_t) ptoa_32(copyPageList[1]);
637 }
638
639 // -- image has been destroyed...
640
641 gIOHibernateCurrentHeader->actualImage1Sum = sum;
642 gIOHibernateCurrentHeader->actualUncompressedPages = uncompressedPages;
643 gIOHibernateCurrentHeader->conflictCount = conflictCount;
644 gIOHibernateCurrentHeader->nextFree = nextFree;
645
646 gIOHibernateState = kIOHibernateStateWakingFromHibernate;
647
648 #if CONFIG_SLEEP
649 #if defined(__ppc__)
650 typedef void (*ResetProc)(void);
651 ResetProc proc;
652 proc = (ResetProc) 0x100;
653 __asm__ volatile("ori 0, 0, 0" : : );
654 proc();
655 #elif defined(__i386__) || defined(__x86_64__)
656 typedef void (*ResetProc)(void);
657 ResetProc proc;
658 proc = (ResetProc) acpi_wake_prot_entry;
659 // flush caches
660 __asm__("wbinvd");
661 proc();
662 #else
663 // implement me
664 #endif
665 #endif
666
667 return -1;
668 }