Re: repeatable panic on pageout with 945GM

From: Matthew Macy <mmacy_at_nextbsd.org>
Date: Sat, 04 Jun 2016 10:51:08 -0700
 >  
 > 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 
 > _at__at_ -3947,12 +3947,14 _at__at_ 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; 
 > _at__at_ -5775,13 +5777,14 _at__at_ 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; 
 > _at__at_ -5985,12 +5988,14 _at__at_ 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; 
 >              } 
 > _at__at_ -6248,11 +6253,13 _at__at_ 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; 
 >              } 
 > 
Received on Sat Jun 04 2016 - 15:51:13 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:05 UTC