repeatable panic on pageout with 945GM
Matthew Macy
mmacy at nextbsd.org
Sat Jun 4 17:51:13 UTC 2016
>
> 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;
> }
>
More information about the freebsd-current
mailing list