Date: Wed, 10 Jun 2020 23:03:35 +0000 (UTC) From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362034 - head/sys/powerpc/booke Message-ID: <202006102303.05AN3Zdh042897@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhibbits Date: Wed Jun 10 23:03:35 2020 New Revision: 362034 URL: https://svnweb.freebsd.org/changeset/base/362034 Log: powerpc/pmap: Fix pte_find_next() iterators for booke64 pmap After r361988 fixed the reference count leak on booke64, it became possible for an iteration somewhere in the middle of a page to become stale, with the page vanishing (correctly) due to all PTEs on that page going away. pte_find_next() would start at that iterator, and move along 'higher' order directory pages until it finds a valid one, without zeroing out the lower order pages. For instance: /* Find next pte at or above 0x10002000. */ pte = pte_find_next(pmap, &(0x10002000)); pte_remove(pmap, pte); /* This pte was the last reference in the page table page, page is * gone. */ pte = pte_find_next(pmap, 0x10002000); /* pte_find_next will see 0x10002000's page is gone, and jump to the * next one, but starting iteration at the '0x2000' slot, skipping * 0x0000 and 0x1000. */ This caused some processes, like git, to trip the KASSERT() in pmap_release(). Fix this by zeroing all lower order iterators at each level. Modified: head/sys/powerpc/booke/pmap_64.c Modified: head/sys/powerpc/booke/pmap_64.c ============================================================================== --- head/sys/powerpc/booke/pmap_64.c Wed Jun 10 22:30:32 2020 (r362033) +++ head/sys/powerpc/booke/pmap_64.c Wed Jun 10 23:03:35 2020 (r362034) @@ -220,12 +220,13 @@ pte_find_next(pmap_t pmap, vm_offset_t *pva) k = PDIR_IDX(va); l = PTBL_IDX(va); pm_root = pmap->pm_root; + /* truncate the VA for later. */ va &= ~((1UL << (PG_ROOT_H + 1)) - 1); - for (; i < PG_ROOT_NENTRIES; i++, j = 0) { + for (; i < PG_ROOT_NENTRIES; i++, j = 0, k = 0, l = 0) { if (pm_root[i] == 0) continue; - for (; j < PDIR_L1_NENTRIES; j++, k = 0) { + for (; j < PDIR_L1_NENTRIES; j++, k = 0, l = 0) { if (pm_root[i][j] == 0) continue; for (; k < PDIR_NENTRIES; k++, l = 0) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006102303.05AN3Zdh042897>