Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Apr 2012 15:08:25 -0400
From:      Ewart Tempest <etempest@juniper.net>
To:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Cc:        Tony Lanza <tlanza@juniper.net>, Ewart Tempest <etempest@juniper.net>
Subject:   Corrupted pmap pm_vlist - pmap_remove_pte()
Message-ID:  <A4C6A166C36F5F40A5767E6F66358FC0BB8B0B9681@EMBX01-WF.jnpr.net>

next in thread | raw e-mail | index | archive | help
In FreeBSD 6.*, we have been seeing crashes in pmap_remove_pages() that onl=
y seem to occur in scaling scenarios:

2564    #ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
2565                    pte =3D vtopte(pv->pv_va);
2566    #else
2567                    pte =3D pmap_pte(pmap, pv->pv_va);
2568    #endif
2569                    tpte =3D *pte; <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D page fault here

The suspicion is that the pmap's pm_pvlist list is getting corrupted. To th=
is end, I have a question on the following logic in pmap_remove_pte() (see =
in-line comment):

   1533 static int
   1534 pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va, pd_en=
try_t ptepde)
   1535 {
   1536 	pt_entry_t oldpte;
   1537 	vm_page_t m;
   1538=20
   1539 	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
   1540 	oldpte =3D pte_load_clear(ptq);
   1541 	if (oldpte & PG_W)
   1542 		pmap->pm_stats.wired_count -=3D 1;
   1543 	/*
   1544 	 * Machines that don't support invlpg, also don't support
   1545 	 * PG_G.
   1546 	 */
   1547 	if (oldpte & PG_G)
   1548 		pmap_invalidate_page(kernel_pmap, va);
   1549 	pmap->pm_stats.resident_count -=3D 1;
   1550 	if (oldpte & PG_MANAGED) {
   1551 		m =3D PHYS_TO_VM_PAGE(oldpte & PG_FRAME);
   1552 		if (oldpte & PG_M) {
   1553 #if defined(PMAP_DIAGNOSTIC)
   1554 			if (pmap_nw_modified((pt_entry_t) oldpte)) {
   1555 				printf(
   1556 	"pmap_remove: modified page not writable: va: 0x%lx, pte: 0x%lx\n"=
,
   1557 				    va, oldpte);
   1558 			}
   1559 #endif
   1560 			if (pmap_track_modified(va))
   1561 				vm_page_dirty(m);
   1562 		}
   1563 		if (oldpte & PG_A)
   1564 			vm_page_flag_set(m, PG_REFERENCED);
   1565 		pmap_remove_entry(pmap, m, va);
   1566 	}
   1567 	return (pmap_unuse_pt(pmap, va, ptepde)); <=3D=3D=3D=3D=3D=3D=3D *=
** under what circumstances is it valid to free the page but not remove it =
from the pmap's pm_vlist? Even the code comment for pmap_unuse_pt() commenc=
es "After removing a page table entry ... ". ***
   1568 }

If the tail end of the above function is changed as follows:

   1565 		pmap_remove_entry(pmap, m, va);
   1565.5 	      return (pmap_unuse_pt(pmap, va, ptepde));
   1566 	}
   1567 	return (0);

Then we don't see any crashes ... but is it the right thing to do?

Ewart



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?A4C6A166C36F5F40A5767E6F66358FC0BB8B0B9681>