Subject: port-hppa/20933: hppa vmapbuf()/vunmapbuf() bugs
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 03/30/2003 00:18:25
>Number:         20933
>Category:       port-hppa
>Synopsis:       hppa vmapbuf()/vunmapbuf() bugs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-hppa-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Mar 29 07:19:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Izumi Tsutsui
>Release:        NetBSD 1.6K around 20021230, but -current has the same code
>Organization:
>Environment:
System: NetBSD 1.6K
Architecture: hppa
Machine: hp700 712/60 and 735/125
>Description:
Current vmapbuf()/vunmapbuf() in hppa/vm_machdep.c have bugs
which cause "DTLB miss trap" panics on physio access:
- In vmapbuf(), uvm_map(9) is called with wrong addr (uoffset) and size values.
  (size is rounded up, but addr isn't truncated)
- In vunmapbuf(), pmap_remove() is not called.

>How-To-Repeat:
Code inspection.

>Fix:
The following patch fixes the problems,
but It's better to sync with other ports.

Index: vm_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hppa/hppa/vm_machdep.c,v
retrieving revision 1.2
diff -u -r1.2 vm_machdep.c
--- vm_machdep.c	2002/07/01 16:10:03	1.2
+++ vm_machdep.c	2003/03/29 14:53:31
@@ -290,9 +290,9 @@
 	p = bp->b_proc;
 	map = &p->p_vmspace->vm_map;
 	bp->b_saveaddr = bp->b_data;
-	addr = (vaddr_t)bp->b_saveaddr;
-	off = addr & PGOFSET;
-	size = round_page(bp->b_bcount + off);
+	addr = trunc_page((vaddr_t)bp->b_data);
+	off = (vaddr_t)bp->b_data - addr;
+	size = round_page(off + len);
 
 	/*
 	 * Note that this is an expanded version of:
@@ -311,7 +311,6 @@
 	}
 
 	bp->b_data = (caddr_t)(kva + off);
-	addr = trunc_page(addr);
 	npf = btoc(size);
 	while (npf--) {
 		/* not needed, thanks to PMAP_PREFER() */
@@ -335,7 +334,8 @@
 	struct buf *bp;
 	vsize_t len;
 {
-	vaddr_t addr, off;
+	vaddr_t addr;
+	vsize_t off;
 
 #ifdef DIAGNOSTIC
 	if ((bp->b_flags & B_PHYS) == 0)
@@ -344,6 +344,8 @@
 	addr = trunc_page((vaddr_t)bp->b_data);
 	off = (vaddr_t)bp->b_data - addr;
 	len = round_page(off + len);
+	pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
+	pmap_update(pmap_kernel());
 	uvm_km_free_wakeup(phys_map, addr, len);
 	bp->b_data = bp->b_saveaddr;
 	bp->b_saveaddr = NULL;
>Release-Note:
>Audit-Trail:
>Unformatted: