• R
    [PATCH] x86_64: Set up safe page tables during resume · 3dd08325
    Rafael J. Wysocki 提交于
    The following patch makes swsusp avoid the possible temporary corruption
    of page translation tables during resume on x86-64.  This is achieved by
    creating a copy of the relevant page tables that will not be modified by
    swsusp and can be safely used by it on resume.
    
    The problem is that during resume on x86-64 swsusp may temporarily
    corrupt the page tables used for the direct mapping of RAM.  If that
    happens, a page fault occurs and cannot be handled properly, which leads
    to the solid hang of the affected system.  This leads to the loss of the
    system's state from before suspend and may result in the loss of data or
    the corruption of filesystems, so it is a serious issue.  Also, it
    appears to happen quite often (for me, as often as 50% of the time).
    
    The problem is related to the fact that (at least) one of the PMD
    entries used in the direct memory mapping (starting at PAGE_OFFSET)
    points to a page table the physical address of which is much greater
    than the physical address of the PMD entry itself.  Moreover,
    unfortunately, the physical address of the page table before suspend
    (i.e.  the one stored in the suspend image) happens to be different to
    the physical address of the corresponding page table used during resume
    (i.e.  the one that is valid right before swsusp_arch_resume() in
    arch/x86_64/kernel/suspend_asm.S is executed).  Thus while the image is
    restored, the "offending" PMD entry gets overwritten, so it does not
    point to the right physical address any more (i.e.  there's no page
    table at the address pointed to by it, because it points to the address
    the page table has been at during suspend).  Consequently, if the PMD
    entry is used later on, and it _is_ used in the process of copying the
    image pages, a page fault occurs, but it cannot be handled in the normal
    way and the system hangs.
    
    In principle we can call create_resume_mapping() from
    swsusp_arch_resume() (ie.  from suspend_asm.S), but then the memory
    allocations in create_resume_mapping(), resume_pud_mapping(), and
    resume_pmd_mapping() must be made carefully so that we use _only_
    NosaveFree pages in them (the other pages are overwritten by the loop in
    swsusp_arch_resume()).  Additionally, we are in atomic context at that
    time, so we cannot use GFP_KERNEL.  Moreover, if one of the allocations
    fails, we should free all of the allocated pages, so we need to trace
    them somehow.
    
    All of this is done in the appended patch, except that the functions
    populating the page tables are located in arch/x86_64/kernel/suspend.c
    rather than in init.c.  It may be done in a more elegan way in the
    future, with the help of some swsusp patches that are in the works now.
    
    [AK: move some externs into headers, renamed a function]
    Signed-off-by: NRafael J. Wysocki <rjw@sisk.pl>
    Signed-off-by: NAndi Kleen <ak@suse.de>
    Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
    3dd08325
suspend.h 1.9 KB