On 8 June 2015 at 18:32, Liviu Ionescu <i...@livius.net> wrote: > Hi Alistair/Peter, > > I am having difficulties to make the armv7m code run if linked from > 0x08000000. > > based on the tracing info that I have (copied below), it seems that the cpu > throws an early exception, properly caught by the cpu and displayed (see the > indented lines). > > this is weird, since displaying these lines inside the UsageFault_Handler > means the alias works and the core can execute code from 0x08000000. > > my guess is that there is a bug in the reset code preventing the cpu to fetch > the Reset_Handler address from the first words in memory. > > I traced the cpu.c: arm_cpu_reset(CPUState *s) function and around line 170 > there are two calls to initialise msp and pc: > > initial_msp = ldl_phys(s->as, 0); > initial_pc = ldl_phys(s->as, 4); > > in my environment both return 0, probably not being able to fetch data from > the aliased region.
I think the problem here is that we're taking the "not a ROM blob" branch of this if(), when we should be taking the "is a rom blob" branch: rom = rom_ptr(0); if (rom) { /* Address zero is covered by ROM which hasn't yet been * copied into physical memory. */ initial_msp = ldl_p(rom); initial_pc = ldl_p(rom + 4); } else { /* Address zero not covered by a ROM blob, or the ROM blob * is in non-modifiable memory and this is a second reset after * it got copied into memory. In the latter case, rom_ptr * will return a NULL pointer and we should use ldl_phys instead. */ initial_msp = ldl_phys(s->as, 0); initial_pc = ldl_phys(s->as, 4); } As the comments explain, for ROMs we need to load directly from the ROM blob, not via load-from-physical-memory, because at the point where the CPU is reset the ROM blob hasn't been copied into memory. (Image contents loaded via -kernel are a kind of ROM blob. This is what QEMU uses for "binary blob that needs to be copied into memory at startup and on reset"; the name is because on x86 that's what you need to do with ROM images.) Unfortunately the test we're doing to decide is calling rom_ptr(), which only looks at the addresses the ROMs are registered to be copied into; it doesn't know about aliasing. If you fudge the if() statement to use 0x08000000 rather than 0 as the address passed to rom_ptr() it will probably work. I'm not sure what the correct fix for this is, though. (Really the problem is that we do the initial PC/SP load in CPU reset, and we don't have two-phase reset. In hardware PC/SP load happens when the CPU *comes out* of reset, as the first thing it does. But we don't have any good place to put that in QEMU, so the reset function is the best we can do, and you end up with this ugly hack.) -- PMM