微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AArch64 (Cortex-A53) - 理解转换表

如何解决AArch64 (Cortex-A53) - 理解转换表

我正在尝试理解 Cortex-A53 的转换表。目前没有成功。无法启用 MMU。我想知道如何正确设置 MMU。已经从 ARM 尝试过这个 tutorial

相关代码(启用):

__el2_cache:
    mrs x0,SCTLR_EL2
    bic x0,x0,#(1 << 0)  /* disable MMU */
    bic x0,#(1 << 2)  /* disable D-Cache */
    bic x0,#(1 << 12) /* disable I-Cache */
    msr SCTLR_EL2,x0
    isb

    /* Invalidate and clean I/D-Cache */
    bl _cpu_icache_invalidate
    bl _cpu_dcache_l1_invalidate
    bl _cpu_dcache_l2_invalidate
    
__el2_pagetable:
    /* Create pagetable for EL2 */
    bl _cpu_el2_tlb_create
    
    /* Invalidate (old) Pagetable */
    tlbi ALLE2
    dsb sy
    isb
    
    mrs x0,SCTLR_EL2
    orr x0,#(1 << 0)  /* Enable MMU */
    orr x0,#(1 << 2)  /* Enable D-Cache */
    orr x0,#(1 << 12) /* Enable I-Cache */
    msr SCTLR_EL2,x0 
    isb /* <-- cpu hangs here */
    nop
    nop
    nop
    nop

当我不启用缓存时它也不起作用。用于使缓存无效的子过程调用中的 code 也基于 ARM 教程。

我在 _cpu_el2_tlb_create 中创建了转换表并设置了相关寄存器:

    ldr x1,=0x80803520
    msr TCR_EL2,x1
    ldr x1,=0x4400FF00
    msr MAIR_EL2,=_tlb_el2_tbb0_lv1
    msr TTBR0_EL2,x1
    mov x8,xzr
    dsb sy
    ret

已使用与 U-Boot 相同的设置(内存类型、可共享、...),但仍然无法正常工作。

_cpu_el2_tlb_create 创建以下表格:

Level 1          Level 2
0000000010006003 0000000000000711 0000000040000711 0000000080000711 00000000c0000711 00000000ff000401  
0000000010007003 0000000000200711 0000000040200711 0000000080200711 00000000c0200711 00000000ff200401     
0000000010008003 0000000000400711 0000000040400711 0000000080400711 00000000c0400711 00000000ff400401
0000000010009003 0000000000600711 0000000040600711 0000000080600711 00000000c0600711 00000000ff600401
000000001000a003 0000000000800711 0000000040800711 0000000080800711 00000000c0800711 00000000ff800401
0000000000000000 0000000000a00711 0000000040a00711 0000000080a00711 00000000c0a00711 00000000ffa00401
0000000000000000 0000000000c00711 0000000040c00711 0000000080c00711 00000000c0c00711 00000000ffc00401
0000000000000000 0000000000e00711 0000000040e00711 0000000080e00711 00000000c0e00711 00000000ffe00401
0000000000000000 0000000001000711 0000000041000711 0000000081000711 00000000c1000711 0000000000000000
[...]
0000000000000000 000000003ee00711 000000007ee00711 00000000bee00711 00000000fee00711 0000000000000000
0000000000000000 000000003f000711 000000007f000711 00000000bf000711 0000000000000000 0000000000000000
0000000000000000 000000003f200711 000000007f200711 00000000bf200711 0000000000000000 0000000000000000
0000000000000000 000000003f400711 000000007f400711 00000000bf400711 0000000000000000 0000000000000000
0000000000000000 000000003f600711 000000007f600711 00000000bf600711 0000000000000000 0000000000000000
0000000000000000 000000003f800711 000000007f800711 00000000bf800711 0000000000000000 0000000000000000
0000000000000000 000000003fa00711 000000007fa00711 00000000bfa00711 0000000000000000 0000000000000000
0000000000000000 000000003fc00711 000000007fc00711 00000000bfc00711 0000000000000000 0000000000000000
0000000000000000 000000003fe00711 000000007fe00711 00000000bfe00711 0000000000000000 0000000000000000

TTBR0_EL2 也指向正确的位置并且是 4KiB 对齐。

来自使用过的电路板的存储设备映射:

0x00000000 - 0xFF000000 DDR-RAM
0xFF000000 - 0xFFFF0000 Memory-Mapped I/O

解决方法

我解决了这个问题。

遗憾的是我没有理解翻译表和所需的设置。

现在我当前的 EL2 设置:
裸机应用程序位于 0x80000000,链接器脚本中定义的大小为 512MiB

从我当前的链接器脚本中提取:

ENTRY(_start)

MEMORY {
    RAM_KERN (rwx) : ORIGIN = 0x80000000,LENGTH = 512M
}

STACK_EL3 = 4K;
STACK_EL2 = 4K;
STACK_EL1 = 64M;
STACK_EL0 = 1M;

TCR_EL2 的一些设置:
目前我对 TOSZ (0x17) 使用 1TiB 范围,所以我还有一个只有一个条目的 0 级表。但稍后减小此值。感谢@Siguza 的提示。我对表格使用 4KiB 颗粒。

0 级:
仅包含索引 0 处的一个条目,该条目指向第一个(也是唯一一个)级别 1 表。所有其他条目均无效(零)。

级别 1(索引 0):
这些表包含两个有效的表条目。由于裸机应用程序从 0x80000000 开始,因此前 1GiB 条目当前无效。因此,在索引 2 处有裸机应用程序。级别中的索引 3 包含 MMIO 表的条目。所有其他后续条目均无效。

2 级(裸机应用):
这些表包含 256 个 2MiB 块条目,因为在链接描述文件中我为应用程序定义了 512MiB。起点是级别 2 表的索引 0。后续条目 (256) 无效。

2 级(MMIO 设备):
这些表包含从索引 503 开始​​的 8 个 2MiB 块条目,因为 IO 映射在起点 0xFF000000。前 502 个条目当前无效。

现在我可以成功启用 MMU。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。