ARM Cache中的ARM Cortex-A9预加载和锁定代码

时间:2017-04-29 22:52:33

标签: caching arm zynq cortex-a

过去一周,我一直在研究和试验ARM Cortex-A9上的缓存,即Zynq SoC,主要目的是将我的部分代码加载并锁定到L2(PL310)。我为实现这一目标而采取的步骤是:

  • 设置TTBR0并使TLBS无效
  • 使L1 Inst和数据缓存以及L2缓存无效
  • 初始化并启用L2缓存
  • 启用L1数据和Inst和MMU
  • 解锁所有L2方式。运行加载代码的循环(使用链接描述文件中为目标内存区域定义的符号)。我尝试使用三种类型的加载指令 - LDR,PLD和PLI。锁定所有L2方式。

加载代码为:

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。我要加载的区域在页面表中配置为外部和内部回写,写入分配。

0 个答案:

没有答案