Subject: Re: Setting page cacheability
To: Cameron Kaiser <spectre@stockholm.ptloma.edu>
From: Michael R. Zucca <mrz5149@acm.org>
List: port-mac68k
Date: 01/24/2002 21:23:31
At 8:37 PM -0500 1/24/02, Cameron Kaiser wrote:
>> Is there a kernel API in NetBSD to modify the cacheability of certain
>> pages. Unfortunately, I'm not familiar enough with the NetBSD memory
>> management API's.
>> Basically, I'd like to mark a page as uncacheable and then later mark it as
>> cacheable again (assuming the API does all of the necessary
>> flush/invalidate stuff). I believe the memory in question is already marked
>> non-swappable and is in kernel space.
>
>What's the larger thing you're trying to do with this?

I'm doing AV SCSI DMA. I have a driver working if the DMA occurs into an
uncacheable buffer that I bcopy to/from. However, the DMA engine is capable
of putting the data pretty much anywhere in DRAM. So what I'd like to do is
point it directly at the longest physically contiguous run of disk buffer.
In some cases, the beginning or end of a buffer won't fully occupy a page,
so that page must be marked uncacheable. Why? Because there is the
possibility of data being read/written to that page during the transfer so
I can't just flush/invalidate. For instance, suppose I am doing a DMA write
into a memory page which has activity going on in it. If I flush the cache
at the end of the transfer, the cache may overwrite the stuff I just DMA'd
with whatever was in the cahce. On the other hand, if I invalidate the
cache after the DMA, the stuff the CPU put in the cache won't get out to
memory. So I'm damned if I do and damned if I don't. The only thing to do
is to mark the pages in question as uncacheable before the transfer and
then uncacheable after the transfer.

I can get away with setting just the first and last pages in a transfer as
uncacheable and then flushing/invalidating the other full pages in the
transfer as necessary.

If there is no way to mark individual pages as cacheable, then for
transfers under 1 page I'll have to DMA into/out of a buffer that I bcopy
from/to. However, I would prefer to just mark the appropriate pages as
uncacheable for the duration of the transfer.

Keep in mind, this is a reasonably rare occurance. 90% of the time the
kernel does page-sized transfers with the occasional 1k or 2k transfer here
and there. The remaining cases that I've seen seem to involve small
transfers for SCSI messages. While I can avoid caching issues with the SCSI
messages by pre-allocating the messages on their own pages (the SCSI code
allows this), I can't deal with the problem of the <4k transfers that
happen everywhere else.

If I can be convinced that the <4k non-SCSI message transfers happen into
buffers where the remainder of the page is unimportant, I'll be happy. That
means I just have to put the SCSI messages on their own pages and just do
the appropriate flush/invalidate for read/write.

Can I have my answer now? :-)

----------------------------------------------
 Michael Zucca - mrz5149@acm.org
----------------------------------------------
 "I'm too old to use Emacs." -- Rod MacDonald
----------------------------------------------