[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Get_page_addr_code_hostp function returns -1 after turning MMU on

From: ckim
Subject: Get_page_addr_code_hostp function returns -1 after turning MMU on
Date: Fri, 12 Mar 2021 17:33:08 +0900

Hello, all


I’m having a trouble while trying to run a bare-metal program on qemu (virt, cortext-a72, running in EL3), so I ask for a help here again.

The phenomenon is : right after I set sctlr_el3 register (with MMU enable bit set), the next instruction fetch causes exception, with “cannot access memory at ...” error.

I have followed the get_phy_addr function (get_phy_addr_lpae inside) and saw qemu walks the page table almost ok. (almost because I didn’t understand 100% of them).

At least it followed all the descriptor addresses, entries, and attributes. The get_phys_addr returned false (meaning translation was successful).

The arm-supported bare-metal startup code has a page table that has 1GB block descriptors and a table entry in the first table, and the next level tables had 2MB block entries, which looked like level 1 and level 2 tables according to the Armv8 spec. (the TTBR0_EL3 register points to this first table)

(Armv8 spec says level 0 table can’t have block descriptor and level 1 and level 2 block size is 1GB and 2MB, for 64KB granule, which is my case)

So I tried adding the level 0 table before the first table and now qemu thinks the final block entry is 2MB size and sets page_size to 2MB. (before it thought the last block was 1GB).


But the problem is still persistent. Now I should see the very complex looking tlb_set_page_with_attrs function (they are in arm_cpu_tbl_fill function in target/arm/tlb_helper.c. )

When briefly following it with debugger, I found that in the function below the condition “entry->addr_code & TLB_MMIO” is true and it returns -1. (by the way I set the first 2MB’s to read-only blocks, because they are flash/ROM)

Could anyone explain to me what this condition is? Just a brief explanation will be much appreciated.


tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,

                                        void **hostp)


    uintptr_t mmu_idx = cpu_mmu_index(env, true);

    uintptr_t index = tlb_index(env, mmu_idx, addr);

    CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);

    void *p;


    if (unlikely(!tlb_hit(entry->addr_code, addr))) {

        .... omitted...



    if (unlikely(entry->addr_code & TLB_MMIO)) {        <======= returns -1

        /* The region is not backed by RAM.  */

        if (hostp) {

            *hostp = NULL;


        return -1;



    p = (void *)((uintptr_t)addr + entry->addend);

    if (hostp) {

        *hostp = p;


    return qemu_ram_addr_from_host_nofail(p);





Chan Kim


reply via email to

[Prev in Thread] Current Thread [Next in Thread]