Subject: kern/11125: UVM leaves stale vm map hint
To: None <gnats-bugs@gnats.netbsd.org>
From: ITOH Yasufumi <itohy@netbsd.org>
List: netbsd-bugs
Date: 10/03/2000 17:33:28
>Number:         11125
>Category:       kern
>Synopsis:       UVM leaves stale vm map hint
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 03 17:33:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     ITOH Yasufumi
>Release:        1.5G (Oct. 3, 2000)
>Organization:
	
>Environment:
System: NetBSD acha.my.domain 1.5G NetBSD 1.5G (ACHA) #58: Tue Oct 3 21:06:48 JST 2000 itohy@pino.my.domain:/usr/src/sys/arch/x68k/compile/ACHA x68k
Machine: X68030, MPU: MC68030 (25MHz), Main memory: 12MB

>Description:
	The UVM may possibly leave stale vm map hint,
	which points at freed vm map entry.

	This causes random crashes and any sort of inconsistency
	in the kernel.
	The 1.4 and 1.5 trees are also affected.

>How-To-Repeat:
	I'm not sure.
	However, fortunately(?), cdrecord-1.9 (pkgsrc/sysutils/cdrecord) pkg
	crashes my x68k in more than 95% probability.

	Here is a script (crash.sh):

	  #! /bin/sh
	  ulimit -d unlimited; ulimit -m unlimited; ulimit -s unlimited
	  cdrecord -dummy -v dev=/dev/rcd0c driver=cdr_simul speed=2 fs=2m -

	You need not have a CD-R drive connected to your machine.
	System crashes before opening the device.
	I think the mlockall(2) call helps the problem to appear.

	# sh crash.sh
	Cdrecord 1.9 (--) Copyright (C) 1995-2000 Jorg Schilling
	TOC-Type: CD-ROM
	uvm_fault(0x15ace4, 0x20620000, 0, 0x1) -> 0x1
	  type 8, code [mmu,,ssw]: 401074d
	trap type 8, code = 0x401074d, v = 0x2062000b
	kernel program counter = 0xf665e
	kernel: MMU fault trap
	pid = 16, pc = 000F665E, ps = 2009, sfc = 1, dfc = 1
	Registers:
	(register dump)

	Kernel stack (006A1D04):
	(stack dump)
	panic: MMU fault
	Stopped in cdrecord at	_cpu_Debugger+0x6:	unlk	a6
	db> t
	_cpu_Debugger(...) + 6
	_panic(...) + 60
	_trap(8,401074d,c50af0b) + 244
	_uvm_map_lookup_entry(665384,ffffa000,6a1efc) + 4e
	_uvm_fault(665384,ffffa000,0,3) + e0
	_trap(8,4020709,ffffafc0) + 55a
	faultstkadj() + 0
	db>

>Fix:
	uvm_map_entry_unlink() deletes an entry from the vm map,
	and if the hint points at the entry, the hint becomes stale.

	Here's a fix.
	I confirmed this case occurs and that this change fixes the problem,
	but I don't know
		whether the locking is necessary,
		whether the "if (map->hint == entry)" is necessary,
		what value should be set to the hint,
		etc...,
	and I'll leave it to the UVM gru.

diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/uvm/uvm_map.c.orig sys/uvm/uvm_map.c
--- sys/uvm/uvm_map.c.orig	Thu Sep 14 13:21:17 2000
+++ sys/uvm/uvm_map.c	Wed Oct  4 00:11:55 2000
@@ -1089,6 +1089,13 @@ uvm_unmap_remove(map, start, end, entry_
 		 * that we've nuked.  then go do next entry.
 		 */
 		UVMHIST_LOG(maphist, "  removed map entry 0x%x", entry, 0, 0,0);
+
+		/* critical!  prevents stale hint */
+		simple_lock(&map->hint_lock);
+		if (map->hint == entry)
+			map->hint = entry->prev;
+		simple_unlock(&map->hint_lock);
+
 		uvm_map_entry_unlink(map, entry);
 		map->size -= len;
 		entry->next = first_entry;
>Release-Note:
>Audit-Trail:
>Unformatted: