Subject: Re: lack of pciide transfer alignment checking causes crash
To: Jason Thorpe <thorpej@shagadelic.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-kern
Date: 06/25/2005 21:11:35
On Sat, Jun 25, 2005 at 10:52:13AM -0700, Jason Thorpe wrote:
> 
> On Jun 25, 2005, at 4:39 AM, Erik E. Fair wrote:
> 
> >The problem I want help with here on tech-kern is precisely where  
> >to enforce
> >the cache-line (16 byte) alignment requirement for IDE DMA  
> >transfers. I have
> >experimentally determined that any violation of that rule will  
> >cause the system
> >to lock up hard, requiring a Power-cycle to reset. User mode access  
> >to the
> >raw device, which, of course, invokes kern_physio().
> >
> >This is probably why the NetBSD install failed at the disklabelling  
> >step (I
> >subsequently installed NetBSD on an IDE disk on another system, and  
> >then moved
> >the disk over).
> >
> >The only reason that NetBSD runs at all on this box is that the  
> >typical FFS
> >filesystem I/O requests are apparently aligned properly.
> >
> >I think there are two basic choices for handling a misaligned  
> >transfer request:
> >
> >1. return an error (e.g. EIO).
> >
> >2. use PIO mode for misaligned transfers.
> >
> >I think that sys/dev/pci/pciide_common.c should have facilities  
> >added to it
> >to enforce alignment (I didn't see any at a minimum, and I think it  
> >would be
> >nice if it handled them gracefully by degrading to PIO mode.
> 
> I think the best way to handle this would be:
> 
> 1. Change _wdc_ata_bio_start() handle the case where (*wdc->dma_init) 
> () fails with EINVAL.  Fall back to PIO mode in that case (clear  
> C_DMA flag bit in the xfer structure).
> 
> 2. Make same change to wdc_atapi_intr().
> 
> 3. Give geodeide its own dma_init routine that checks for the  
> alignment of the buffer.  If the buffer is not aligned, it returns  
> EINVAL.  Otherwise, it just calls the normal pciide_dma_init() routine.
> 
> 
> Manuel -- does this seem feasible?

Yes, this should work. But I think it's better and easier to do the
I/O to a properly aligned buffer and data copy to/from this buffer.
This can easily be done in the dma_start and dma_finish callbacks.
Of course, if the supplied buffer is already properly aligned, just use it.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--