Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!uunet!pipex!sunic!isgate!veda.is!adam From: adam@veda.is (Adam David) Newsgroups: comp.os.386bsd.bugs Subject: Fixing SCSI DMA / cache problem Message-ID: <C637wx.3HA@veda.is> Date: 26 Apr 93 11:00:17 GMT Organization: Veda Systems, Iceland Lines: 72 Here's a quick and dirty fix to work around the broken motherboard problem. Problem description: The cache controller in the motherboard chipset does not invalidate the cache when data is read into memory by DMA. This causes the cache and external memory to be inconsistent with each other, resulting in files "temporarily" containing random garbage in a non-predictable manner. Possible solutions: 1) get a better motherboard. Known braindead chipsets include Headland, no doubt many others exist. A lot of manufacturers still seem to be unaware of the necessity to coordinate DMA and cache control so that they actually work together without specialised software support. 2,3) disable or correctly invalidate the cache. Most 486 systems have a two layer cache, the internal CPU cache is not always possible to configure in the CMOS setup. In such cases it is either necessary to disable the internal cache by writing some magic value to an unknown port address on the chipset, or the software (in this case 386bsd) has to make sure the cache is not allowed to become inconsistent after a DMA read operation. The external cache is always possible to configure on or off in the CMOS setup, so the simplest "quick fix" on 386 systems or those 486 systems that support it is to simply disable all memory caching (but this runs slow). 4) Mark any memory pages uncachable before allowing DMA to them. This is the best solution for how to successfully use these badly designed boards. However, this method requires substantial rewriting of parts of the VM system and will probably not be done before 386bsd 0.2. On systems with a write-back cache it is to be hoped that the controller takes care of maintaining consistency correctly. Otherwise the cache (if enabled) would have to be flushed also before every DMA write operation. The solution that I include here invalidates the 486 internal cache after every DMA disk read operation. Until it is known how to invalidate the external cache, it is necessary to disable the external cache in the CMOS setup. This is a really ugly fix, because it has to be done for every bus-mastering device. Also the whole cache is invalidated, whether it needs to or not, or the individual cache entries. This fix has at least made my motherboard useable (though rather slow), pending a better fix. The same method could be applied to other drivers, this one is Julian's low-level SCSI driver. The fix: ============================================================================ *** aha1542.c.old Mon Apr 26 10:31:49 1993 --- aha1542.c Mon Apr 26 10:34:50 1993 *************** *** 898,901 **** --- 898,904 ---- xs->flags |= ITSDONE; aha_free_ccb(unit,ccb, xs->flags); + #ifdef BROKEN_CACHE + INVALIDATE_CACHE + #endif if(xs->when_done) (*(xs->when_done))(xs->done_arg,xs->done_arg2); ============================================================================ This relies on the otherwise unused INVALIDATE_CACHE macro that just happened to be in the same file, perhaps there is a more strategic positioning for this call. The macro could be improved on to allow the external cache to be enabled. Thanks to prallon@nce.ufrj.br for pointing me in the right direction to get this fix done. At last I am able to compile the kernel without perpetual crashings (think of all those tiny header files bouncing around in the cache space). Previously the compile would stop with an error when it found binary garbage in the middle of source files, and the machine would often reboot spontaneously before very long after that.