diff options
author | cperciva <cperciva@FreeBSD.org> | 2010-11-25 22:06:07 +0000 |
---|---|---|
committer | cperciva <cperciva@FreeBSD.org> | 2010-11-25 22:06:07 +0000 |
commit | 2b320b89cfe0888454773412b8c48f36acf6c79a (patch) | |
tree | 35c7cac6d06bd71b7677d6c801cd680507efd42a | |
parent | 701321ab36df75b6ea907f1457e0e7e2a626f6d6 (diff) | |
download | FreeBSD-src-2b320b89cfe0888454773412b8c48f36acf6c79a.zip FreeBSD-src-2b320b89cfe0888454773412b8c48f36acf6c79a.tar.gz |
Revert r215819 and fix the bug properly. In pmap_qremove, paging table
updates were being queued by pmap_kremove, but the queue wasn't being
flushed; as a result, the updates didn't happen until *after* the call
to pmap_invalidate_range, and old entries could stick around in the TLB.
Adding a PT_UPDATES_FLUSH() call immediately before pmap_invalidate_range
ensures that after the invalidation the TLB will be repopulated with the
correct new entries.
Thanks to: kib, avg, alc
-rw-r--r-- | sys/i386/xen/pmap.c | 13 |
1 files changed, 1 insertions, 12 deletions
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 7671dd9..b63089d 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -1292,19 +1292,7 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) mclp->args[0] = va; mclp->args[1] = (uint32_t)(pa & 0xffffffff); mclp->args[2] = (uint32_t)(pa >> 32); -#if 0 mclp->args[3] = (*pte & PG_V) ? UVMF_INVLPG|UVMF_ALL : 0; -#else - /* - * Somehow we seem to be ending up with pages which are in - * the TLB in spite of not having PG_V set, resulting in - * pages newly loaded into the bufcache not showing up - * immediately (i.e., accessing them provides the old data). - * As a workaround, always perform a TLB flush, even if the - * old page didn't have PG_V. - */ - mclp->args[3] = UVMF_INVLPG|UVMF_ALL; -#endif va += PAGE_SIZE; pte++; @@ -1348,6 +1336,7 @@ pmap_qremove(vm_offset_t sva, int count) pmap_kremove(va); va += PAGE_SIZE; } + PT_UPDATES_FLUSH(); pmap_invalidate_range(kernel_pmap, sva, va); critical_exit(); vm_page_unlock_queues(); |