aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/setup.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index dd6b0e3386ce..e6023970aa40 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -48,6 +48,7 @@
48#include <linux/crash_dump.h> 48#include <linux/crash_dump.h>
49#include <linux/dmi.h> 49#include <linux/dmi.h>
50#include <linux/pfn.h> 50#include <linux/pfn.h>
51#include <linux/suspend.h>
51 52
52#include <video/edid.h> 53#include <video/edid.h>
53 54
@@ -1434,6 +1435,111 @@ static void set_mca_bus(int x)
1434static void set_mca_bus(int x) { } 1435static void set_mca_bus(int x) { }
1435#endif 1436#endif
1436 1437
1438#ifdef CONFIG_SOFTWARE_SUSPEND
1439static void __init mark_nosave_page_range(unsigned long start, unsigned long end)
1440{
1441 struct page *page;
1442 while (start <= end) {
1443 page = pfn_to_page(start);
1444 SetPageNosave(page);
1445 start++;
1446 }
1447}
1448
1449static void __init e820_nosave_reserved_pages(void)
1450{
1451 int i;
1452 unsigned long r_start = 0, r_end = 0;
1453
1454 /* Assume e820 map is sorted */
1455 for (i = 0; i < e820.nr_map; i++) {
1456 struct e820entry *ei = &e820.map[i];
1457 unsigned long start, end;
1458
1459 start = PFN_DOWN(ei->addr);
1460 end = PFN_UP(ei->addr + ei->size);
1461 if (start >= end)
1462 continue;
1463 if (ei->type == E820_RESERVED)
1464 continue;
1465 r_end = start;
1466 /*
1467 * Highmem 'Reserved' pages are marked as reserved, swsusp
1468 * will not save/restore them, so we ignore these pages here.
1469 */
1470 if (r_end > max_low_pfn)
1471 r_end = max_low_pfn;
1472 if (r_end > r_start)
1473 mark_nosave_page_range(r_start, r_end-1);
1474 if (r_end >= max_low_pfn)
1475 break;
1476 r_start = end;
1477 }
1478}
1479
1480static void __init e820_save_acpi_pages(void)
1481{
1482 int i;
1483
1484 /* Assume e820 map is sorted */
1485 for (i = 0; i < e820.nr_map; i++) {
1486 struct e820entry *ei = &e820.map[i];
1487 unsigned long start, end;
1488
1489 start = ei->addr;
1490 end = ei->addr + ei->size;
1491 if (start >= end)
1492 continue;
1493 if (ei->type != E820_ACPI && ei->type != E820_NVS)
1494 continue;
1495 /*
1496 * If the region is below max_low_pfn, it will be
1497 * saved/restored by swsusp follow 'RAM' type.
1498 */
1499 if (start < (max_low_pfn << PAGE_SHIFT))
1500 start = max_low_pfn << PAGE_SHIFT;
1501 /*
1502 * Highmem pages (ACPI NVS/Data) are reserved, but swsusp
1503 * highmem save/restore will not save/restore them. We marked
1504 * them as arch saveable pages here
1505 */
1506 if (end > start)
1507 swsusp_add_arch_pages(start, end);
1508 }
1509}
1510
1511extern char __start_rodata, __end_rodata;
1512/*
1513 * BIOS reserved region/hole - no save/restore
1514 * ACPI NVS - save/restore
1515 * ACPI Data - this is a little tricky, the mem could be used by OS after OS
1516 * reads tables from the region, but anyway save/restore the memory hasn't any
1517 * side effect and Linux runtime module load/unload might use it.
1518 * kernel rodata - no save/restore (kernel rodata isn't changed)
1519 */
1520static int __init mark_nosave_pages(void)
1521{
1522 unsigned long pfn_start, pfn_end;
1523
1524 /* FIXME: provide a version for efi BIOS */
1525 if (efi_enabled)
1526 return 0;
1527 /* BIOS reserved regions & holes */
1528 e820_nosave_reserved_pages();
1529
1530 /* kernel rodata */
1531 pfn_start = PFN_UP(virt_to_phys(&__start_rodata));
1532 pfn_end = PFN_DOWN(virt_to_phys(&__end_rodata));
1533 mark_nosave_page_range(pfn_start, pfn_end-1);
1534
1535 /* record ACPI Data/NVS as saveable */
1536 e820_save_acpi_pages();
1537
1538 return 0;
1539}
1540core_initcall(mark_nosave_pages);
1541#endif
1542
1437/* 1543/*
1438 * Determine if we were loaded by an EFI loader. If so, then we have also been 1544 * Determine if we were loaded by an EFI loader. If so, then we have also been
1439 * passed the efi memmap, systab, etc., so we should use these data structures 1545 * passed the efi memmap, systab, etc., so we should use these data structures