Date: Sat, 04 Jun 2016 10:51:08 -0700 From: Matthew Macy <mmacy@nextbsd.org> To: "Konstantin Belousov" <kostikbel@gmail.com> Cc: "Michael Butler" <imb@protected-networks.net>, "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>, "<alc@freebsd.org>" <alc@freebsd.org> Subject: Re: repeatable panic on pageout with 945GM Message-ID: <1551c8a3732.cbde57d0124455.2726151520830111171@nextbsd.org> In-Reply-To: <20160604174745.GB38613@kib.kiev.ua> References: <2490f1c7-8153-ece3-49ed-4b3886564fd7@protected-networks.net> <da19738b-6bf1-10a3-4428-43b6095ec35a@protected-networks.net> <205d4423-b834-9a21-785f-fa15d44c78ec@protected-networks.net> <CAHM0Q_PR5Aoak6A7f=tsRy0DJFCmLDVfRGpceZ0mXU3P%2BxO8DA@mail.gmail.com> <1551419a1db.12929035f45012.326107747932338888@nextbsd.org> <939f9d2b-e925-e8e0-0ff3-8d90623728c6@protected-networks.net> <1551c5dbd86.c68532b5123717.566503881838650848@nextbsd.org> <20160604174745.GB38613@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
>
> I believe that this is a bug in amd64 pmap. Fictitious pages are not
> promoted, in particular, the pv_table array does not span over the
> dynamically registered fictitious ranges. As result, pa_to_pvh() returns
> garbage and pvh must not be accessed in the case of 'small_mappings' in
> several pmap functions. It is typically not accessed, except in case
> when we have to drop and reacquire pv lock, to avoid LOR with pmap.
Cool. Thanks for explaining that.
-M
> i386 does not have the issue, due to pvh_global_lock.
>
> Below is the supposed fix (not tested).
>
> diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
> index 7a93e76..e514b07 100644
> --- a/sys/amd64/amd64/pmap.c
> +++ b/sys/amd64/amd64/pmap.c
> @@ -3947,12 +3947,14 @@ small_mappings:
> while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
> pmap = PV_PMAP(pv);
> if (!PMAP_TRYLOCK(pmap)) {
> - pvh_gen = pvh->pv_gen;
> + if ((m->flags & PG_FICTITIOUS) == 0)
> + pvh_gen = pvh->pv_gen;
> md_gen = m->md.pv_gen;
> rw_wunlock(lock);
> PMAP_LOCK(pmap);
> rw_wlock(lock);
> - if (pvh_gen != pvh->pv_gen || md_gen != m->md.pv_gen) {
> + if (((m->flags & PG_FICTITIOUS) == 0 &&
> + pvh_gen != pvh->pv_gen) || md_gen != m->md.pv_gen) {
> rw_wunlock(lock);
> PMAP_UNLOCK(pmap);
> goto retry;
> @@ -5775,13 +5777,14 @@ small_mappings:
> TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
> pmap = PV_PMAP(pv);
> if (!PMAP_TRYLOCK(pmap)) {
> - pvh_gen = pvh->pv_gen;
> + if ((m->flags & PG_FICTITIOUS) == 0)
> + pvh_gen = pvh->pv_gen;
> md_gen = m->md.pv_gen;
> rw_wunlock(lock);
> PMAP_LOCK(pmap);
> rw_wlock(lock);
> - if (pvh_gen != pvh->pv_gen ||
> - md_gen != m->md.pv_gen) {
> + if (((m->flags & PG_FICTITIOUS) == 0 &&
> + pvh_gen != pvh->pv_gen) || md_gen != m->md.pv_gen) {
> PMAP_UNLOCK(pmap);
> rw_wunlock(lock);
> goto retry_pv_loop;
> @@ -5985,12 +5988,14 @@ small_mappings:
> pvf = pv;
> pmap = PV_PMAP(pv);
> if (!PMAP_TRYLOCK(pmap)) {
> - pvh_gen = pvh->pv_gen;
> + if ((m->flags & PG_FICTITIOUS) == 0)
> + pvh_gen = pvh->pv_gen;
> md_gen = m->md.pv_gen;
> rw_wunlock(lock);
> PMAP_LOCK(pmap);
> rw_wlock(lock);
> - if (pvh_gen != pvh->pv_gen || md_gen != m->md.pv_gen) {
> + if (((m->flags & PG_FICTITIOUS) == 0 &&
> + pvh_gen != pvh->pv_gen) || md_gen != m->md.pv_gen) {
> PMAP_UNLOCK(pmap);
> goto retry;
> }
> @@ -6248,11 +6253,13 @@ small_mappings:
> pmap = PV_PMAP(pv);
> if (!PMAP_TRYLOCK(pmap)) {
> md_gen = m->md.pv_gen;
> - pvh_gen = pvh->pv_gen;
> + if ((m->flags & PG_FICTITIOUS) == 0)
> + pvh_gen = pvh->pv_gen;
> rw_wunlock(lock);
> PMAP_LOCK(pmap);
> rw_wlock(lock);
> - if (pvh_gen != pvh->pv_gen || md_gen != m->md.pv_gen) {
> + if (((m->flags & PG_FICTITIOUS) == 0 &&
> + pvh_gen != pvh->pv_gen) || md_gen != m->md.pv_gen) {
> PMAP_UNLOCK(pmap);
> goto restart;
> }
>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1551c8a3732.cbde57d0124455.2726151520830111171>
