[alc at FreeBSD.org: cvs commit: src/sys/vm vm_page.c vm_pageout.c]

Matthew Dillon dillon at apollo.backplane.com
Sat Feb 14 02:51:41 PST 2004

    Thanks for the head's up, Xin.

    Alan, when I looked into this a bit more deeply I think there is an
    even more serious problem which still needs to be fixed.  The problem
    is that the PTE entry on the foreign cpu may be loaded into the 
    foreign CPU's TLB.  When pmap_remove_all() recurses through removing
    the pte from the various page tables it calls loadandclear(pte), but
    this is not sufficient to synchronize TLB on the target cpu.  The
    TLB invalidate done later is far too late (and, in fact, there is no
    way an asynch TLB invalidate could ever be used to solve this problem).

    I think there is a window of opportunity either (A) where a TLB entry
    on the target cpu is dirtied and written back to memory (the page table)
    *AFTER* the current cpu has cleared the entry, or (B) where the TLB
    entry on the target cpu is valid and the target cpu modifies the page,
    but races with our loadandclear() and gets entirely lost, resulting in
    a dirty page winding up in the cache queue without either the software
    or the hardware realizing that it's dirty.

    (A) is the more serious scenario because PG_ZERO is set on page table
    pages which are freed (after having been cleared by the pmap subsystem),
    and if this race occurs the page in question will not in fact be 
    completely zero'd.

    I don't think the TLB snoops the bus.  If it doesn't, then scenario (A)
    can occur.  If the TLB performs a RMW to update the dirty bit the page
    table entry still winds up not being zero'd.  If it performs a 
    writeback then the table entry we just zero'd could be updated by
    a foreign cpu issuing a TLB writeback when going from clean->dirty.

    The problem appears to exist not only for shared page tables, but also
    for private page tables which share the page in question.  I don't see
    an easy solution... not even making the page read-only is sufficient
    to prevent the race becaue we still have the TLB writeback problem
    while trying to make the page read-only.

    What do you think?

					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

:Please take a look at the following commit, as well as
:Hope this is helpful :)
:Best regards,
:Xin LI <delphij frontfree net>	http://www.delphij.net/
:See complete headers for GPG key and other information.
:----- Forwarded message from Alan Cox <alc at xxxxxxxxxxx> -----
:Date: Sat, 14 Feb 2004 00:54:38 -0800 (PST)
:From: Alan Cox <alc at xxxxxxxxxxx>
:alc         2004/02/14 00:54:38 PST
:  FreeBSD src repository
:  Modified files:
:    sys/vm               vm_page.c vm_pageout.c=20
:  Log:
:   - Correct a long-standing race condition in vm_page_try_to_cache() that
:     could result in a panic "vm_page_cache: caching a dirty page, ...":
:     Access to the page must be restricted or removed before calling
:     vm_page_cache().  This race condition is identical in nature to that
:     which was addressed by vm_pageout.c's revision 1.251.
:   - Simplify the code surrounding the fix to this same race condition
:     in vm_pageout.c's revision 1.251.  There should be no behavioral
:     change.  Reviewed by: tegge
: =20
:  MFC after:      7 days
: =20
:  Revision  Changes    Path
:  1.275     +1 -1      src/sys/vm/vm_page.c
:  1.252     +2 -3      src/sys/vm/vm_pageout.c

More information about the Bugs mailing list