Re: repeatable panic on pageout with 945GM

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Sat, 4 Jun 2016 20:47:45 +0300
On Sat, Jun 04, 2016 at 10:02:33AM -0700, Matthew Macy wrote:
> 
> 
> 
>  
>  >  
>  > This "band-aid" seems to have worked. I haven't had a single panic since 
>  > - Thanks! :-) 
>  >  
>  > I tried to compile with -O0 but, for some reason, it panics in the sound 
>  > driver with a double-fault. When I get time, I'll recompile only the 
>  > files involved and see if I can't get a decent trace (and dump) to 
>  > identify the cause, 
>  
> No need. Based on the line that it crashed at, the problem is that with no mappings no pv_entry has been allocated. Somehow on your laptop you're able to get in to a situation where fictitious pages have been added to the object that don't get mapped. This isn't a strange situation in and of itself, but you seem to be the only hitting this. 
> 
> In any event, the DRM 4.6 port will support AGP in about a week. It will probably have bugs, but this one isn't in any of its code paths.
> 
> 
> I'm glad your system works a bit better now.
> 

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.

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:47:51 UTC

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