ฉันกำลังใช้ฟังก์ชันการบำรุงรักษาแคชสำหรับ 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-cache ทั้งหมดถูกล้าง/ทำให้ใช้ไม่ได้โดยผลลัพธ์ชุด/วิธีถูกต้อง
// 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