This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CP15DCacheFlushBuff does *clean* and flush?

Hi,

It looks like CP15DCacheFlushBuff cleans (i.e. forces dirty data to memory) the first one or two cache lines it is supposed to flush (i.e. invalidate the contents in the cache), judging by the fact that lines

  MCRNE p15, #0, r14, c7, c14, #1 @ Clean and Flush D/U line to PoC

  MCR   p15, #0, r0,  c7, c14, #1 @ Clean and Flush D/U line to PoC

are in both in CP15DCacheCleanFlushBuff and CP15DCacheFlushBuff. (And, it matches the info from ARM on http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babhejba.html about clean and invalidate.)

CP15DCacheFlushBuff then moves on to only flushing cache lines:

 MCR    p15, #0, r0,  c7,  c6, #1 @ Flush D/U line to PoC

 

We discovered this when poisoning a small read buffer that the DMA later wrote to.  When calling CacheDataInvalidateBuff, the poisoned data in the cache was cleaned (written to memory), overwriting what the DMA had just put there!

I'm not sure if it's done the way it is for when the data buffer to be cleaned is not aligned on a cache line boundary (which it is, but the code doesn't check). If that is the case, I assume the same situation can arise at the end of the buffer (if the last cache line is shared with other data).

It seems wasteful to always have to call CacheDataCleanBuff before setting up the DMA, just to make sure that a subsequent CacheDataInvalidateBuff doesn't accidentally do any cleaning.  I'm hoping you have a better suggestion or explanation of the above.

Thanks,

Orjan

  • when the memory is not aligned - we have 2 choices. one not to clean the line and 2nd to clean the complete line. When the line is not cleaned the dirty data will not be moved to main memory. This will be a problem in some cases. And with the 2nd option we will get scenarios like the once you faced.

    So the best would be always align the memory to be cached.

    Regards

    Baskaran

  • In my case, the data is aligned.  The code in CP15DCacheFlushBuff doesn't check whether it is already aligned or not, however: it just truncates the address down to the nearest cache line.

    (And also, it only does the cleaning for the first cache line; not the last.)

     Thanks,

    Orjan

  • The action on checking the alignment is same whether it is aligned or not. So no need to check the alignment.

    I just skimmed the code again, seems it will clean the last line also. why do you think it will not clean the last line? - i am sorry if i am missing something.

    Regards

    Baskaran

  • Right, it doesn't check whether the buffer start is aligned on a cache line: but it seems to nevertheless assume that the first cache line could be shared with other data. That is the only reason I can see for doing clean + flush instead of just flush. 

    As for the rest of the cache lines, if I'm reading it correctly they are only flushed (invalidated), not cleaned (written back).  What I mean by that is, if there is a potential data sharing issue on the first cache line (ignoring knowledge about alignment and size), then that must be an issue on the last cache line as well. 

    Thanks,

    Orjan

  • Earlier i misunderstood the issue. I hope i got it now.

    Your concerns are taken care in the existing code already.

    First line and last line - you can see 2 MCRNE instructions, the first one takes care of first line and the 2nd one takes care of last line.

    Alignment check- this is achieved with TST instruction and 'NE' - not equal (part of MCRNE). If TST result is zero (equal cond) then the start/end address is aligned. In this case the MCRNE instruction will be treated as NOP.

    Hope that is clear. If you are facing the issue you may need to recheck the alignment of your memory area.

    Regards

    Baskaran

  • Thank you.  I think it all makes sense now: when I mentioned "small buffer" initially, it is in fact 12 bytes.  I.e., the end address is not aligned to a cache line boundary, and hence is written back.