按虚拟地址刷新/失效范围;ARMv8;隐藏物

按虚拟地址刷新/失效范围;ARMv8;隐藏物,arm,cpu-cache,armv8,Arm,Cpu Cache,Armv8,我正在为32位模式下运行的ARMv8(Cortex-A53)实现缓存维护功能。 当我尝试使用虚拟地址(VA)刷新内存区域时,出现了一个问题DCacheFlushByRange如下所示 // some init. // kDCacheL1 = 0; kDCacheL2 = 2; while (alignedVirtAddr < endAddr) { // Flushing L1 asm volatile("mcr p15, 2, %0, c0, c0, 0" : :

我正在为32位模式下运行的ARMv8(Cortex-A53)实现缓存维护功能。 当我尝试使用虚拟地址(VA)刷新内存区域时,出现了一个问题
DCacheFlushByRange
如下所示

// some init.
// kDCacheL1 = 0; kDCacheL2 = 2;
while (alignedVirtAddr < endAddr)
{
    // Flushing L1
    asm volatile("mcr   p15, 2, %0,  c0,  c0,  0" : : "r"(kDCacheL1) :);        // select cache
    isb();
    asm volatile("mcr   p15, 0, %0,  c7, c14,  1" : : "r"(alignedVirtAddr) :);  // clean & invalidate
    dsb();

    // Flushing L2
    asm volatile("mcr   p15, 2, %0,  c0,  c0,  0" : : "r"(kDCacheL2) :);        // select cache
    isb();
    asm volatile("mcr   p15, 0, %0,  c7, c14,  1" : : "r"(alignedVirtAddr) :);  // clean & invalidate
    dsb();

    alignedVirtAddr += lineSize;
}
因此,很快按设置/方式刷新/无效将正常工作。使用VA进行闪烁/失效时,情况也不一样。有什么问题吗


PS:
kBufSize=4096,总缓冲区大小为
4096*sizeof(uint32\u t)=16KB

不存在函数本身而不是Cortex-A53缓存实现功能的问题

来自Cortex-A53 TRM

AArch32中的DCIMVAC操作和AArch64中的DC IVAC指令执行目标地址的失效。如果集群中的数据不干净,则在执行“无效”之前执行“清除”


因此没有实际的失效,有清理和失效

正常(至少对我来说)顺序是

flush(src);
dma(); // copy src -> dst
invalidate(dst);
但由于invalidate()会刷新,在DMA传输后,缓存(dst区域)中的旧数据会写入内存中的数据之上


解决方案/解决方法是

flush(src);
invalidate(dst);
dma(); // copy src -> dst
invalidate(dst); // again, that's right*.


*可以提前将来自“dst”内存区域的数据提取到缓存中。若这种情况发生在DMA将数据放入内存之前,那个么将使用缓存中的旧数据。第二个无效是可以的,因为数据没有标记为“脏”,所以它将被执行为“纯无效”。在这种情况下不进行清理/刷新。

如果范围/缓冲区较大,则可能只需刷新整个一级缓存,然后暂停以确保在刷新二级缓存之前完成。此外,存在不是高速缓存的一部分的写入缓冲区(或类似物)。如果“buf1”完全为零或部分为零,则不提供尺寸。集合通常是连续的地址。缓冲区大小为16KB。我还尝试了64B缓冲区,结果是一样的。通过VA刷新整个L1和L2区域不起作用。在所有情况下,整个目标缓冲区都是零。对不起,我不熟悉A53,但是在Cortex-A7上,L2有一个内存映射寄存器接口。CP15寄存器将不会刷新二级缓存(即使手册可能会指出这一点)。除了Cortex-A53 TRM外,您还有手臂手册吗?通常SCU和片上定时器等至少与早期ARM芯片有单独的寄存器文件。Linux在A7中使用不同的机制。@artlessnoise二级缓存控制器是单独的芯片(与其他外围设备类似,即使它们都打包在一起)。A53集成了二级缓存。
flush(src);
dma(); // copy src -> dst
invalidate(dst);
flush(src);
invalidate(dst);
dma(); // copy src -> dst
invalidate(dst); // again, that's right*.