Subject: kern/33688: panic when NKMEMPAGES set to certain large number
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <chenpeng@semptian.com>
List: netbsd-bugs
Date: 06/10/2006 12:55:02
>Number:         33688
>Category:       kern
>Synopsis:       panic when NKMEMPAGES set to certain large number
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jun 10 12:55:02 +0000 2006
>Originator:     Ricardo Chen
>Release:        3.0
>Organization:
>Environment:
NetBSD 3.0 i386
>Description:
Firstly I'm sorry for my bad English, I wish I could descibe the problem and fix clearly...

When I tuning my kernel, and setting the NKMEMPAGES to any number larger than ((384 * 1024 * 1024) >> PAGE_SHIFT) and rebuilding and the new system will go to panic soon after boot.


>How-To-Repeat:
Use i386 PC(with 1G memory), add 

options NKMEMPAGES ((768* 1024 * 1024) >> PAGE_SHIFT)

to the kernel config file, config and build and reboot, panic will happen.
 
>Fix:
I checked and traced the source code, found the following code:
sys/kern/kern_malloc.c, from line 845:

 kmemusage = (struct kmemusage *) uvm_km_zalloc(kernel_map,
	    (vsize_t)(nkmempages * sizeof(struct kmemusage)));
 kmb = 0;
 kmem_map = uvm_km_suballoc(kernel_map, &kmb,
	    &kml, ((vsize_t)nkmempages << PAGE_SHIFT),
	    VM_MAP_INTRSAFE, FALSE, &kmem_map_store);
 uvm_km_vacache_init(kmem_map, "kvakmem", 0);

I'm not familiar the code, but I guess since the size of kmemusage becoming very large, it isn't possible to be allocated "directly", then finally the function pmap_alloc_pvpage been called, then 

  pv_cachedva = uvm_km_kmemalloc(kmem_map, NULL, PAGE_SIZE,
		    UVM_KMF_TRYLOCK|UVM_KMF_VALLOC);

been called (line 1303 at sys/arch/i386/i386/pmap.c), but at the time, the kmem_map is still not initialized, then panic happens.

So I swich the calling sequence of the two functions:

 kmb = 0;
 kmem_map = uvm_km_suballoc(kernel_map, &kmb,
	    &kml, ((vsize_t)nkmempages << PAGE_SHIFT),
	    VM_MAP_INTRSAFE, FALSE, &kmem_map_store);
 kmemusage = (struct kmemusage *) uvm_km_zalloc(kernel_map,
	    (vsize_t)(nkmempages * sizeof(struct kmemusage)));
 uvm_km_vacache_init(kmem_map, "kvakmem", 0);

and now the system seems working OK.