Subject: port-mips/33166: pmap_remove_pv called for unmanaged pages
To: None <port-mips-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <gdamore@netbsd.org>
List: netbsd-bugs
Date: 03/29/2006 21:35:00
>Number:         33166
>Category:       port-mips
>Synopsis:       pmap_remove_pv called for unmanaged pages
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    port-mips-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 29 21:35:00 +0000 2006
>Originator:     Garrett D'Amore
>Release:        3.99.17
>Organization:
Tadpole Computer, Inc.
>Environment:
NetBSD cabernet 3.99.17 NetBSD 3.99.17 (METEOR) #10: Wed Mar 29 12:52:54 PST 2006  garrett@zippy:/home/garrett/netbsd/src/sys/arch/evbmips/compile/obj/METEOR evbmips


>Description:
when munmap() is called for a previously mmap()ed region of framebuffer memory located in high memory (> 4GB on Alchemy), pmap_remove tries to call pmap_remove_pv with a null "pg".  This results in a panic.
>How-To-Repeat:
stick a pci device on PCI alchemy, and then mmap() some of it.  when your process munmap()'s it (or exits), the system will panic.
>Fix:
Add appropriate checks for null pg.  Here's a diff:

*** pmap.c.~1.166.~    Sat Dec 24 12:07:19 2005
--- pmap.c    Wed Mar 29 12:52:07 2006
***************
*** 730,736 ****
                  pmap->pm_stats.wired_count--;
              pmap->pm_stats.resident_count--;
              pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(entry));
!             pmap_remove_pv(pmap, sva, pg);
              if (MIPS_HAS_R4K_MMU)
                  /* See above about G bit */
                  pte->pt_entry = MIPS3_PG_NV | MIPS3_PG_G;
--- 730,737 ----
                  pmap->pm_stats.wired_count--;
              pmap->pm_stats.resident_count--;
              pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(entry));
!             if (pg)
!                 pmap_remove_pv(pmap, sva, pg);
              if (MIPS_HAS_R4K_MMU)
                  /* See above about G bit */
                  pte->pt_entry = MIPS3_PG_NV | MIPS3_PG_G;
***************
*** 789,795 ****
                  pmap->pm_stats.wired_count--;
              pmap->pm_stats.resident_count--;
              pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(entry));
!             pmap_remove_pv(pmap, sva, pg);
              pte->pt_entry = mips_pg_nv_bit();
              /*
               * Flush the TLB for the given address.
--- 790,797 ----
                  pmap->pm_stats.wired_count--;
              pmap->pm_stats.resident_count--;
              pg = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(entry));
!             if (pg)
!                 pmap_remove_pv(pmap, sva, pg);
              pte->pt_entry = mips_pg_nv_bit();
              /*
               * Flush the TLB for the given address.