[lkml]   [1999]   [Dec]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Subject2.3 Pagedir allocation/free and update races
    This note describes races in the procedures that allocate and free
    user level page directories. Platform code maintainers, please

    Prior to 2.3, a lot of architectures used to cache unused page
    directories to minimize copying the kernel level page tables
    from the swapper_pg_dir. 2.2 used to rely on the kernel lock
    for manipulating the cache list. In 2.3.31, page directories
    are allocated with the kernel lock, but not freed with this lock.
    So, all architectures that cache page directories have racy code.
    The i386 does not cache page directories in 2.3.31.

    In 2.2, set_pgdir() could rely on kernel_lock as it traversed the
    cached page directories while updating them. 2.2 set_pgdir() was
    racy in the sense that it could miss updating page directories
    that belonged to newly created processes that were still not on
    the active task list. This race exists in 2.3.31. To compound this
    race, there might be page directories that do not have active
    processes anymore due to optimized mm context switching.

    Partly to solve this problem, in 2.3.32, an active mm list has
    been added, that links up all the active mm's on the system.
    Page directory allocation and freeing happen at precisely the
    same times as elements are added and deleted from the active mm
    list. Also, to make sure that no page directory misses seeing
    updates by set_pgdir(), the pgd_alloc() call has been replaced
    by 3 different calls:

    a. get_pgd_fast(), which can not go to sleep since it is called
    with the mmlist spin lock held. Ideal for searching cached page
    directories for a free one.
    b. get_pgd_slow(), that is called without mmlist lock, can go to
    sleep, user level pgde's can be 0'ed out.
    c. get_pgd_uptopdate(), called on newly allocated pgdirs, with the
    mmlist lock held, to update kernel level pgde's. Cache lists may
    be updated, if in-use pgdirs are being cached.

    (Yes, alternate solutions are possible, this is the one that makes
    most sense globally).

    Also, pgd_free() is now called with mmlist lock held.

    Now, the mmlist lock can be used to implement a global (not percpu)
    cached list of page directories.

    For example, the mmlist lock has been used to restore pgd caching
    for i386. The i386 do_check_pgt_cache() also grabs the mmlist lock
    while freeing extra pgdirs.

    I also updated the code for these hooks for alpha, mips, ppc, sh
    and sparc64. Most of these had page caching, but did not have a
    lock to protect the cache. Now, they can use the mmlist lock for
    this. I have _NOT_ fixed the do_check_pgt_cache() to use
    mmlist_lock, which is needed for complete MP-safety.

    The arm, m68k and sparc code is a little more intricate, I would
    like the platform maintainers to take a look at these issues.

    I would like to hear back from at least one platform maintainer
    for each architecture (except i386), confirming that he will look
    into and fix this issue. Lets say by end of this week, by private
    mail. I am willing to review any changes. If you would like me to
    fix the code for you, let me know too. Else, I will have to grope
    through unfamiliar code, and send in changes to Linus without having
    any way to test the changes.

    Thanks a lot for taking the time to read this!


    PS: Look for mmlist_access_lock/mmlist_modify_lock/mmlist_set_pgdir
    for examples on how to use the lists and lock.

    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to
    Please read the FAQ at

     \ /
      Last update: 2005-03-22 13:55    [W:0.042 / U:21.880 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site