Subject: Re: panic: uvm_unmap_remove: has mapping (3.0 DEBUG kernel) - probably solved
To: None <port-vax@NetBSD.org>
From: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
List: port-vax
Date: 03/09/2006 23:29:56
--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Mar 09, 2006 at 02:35:58PM +0100, Hans Rosenfeld wrote:
> when trying to boot a 3.0 VAX kernel I built to for chasing that SGEC
> bug the system crashes as soon as init is started:
> 
> boot device: sd0
> root on sd0a dumps on sd0b
> init: copying out path `/sbin/init' 11
> panic: uvm_unmap_remove: has mapping
> Stopped in pid 1.1 (init) at    netbsd:uvm_unmap_remove+0x2e0:  movab 0x1000(r2), r2
> db> trace
> panic: uvm_unmap_remove: has mapping
> Stack traceback :
> 0x876e6e6c:
> uvm_unmap_remove+0x2e0(0x83e34000,0x7f7ff000,0x7f800000,0x876e6f0c,0)
> 0x876e6ec8: sys_munmap+0x133(0x83e33000,0x876e6f60,0x876e6f58)
> 0x876e6f10: syscall+0x11d(0x876e6fb4)
> db>
> 
> This is caused by a debug check in uvm/uvm_map.c which seems to be quite
> new, at least 2.1 didn't have it.

After a day of meditating about that code and singlestepping through it
several times, I came to the conclusion that there is something wrong
with pmap_extract() in arch/vax/include/pmap.h (and arch/vax/vax/pmap.c,
but this one is not used).

Uvm_unmap_remove() uses pmap_extract() to check that there are no
mappings left in that memory range it just unmapped. Given a pmap and a
virtual address, pmap_extract() is expected to return FALSE if that
address is not mapped by the pmap. There is this code that I think is
buggy:

if (kvtopte(&pte[sva])->pg_pfn) {
	if (pap)
		*pap = (pte[sva] & PG_FRAME) << VAX_PGSHIFT;
	return (TRUE);
}
return (FALSE);

As far is I understand kvtopte(&pte[sva]) returns the system PTE of the
kernel virtual address of the process PTE used for the virtual address
given to pmap_extract() and therefore kvtopte(&pte[sva])->pg_pfn returns
the page frame of that system PTE. I am not quite sure about what this is
supposed to do, but I guess it is just making sure that the page table
entry is resident. It seems that the test for the mapping of that PTE is
actually not done.

Changing that code to

if (kvtopte(&pte[sva])->pg_pfn && (pte[sva] & PG_FRAME)) {

seems to fix that function, fix that panic and not to break anything
else.

The diff I attached goes a somewhat different way by testing the valid
bit in the PTE. I think this is the right thing to do here, and would
possibly be apropriate for the code a few lines above.

Please correct me if I'm wrong with this one, I don't fully understand
the inner workings of the memory system yet. :)

 - Hans Rosenfeld


-- 
%SYSTEM-F-ANARCHISM, The operating system has been overthrown

--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: sys/arch/vax/include/pmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/include/pmap.h,v
retrieving revision 1.60
diff -u -r1.60 pmap.h
--- sys/arch/vax/include/pmap.h	14 Dec 2003 19:39:24 -0000	1.60
+++ sys/arch/vax/include/pmap.h	9 Mar 2006 21:52:32 -0000
@@ -186,7 +186,7 @@
 			return FALSE;
 		pte = (int *)pmap->pm_p1br;
 	}
-	if (kvtopte(&pte[sva])->pg_pfn) {
+	if (kvtopte(&pte[sva])->pg_pfn && (pte[sva] & PG_FRAME)) {
 		if (pap)
 			*pap = (pte[sva] & PG_FRAME) << VAX_PGSHIFT;
 		return (TRUE);

--RnlQjJ0d97Da+TV1--