简而言之,为了调试的目的,我想关闭Linux上下文中的所有MMU (和缓存)操作,只为了运行一些测试。要非常清楚的是,我不打算在那之后我的系统还能正常工作。
关于我的设置:我目前正在摆弄一个飞思卡尔Vybrid (VF610),它集成了一个A5和它的低功耗模式。由于我正在试验一些可疑的本地内存损坏,而芯片处于“低功耗停止”模式,而我的DDR3处于自刷新状态,因此我试图一点一点地改变操作,现在执行所有挂起/恢复步骤,而不实际执行WFI。因为在此指令之前,我运行地址转换,在没有地址转换(本质上是重置)的情况下,我想通过“手动”关闭MMU来“模拟”。
(我目前没有JTAG或对我的芯片的任何其他调试访问权限。我通过MMC/TFTP/NFS加载它,并使用LED调试它。)
到目前为止我尝试过的是:
    /* disable the Icache, Dcache and branch prediction */
    mrc     p15, 0, r6, c1, c0, 0
    ldr r7, =0x1804
    bic r6, r6, r7
    mcr     p15, 0, r6, c1, c0, 0
    isb
    /* disable the MMU and TEX */
    bic r7, r6, r7
    isb
    mcr p15, 0, r6, c1, c0, 0   @ turn on MMU, I-cache, etc
    mrc p15, 0, r6, c0, c0, 0   @ read id reg
    isb
    dsb
    dmb以及其他同样效果的变体。
我观察到:
在MMU块之前,我可以点亮一个LED (3个组装指令,没有分支,没什么花哨,也不需要访问我的DDR,它已经在自我刷新-- GPIO端口的虚拟地址在此之前存储在寄存器中)。
在MMU块之后,无论我尝试物理地址还是虚拟地址,我都不能再使用了。
我认为这个问题可能与我的个人电脑有关,它保留了一个过时的虚拟地址。查看内核的其他部分是如何完成的,但反过来(即,在启用翻译的同时):
    ldr r3, =cpu_resume_after_mmu
    instr_sync
    mcr p15, 0, r0, c1, c0, 0   @ turn on MMU, I-cache, etc
    mrc p15, 0, r0, c0, c0, 0   @ read id reg
    instr_sync
    mov r0, r0
    mov r0, r0
    ret r3          @ jump to virtual address
ENDPROC(cpu_resume_mmu)
    .popsection
cpu_resume_after_mmu:(来自arch/arm/内核/睡眠.S,cpu_resume_mmu)
我不知道这2条指令延迟与什么相关,以及它在哪里被记录下来。我在这个问题上什么也没有发现。我尝试过类似的东西,但没有成功:
    adr lr, BSYM(phys_block)
    /* disable the Icache, Dcache and branch prediction */
    mrc     p15, 0, r6, c1, c0, 0
    ldr r7, =0x1804
    bic r6, r6, r7
    mcr     p15, 0, r6, c1, c0, 0
    isb
    /* disable the MMU and TEX */
    bic r7, r6, r7
    isb
    mcr p15, 0, r6, c1, c0, 0   @ turn on MMU, I-cache, etc
    mrc p15, 0, r6, c0, c0, 0   @ read id reg
    isb
    dsb
    msb
    mov r0, r0
    mov r0, r0
    ret lr
phys_block:
    blue_light
    loop感谢任何有线索或指点的人!
发布于 2015-06-16 13:15:39
由于杰森和德韦尔奇都通过评论(每个人)提出了我所需要的答案,为了清楚起见,我将在这里回答我自己的问题:
诀窍是简单地添加一个身份映射从/到执行转换的页面,允许我们跳到它与一个“物理”(实际上是虚拟的) PC,然后禁用MMU。
下面是最后的代码(有点具体,但有注释):
    /* Duplicate mapping to here */
    mrc p15, 0, r4, c2, c0, 0 // Get TTRB0
    ldr r10, =0x00003fff
    bic r4, r10 // Extract page table physical base address
    orr r4, #0xc0000000 // Nastily "translate" it to the virtual one
    /*
     * Here r8 holds vf_suspend's physical address. I had no way of
     * doing this more "locally", since both physical and virtual
     * space for my code are runtime-allocated.
     */
    add lr, r8, #(phys_block-vf_suspend) // -> phys_block physical address 
    lsr r9, lr, #20 // SECTION_SHIFT     -> Page index
    add r7, r4, r9, lsl #2 // PMD_ORDER  -> Entry address
    ldr r10, =0x00000c0e // Flags
    orr r9, r10, r9, lsl #20 // SECTION_SHIFT   -> Entry value
    str r9, [r7] // Write entry
    ret lr  // Jump / transition to virtual addressing
phys_block:
    /* disable the MMU and TEX */
    isb
    mrc     p15, 0, r6, c1, c0, 0
    ldr r7, =0x10000001
    bic r6, r6, r7
    mcr p15, 0, r6, c1, c0, 0   @ turn on MMU, I-cache, etc
    mrc p15, 0, r6, c0, c0, 0   @ read id reg
    isb
    dsb
    dmb
    /* disable the Icache, Dcache and branch prediction */
    mrc     p15, 0, r6, c1, c0, 0
    ldr r7, =0x1804
    bic r6, r6, r7
    mcr     p15, 0, r6, c1, c0, 0
    isb
    // Done !https://stackoverflow.com/questions/30843270
复制相似问题