Я реализую функции обслуживания кеша для ARMv8 (Cortex-A53), работающего в 32-битном режиме. Возникают проблемы, когда я пытаюсь очистить область памяти с помощью виртуальных адресов (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;
}
DMA используется для проверки функций. DMA копирует один буфер в другой. Исходный буфер очищается перед DMA, целевой буфер становится недействительным после завершения DMA. Буферы выровнены по 64 байта. Тестовое задание
for (uint32_t i = 0; i < kBufSize; i++)
buf1[i] = 0;
for (uint32_t i = 0; i < kBufSize; i++)
buf0[i] = kRefValue;
DCacheFlushByRange(buf0, sizeof(buf0));
// run DMA
while (1) // wait DMA completion;
DCacheInvalidateByRange(buf1, sizeof(buf1));
compare(buf0, buf1);
В дампе я увидел, что buf1
по-прежнему содержит только нули. Когда кеши отключены, результат правильный, поэтому сам DMA работает правильно.
Другой момент - когда весь D-кеш сбрасывается / становится недействительным по результату set / way.
// loops th/ way & set for L1 & L2
asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r"(setway) :)
Итак, скоро очистка / аннулирование с помощью набора / способа работает правильно. То же самое при перепрошивке / аннулировании с помощью VA - нет. В чем может быть проблема?
PS: kBufSize=4096;
, общий размер буфера 4096 * sizeof(uint32_t) == 16KB