[matthew@wil.cx: Re: [parisc-linux] Console Kernel Panic]

Russell King rmk at arm.linux.org.uk
Wed Dec 21 08:18:15 MST 2005


(Sorry for this not being threaded).

On Wed, Dec 21, 2005 at 07:39:37AM -0700, Matthew Wilcox wrote:
> On Mon, Dec 19, 2005 at 08:50:18PM -0700, Keven Tipping wrote:
> > I am currently running Kernel version 2.6.15-rc6-pa1.
> > 
> > This problem, however, is evident in 2.6.14.3-pa0, and 2.6.15-rc5-pa5, as well as 2.6.12.2 (Gentoo 2005 LiveCD). Problem remains regardless of SMP or Uniprocessor kernels.
> > 
> > On the K Class (it appears it is limited to these machines?), if nothing is currently running on the ttyB0 Serial Console, if you press any key, the system burps up the following:
> > 
> > Kernel Panic: Kernel Fault
> > Not Syncing...
> > 
> > What I mean by "nothing running" is if Agetty is NOT running, NOR is Bash. 
> 
> I really think you could have provided the useful bits from a kernel panic
> here.  Please see http://www.parisc-linux.org/faq/kernelbug-howto.html
> 
> However, I've reproduced it myself.  Here's the relevant bits:
> 
>  IAOQ[0]: mux_read+0x4c/0x17c
>  IAOQ[1]: mux_read+0x50/0x17c
>  RP(r2): mux_poll+0x78/0x88
> 
> The instruction faulting is:
> 
>   4c:   48 94 02 28     ldw 114(,r4),r20
> 
> which corresponds to the load of flip.count:
> 
>                 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
> 			continue;
> 
> ie the 'tty' variable is NULL at this point.
> 
> Alan, you seem to have the tarbaby for ttys at the moment ... any idea
> why port->info->tty would be NULL?  The corresponding routine in 8250.c
> (receive_chars()) doesn't check for tty being NULL.  So is there
> some non-obvious check the MUX driver is missing, or is this a latent
> problem in 8250 too?

Basically, mux.c is operating with an invalid assumption.  The
assumption that port->info is set to NULL when we don't want to
handle the port is bogus.

Let's look at the code:

static int mux_startup(struct uart_port *port)
{
        mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
        return 0;
}

Ok, so mux_startup starts the mux_timer running.

static void mux_shutdown(struct uart_port *port)
{
}

mux_shutdown does nothing at all.

mux_poll is the mux_timer expiry function:

static void mux_poll(unsigned long unused)
{
        int i;
 
        for(i = 0; i < port_cnt; ++i) {
                if(!mux_ports[i].info)
                        continue;
 
                mux_read(&mux_ports[i]);
                mux_write(&mux_ports[i]);
        }
 
        mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
}

and it assumes that we can call mux_read and mux_write if port->info
is non-NULL.  port->info is set non-NULL on the first open of the
port.  It will not be set to NULL when the port is closed - that
only happens when the port is removed from the serial subsystem.

So, this means that mux_read() will be called by mux_poll() after
mux_shutdown() has been called, and mux_read() will try to
dereference port->info->tty.

Since serial_core assumes that the shutdown method will shut the
driver up completely before returning, this obviously is bad,
especially when the serial_core NULLs out port->info->tty.

Hence, it's a mux driver bug.  Please fix.

-- 
Russell King


More information about the parisc-linux mailing list