This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Cortex-A53 - Understanding Translation Table (Cannot enable MMU)

Hello,

I'm trying to get MMU working on Cortex-A53. But still fails since at least 3 days. :(

I created following tables:

Level 1

0   0000000010006003                             
1   0000000010007003 
2   0000000010008003                             
3   0000000010009003           
4   000000001000a003
5   0000000000000000
[...]
511 0000000000000000

Level 2

Table 0 @ 0x10006000 (DDR RAM)

0   0000000000000701
1   0000000000200701
[...]
510 000000003fc00701
511 000000003fe00701

Table 1 @ 0x10007000 (DDR RAM)

0   0000000040000701
1   0000000040200701
[...]
510 000000007fc00701
511 000000007fe00701

Table 2 @ 0x10008000T (DDR RAM)

0   0000000080000701
1   0000000080200701
[...]
510 00000000bfc00701
511 00000000bfe00701

Table 3 @ 0x10009000 (DDR RAM)

0   00000000c0000701
1   00000000c0200701
[...]
503 00000000fee00701
504 0000000000000000
[...]
511 0000000000000000

Table 3 @ 0x1000a000 (Memory-Mapped Devices)

0   00000000ff000705
1   00000000ff200705
[...]
7   00000000ffe00705
8   0000000000000000
[...]
511 0000000000000000

The relevant setup for setup the pagetable:

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

The relevant code for enabling the MMU:

__el2_cache:
    mrs x0, SCTLR_EL2
    bic x0, x0, #(1 << 0)  /* Disable MMU */
    bic x0, x0, #(1 << 2)  /* Disable D-Cache */
    bic x0, 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, x0, #(1 << 0) /* Enable MMU */
    orr x0, x0, #(1 << 2)  /* Enable D-Cache */
    orr x0, x0, #(1 << 12) /* Enable I-Cache */
    msr SCTLR_EL2, x0 
    isb
    nop
    nop
    nop
    nop

I'm using U-Boot as bootloader (starting at EL2).

Have I something misunderstood? Have also tried several configurations. But still fails.

  • I have finally solved it.

    Unfortunately I didn't understand the translation table and the required settings.

    Now my current setup for EL2:
    Bare-Metal application is at 0x80000000 with a size of 512MiB defined in the linker script.

    Extract from my current linker script:

    ENTRY(_start)
    
    MEMORY {
        RAM_KERN (rwx) : ORIGIN = 0x80000000, LENGTH = 512M
    }
    
    STACK_EL3 = 4K;
    STACK_EL2 = 4K;
    STACK_EL1 = 64M;
    STACK_EL0 = 1M;

    Some settings for TCR_EL2:
    Currently I use a 1TiB range for TOSZ (0x17), so i also have a level 0 table with only one entry. But decrease this value later. I use 4KiB granule for the tables.

    Level 0:
    Contains only one entry at index 0 which points to the first (and only) level 1 table. All other entries are invalid (zero).

    Level 1 (Index 0):
    These table contains two valid table entries. Because the bare-metal application starts at 0x80000000, the first 1GiB entries are currently invalid. So there is the bare-metal application at index 2. Index 3 in the level contains the entry to the MMIO table. All other subsequent entries are invalid.

    Level 2 (Bare-Metal application):
    These table contains 256 2MiB block entries because in linker script i defined 512MiB for the application. Start point is index 0 of the level 2 table. The subsequent entries (256) are invalid.

    Level 2 (MMIO devices):
    These table contains 8 2MiB block entries starting at index 503, because the IO is mapped at start point 0xFF000000. The first 502 entries are currently invalid.

    Now I can successfully enable the MMU.