[U-Boot] [PATCH] ARM: support for cache coherent allocations

Ilya Yanok ilya.yanok at cogentembedded.com
Tue Jun 19 16:32:07 CEST 2012


Hi Marek,

On Tue, Jun 19, 2012 at 3:37 AM, Marek Vasut <marek.vasut at gmail.com> wrote:

>
> Kind of ... I mean rather insert an entry into MMU table at runtime that
> says
> "this region is uncached". But that'd need some hack in the mallocator now
> that
> I think about it. It might not be as simple as I thought at first.
>

Hm. I don't quite understand. Do you mean patch malloc code to handle
turning caching off for the region? I doubt that's a good approach. I would
make the malloc calling code to handle caching.
How about something like this (pseudocode):

if (/* have enough room in space allocated previously*/ )
     /* update existing allocation data and return */

newp = malloc_align(ALIGN(size, min_size), min_size);
/* Allocate both size and offset aligned block.
 * min_size is minimal block size for which cache can be turned off, on ARM
currently it's 1MB
 * malloc_align will return block starting on aligned address, I don't
think current allocator has some support for this so effectively we will
have to allocate ALIGN(size, min_size) + min_size - 1 bytes
 */

/* Patch pagetable (on ARM) or do whatever needed to make allocated block
uncached */
/* Save data about unused space in the block (in case we allocated more
than was requested) */

return newp;

Existing allocation data could be as simple pair of static variables. This
is not optimal in some scenarios but very simple.

On the other hand, most MMUs allow you to allocate stuff with 4k density,
> which
> should be ok.
>

Hm, I don't really feel like rebuilding page tables on the fly in U-Boot is
a good idea. Currently U-Boot ARM uses page table with 1MB granularity.


> > Also, what is this for? Can we not simply flush/invalidate the caches?
> >
> >
> >  flush/invalidate can be racy for some hardware. Sometimes we need to
> write
> > some field to DMA descriptor and then read another one. And because one
> > cannot flush/invalidate individual bytes write/flush can destroy the
> field
> > updated by hardware. (Well, we can invalidate/read before write/flush but
> > that introduces a race).
>
> But that's shitty hardware. Do you really need to do it? Where? I fixed
> similar
> issue in fec_mxc.c recently.
>

CPSW switch on TI AM33x. Here is the code:

         /* not the first packet - enqueue at the tail */
        prev = chan->tail;
        desc_write(prev, hw_next, desc);
        chan->tail = desc;

        /* next check if EOQ has been triggered already */
        if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ)
                chan_write(chan, hdp, desc);


desc_{read/write} are just readl/writel on fields of desc structure. Note
that one have to flush for desc_write() to reach the hardware but as fields
of the DMA descriptor are going to be in the same cache line this flush
will harm other fields that are probably updated by the hardware. Well, I
have to say I never seen a manifestation of this problem in the wild and
probably hardware somehow takes care of this situation but we can't be sure.

Regards, Ilya.


More information about the U-Boot mailing list