过去一周,我一直在研究和试验ARM Cortex-A9上的缓存,即Zynq SoC,主要目的是将我的部分代码加载并锁定到L2(PL310)。我为实现这一目标而采取的步骤是:
加载代码为:
extern uint32_t code_start;
extern uint32_t code_end;
void PreloadCode() {
uint32_t* temp;
uint32_t dummy;
//invalidate all ways and L1 data cache
L1ICacheInvalidate();
*REG7_CLEAN_INV_WAY = 0xffff;
while(*REG7_CLEAN_INV_WAY);
*REG9_CACHE_SYNC = 0;
while(*REG9_CACHE_SYNC);
//unlock all ways
*REG9_D_LOCKDOWN0 = 0x0000;
*REG9_I_LOCKDOWN0 = 0x0000;
asm volatile ("dsb");
asm volatile ("isb");
for(temp = &code_start; temp < &code_end; temp += 1){
asm volatile ("ldr %0, [%1]" : "=r"(dummy) : "r"(temp));
// asm volatile ("pld [%0]" :: "r"(temp) : "memory");
// asm volatile ("pli [%0]" :: "r"(temp) : "memory");
}
asm volatile ("dsb");
asm volatile ("isb");
//lock all ways
*REG9_D_LOCKDOWN0 = 0xFFFF;
*REG9_I_LOCKDOWN0 = 0xFFFF;
}
我还在PL310中设置事件计数器来计算IRHIT(指令读取命中)和IRREQ(指令读取请求)的数量。我定期运行一段代码,重置每个循环的计数器,并使L1指令缓存无效。
我希望验证在每次循环之后我会看到L2中的命中数和请求数是相同的。但是,这不会发生。点击次数始终为0表示我已锁定所有L2,但代码未加载。
当我运行完全相同的代码而不在最后锁定L2时。我得到了0%命中率的第一个循环,但所有后续循环显示100%命中。
你知道我做错了什么吗?
注意:我只使用其中一个CPU。
编辑:另一个说明。我使用直接映射,其中VA直接对应于PA。我要加载的区域在页面表中配置为外部和内部回写,写入分配。