qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] Trying to execute code outside RAM or ROM at 0x08000230


From: Peter Maydell
Subject: Re: [Qemu-devel] Trying to execute code outside RAM or ROM at 0x08000230
Date: Sat, 6 Jun 2015 23:11:39 +0100

On 6 June 2015 at 20:01, Liviu Ionescu <address@hidden> wrote:
> while working on the STM32 emulation, I noticed a problem related to the 
> specific memory layout of STM32 devices.
>
> these devices have the FLASH region at 0x08000000 instead of 0x00000000, and 
> since the specs require the presence of the reset vector at 0x0, there is an 
> internal alias of the entire region 0x08000000 at 0x00000000.
>
> however programming the flash via a jtag works only in the 0x08000000 range, 
> and although possible to make the linker script to run the code at 0x0 and 
> program it at 0x08000000, this is usually not done, and most STM32 
> applications are linked to run directly at 0x08000000.
>
> unfortunately qemu is not very happy with this arrangement :-(

Aliased memory regions do in general work, we use them in several
boards. There's probably just a bug in how you've set this one up.

> the STM32 initialisation code I used, similar to that used by Alistair, takes 
> a reversed approach, it first creates the main flash region at 0x00000000:
>
>     MemoryRegion *flash_mem = g_new(MemoryRegion, 1);
>
>     memory_region_init_ram(flash_mem, NULL, "cortexm-mem-flash", flash_size,
>             &error_abort);
>     vmstate_register_ram_global(flash_mem);
>     memory_region_set_readonly(flash_mem, true);
>     memory_region_add_subregion(system_memory, 0x00000000, flash_mem);
>
> and then creates a memory alias at 0x08000000:
>
>     MemoryRegion *flash_alias_mem = g_malloc(sizeof(MemoryRegion));
>
>     memory_region_init_alias(flash_alias_mem, NULL, "stm32-mem-flash-alias",
>             get_system_memory(), 0, flash_size_kb);

So, there's two odd things here:
 (1) why are you making this an alias of a chunk of the system address
     space, rather than just an alias of the flash memory you just created?
     The stm32 soc code does the latter.
 (2) this function takes the memory region size in bytes, so assuming
     your variable flash_size_kb is what the name suggests, you're
     trying to map a region that's a lot smaller than you want.

(The second one is probably the actual problem here.)

Try
    memory_region_init_alias(flash_alias_mem, NULL, "stm32-mem-flash-alias",
                             flash_mem, 0, flash_size);
which is what the stm32f205_soc code does.

One handy debugging tool for tracking down this kind of thing is to
use the QEMU monitor's "info mtree" command, which will show you all
the memory regions, where they've been put in the address space and
how large they are.

>     memory_region_set_readonly(flash_alias_mem, true);
>     memory_region_add_subregion(get_system_memory(), 0x08000000,
>             flash_alias_mem);
>
>
> this works fine, however it crashes when the core tries to executes the first 
> instruction in the 0x08000000 region.
>
> it crashes in cputlb.c: get_page_addr_code() since the memory region is found 
> as 'unassigned':

Yes; we can't execute code from memory that isn't backed by
real host RAM. It's not exactly a crash since it's a controlled
error-message-printing exit, but it does look rather misleading.
If you get here it typically means that either the board is
not putting RAM where it should, or the guest program has a bug
and is jumping off to an incorrect address.

> at first sight emulation follows a very complicated path required in larger 
> ARM cores, but completely useless for cortex-m, since none have MMUs and TLBs.
>
> ideally cortex-m cores should have a configuration bit to completely skip MMU 
> specific processing.

No, we need most of the code -- we still need to handle the mapping
of guest (virtual) addresses to host virtual addresses (or to io
read/write callbacks), which is most of what the CPUTLB code is about.
The only thing that differs between an MMU based system and an MPU
(or MMU/MPU-disabled) system is that get_phys_addr() will take a
simpler path that handles MPU like behaviour rather than doing a
page table walk.

-- PMM



reply via email to

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