Comment # 12 on bug 913885 from
Hi Bj�rn, 

Thanks for your dmesg on comment#5 and comment#6, it's VERY useful to check the
logic bug of e820 to nosave region.

(In reply to Bj�rn Voigt from comment #6)
> Created attachment 620573 [details]
> Dmesg output after suspend (Kernel 3.18.3-1.gc3e148f-desktop)

Looks there have bug in e820_mark_nosave_regions() make an misjudgment when the
e820 region doesn't align to PAGE_SIZE:

void __init e820_mark_nosave_regions(unsigned long limit_pfn)
{
        int i;
        unsigned long pfn = 0;

        for (i = 0; i < e820.nr_map; i++) {
                struct e820entry *ei = &e820.map[i];

                if (pfn < PFN_UP(ei->addr))
                        register_nosave_region(pfn, PFN_UP(ei->addr));    /*
register to nosave region if there have hole between 2 e820 entries */

                pfn = PFN_DOWN(ei->addr + ei->size);
[...]

The purpose of the above block in e820_mark_nosave_regions() is to compare the
end PFN of last region with the current region's start PFN. It used to find out
the hole between 2 e820 entries and register it to nosave regions list.

The above codes so far works when all e820 entries aligned to PAGE_SIZE, but
have bug on non-aligned e820 entries. For example from dmesg:

Aligned case:
[    0.000000] reserve setup_data: [mem 0x000000000270b658-0x00000000cbc4efff]
usable
[    0.000000] reserve setup_data: [mem 0x00000000cbc4f000-0x00000000cbc93fff]
ACPI NVS

PFN_DOWN (0xcbc4efff+1) = ((0xCBC4F000) >> PAGE_SHIFT) = 0xCBC4F
PFN_UP (0xcbc4f000) = (((0xcbc4f000) + PAGE_SIZE-1) >> PAGE_SHIFT) =
(0xcbc4f000 + 0x1000 - 1 >> PAGE_SHIFT) = 0xCBC4FFFF >> PAGE_SHIFT = 0xCBC4F

    if (0xCBC4F < 0xCBC4F)          /* NOT TRUE! */
        register_nosave_region(...);


Non-aligned case:
[    0.000000] reserve setup_data: [mem 0x0000000000100000-0x0000000002576017]
usable
[    0.000000] reserve setup_data: [mem 0x0000000002576018-0x0000000002585857]
usable

    PFN_DOWN (0x2576017+1) = ((0x2576018) >> PAGE_SHIFT) = 0x2576
    PFN_UP (0x2576018) = (((0x2576018) + PAGE_SIZE-1) >> PAGE_SHIFT) =
(0x2576018 + 0x1000 - 1 >> PAGE_SHIFT) = 0x2577017 >> PAGE_SHIFT = 0x2577

    if (0x2576 < 0x2577)                            /* TRUE! Misjudgment! */
        register_nosave_region(0x2576, 0x2577);     /* register to nosave
region */


Then why this issue happened randomly because the non-aligned e820 entries
generated by e820_reserve_setup_data(), setup data are allocated by kernel when
early boot stage. So the allocated address are random in usable region.

I think this is a old issue in code until I add patch to check the persistent
of e820 region between hibernate and resume. I am trying to make a patch to fix
this issue.


You are receiving this mail because: