mirror of https://github.com/xemu-project/xemu.git
target-arm: Fix resetting issues on ARMv7-M CPUs
When calling qemu_system_reset after startup on a Cortex-M CPU, the initial values of PC, MSP and the Thumb bit weren't being set correctly if the vector table was in ROM. In particular, since Thumb was 0, a Usage Fault would arise immediately after trying to execute any instruction on a Cortex-M. Signed-off-by: Martin Galvan <martin.galvan@tallertechnologies.com> Message-id: CAOKbPbaLt-LJsAKkQdOE0cs9Xx4OWrUfpDhATXPSdtuNw2xu_A@mail.gmail.com [PMM: removed an incorrect comment] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
bfb27e6042
commit
6e3cf5df01
|
@ -129,22 +129,34 @@ static void arm_cpu_reset(CPUState *s)
|
|||
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
|
||||
/* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
|
||||
clear at reset. Initial SP and PC are loaded from ROM. */
|
||||
* clear at reset. Initial SP and PC are loaded from ROM.
|
||||
*/
|
||||
if (IS_M(env)) {
|
||||
uint32_t pc;
|
||||
uint32_t initial_msp; /* Loaded from 0x0 */
|
||||
uint32_t initial_pc; /* Loaded from 0x4 */
|
||||
uint8_t *rom;
|
||||
|
||||
env->daif &= ~PSTATE_I;
|
||||
rom = rom_ptr(0);
|
||||
if (rom) {
|
||||
/* We should really use ldl_phys here, in case the guest
|
||||
modified flash and reset itself. However images
|
||||
loaded via -kernel have not been copied yet, so load the
|
||||
values directly from there. */
|
||||
env->regs[13] = ldl_p(rom) & 0xFFFFFFFC;
|
||||
pc = ldl_p(rom + 4);
|
||||
env->thumb = pc & 1;
|
||||
env->regs[15] = pc & ~1;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
env->regs[13] = initial_msp & 0xFFFFFFFC;
|
||||
env->regs[15] = initial_pc & ~1;
|
||||
env->thumb = initial_pc & 1;
|
||||
}
|
||||
|
||||
if (env->cp15.c1_sys & SCTLR_V) {
|
||||
|
|
Loading…
Reference in New Issue