Subject: ata/wdc vs gcc3 on amiga
To: None <tech-kern@netbsd.org>
From: Jukka Andberg <jandberg@netbsd.org>
List: tech-kern
Date: 04/07/2004 09:41:01
Hello list,

I finally managed to upgrade my userland from gcc 2.95.3 era to
a more current one and found out that kernels compiled with the new
compilers now freeze somewhere after detecting my hard drives.

I managed to track the problem to atabus_thread() in ata.c.
Looks like the compiler now decides to keep ch_flags in a register,
which messes up things as the same variable is also used from
the interrupt handlers.

The sequence leading to the freeze seems to be:
1) atabus_thread() returns from c_start()
2) chp->ch_flags is read into a register
3) splx()
4) wdcintr() runs, changing the ch_flags
5) back in atabus_thread(), splbio()
6) thread decides to sleep and clear some flag in ch_flags. It now uses
   the value it copied into a register earlier, and writes ch_flags,
   destroying the changes wdcintr() did.
7) the system is now in inconsistent state, and does not start any
   new transfers as the flags falsely indicate one is already active, or
   something like that.

Anyone with a bit more clue want to take a look at this?

I found that declaring chp volatile in atabus_thread at least fixes this
problem. Or should it be the flags field that is volatile perhaps?

And some other, less interesting things that came up while I was poking at
this:

- wdc_amiga receives interrupts at a level below splbio(), which causes
  some WDC_DIAGNOSTIC code in wdc.c to panic when it checks the spl level.
- additionally, the method it uses to check the spl level (comparing
  return values from spl* functions) doesn't work very well on amiga as
  the m68k spl* functions seem set only the lower 16 bits of the return
  value, the upper bits being 'random'.