Subject: booting with root-on-md and "panic: init died"
To: None <tech-kern@netbsd.org>
From: Simon Burge <simonb@NetBSD.org>
List: tech-kern
Date: 02/17/2007 01:35:53
I've found a problem where starting up a PPC system with root on a md(4)
memory disk gets:

	Process (pid 1) got signal 6
	panic: init died (signal 0, exit 1)

while trying to start up.  I've tracked this down to this change in
kern_sysctl.c:

  revision 1.191
  date: 2006/03/15 16:12:07;  author: drochner;  state: Exp;  lines: +10 -2
  branches:  1.191.2;
  Check the "oldlen" argument to sysctl(2) before passing it
  to vslock(9). This prevents a local DOS.
  (The checks against system and user limits for wired
  memory should be centralized in UVM; for now prefer a less
  invasive fix which can be pulled pulled up into releases.)

which is:

        if (l != NULL && oldp != NULL && savelen) {
+               /*
+                * be lazy - memory is locked for short time only, so
+                * just do a basic check against system limit
+                */
+               if (uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
+                       lockmgr(&sysctl_treelock, LK_RELEASE, NULL);
+                       return (ENOMEM);
+               }
		error = uvm_vslock(l->l_proc, oldp, savelen, VM_PROT_WRITE);

What's happening is that uvmexp.wiredmax is initialised by the
pagedaemon kthread, and with root-on-md the pagedaemon thread hasn't had
a chance to run.  This means that sysctl_lock() decides it can't lock
down any memory so the machdep.cacheinfo sysctl fails, and syncicache()
calls abort() because it's not happy.

Usually, this system uses root-on-NFS and while we're waiting for
the dhcp dance to finish, the pagedaemon thread runs and sets up
uvmexp.wiredmax before /sbin/init starts.

With root-on-md there's no delays before /sbin/init starts up.  There
are no disks or USB or any devices that would be configured in
config_interrupts() which can also introduce a delay for the pagedaemon
thread to run - another PPC system that has a USB bus boots up fine
with root-on-md, but init fails the same way if USB is removed from the
kernel config file.

The patch I'm using to work around this is:

-               if (uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
+               if (uvmexp.wiredmax &&
+                   uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {

but this obviously isn't right.

I'm not sure if the correct fix is to call uvmpd_tune() (in
uvm_pdaemon.c) before kthreads run, or have something like
uvm_page_physload() update uvmexp.wiredmax directly?  Or maybe
changes in sysctl_lock()?

Anyone have any ideas on what the right way to do this is?

Cheers,
Simon.