diff options
author | Paul Brook <paul@codesourcery.com> | 2010-04-05 19:34:51 +0100 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2010-04-05 19:43:12 +0100 |
commit | 983fe82611b87a1198d32f58636f6f38b88ad337 (patch) | |
tree | 5736751719ff68c4da6729108b1d1d524710a2a7 /target-arm | |
parent | 116348def2bb446d972bdc2f44bd77ff631f85de (diff) |
ARMv7-M reset fixes
Move ARMv7-M PC/SP initialization to the CPU reset routine. Add a board
reset routine to call this. Also load values directly from ROM as
images have not been copied yet.
Avoid clearing the NVIC pointer on cpu reset.
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/cpu.h | 2 | ||||
-rw-r--r-- | target-arm/helper.c | 33 |
2 files changed, 25 insertions, 10 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 3892db44e0..1e34541733 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -146,7 +146,6 @@ typedef struct CPUARMState { int current_sp; int exception; int pending_exception; - void *nvic; } v7m; /* Coprocessor IO used by peripherals */ @@ -205,6 +204,7 @@ typedef struct CPUARMState { CPU_COMMON /* These fields after the common ones so they are preserved on reset. */ + void *nvic; struct arm_boot_info *boot_info; } CPUARMState; diff --git a/target-arm/helper.c b/target-arm/helper.c index e092b2122e..7e6a8186d5 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -8,6 +8,7 @@ #include "helpers.h" #include "qemu-common.h" #include "host-utils.h" +#include "hw/loader.h" static uint32_t cortexa9_cp15_c0_c1[8] = { 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 }; @@ -204,14 +205,28 @@ void cpu_reset(CPUARMState *env) #else /* SVC mode with interrupts disabled. */ env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; + env->regs[15] = 0; /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is - clear at reset. */ - if (IS_M(env)) + clear at reset. Initial SP and PC are loaded from ROM. */ + if (IS_M(env)) { + uint32_t pc; + uint8_t *rom; env->uncached_cpsr &= ~CPSR_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 -kenrel have not been copied yet, so load the + values directly from there. */ + env->regs[13] = ldl_p(rom); + pc = ldl_p(rom + 4); + env->thumb = pc & 1; + env->regs[15] = pc & ~1; + } + } env->vfp.xregs[ARM_VFP_FPEXC] = 0; env->cp15.c2_base_mask = 0xffffc000u; #endif - env->regs[15] = 0; tlb_flush(env, 1); } @@ -624,7 +639,7 @@ static void do_v7m_exception_exit(CPUARMState *env) type = env->regs[15]; if (env->v7m.exception != 0) - armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception); + armv7m_nvic_complete_irq(env->nvic, env->v7m.exception); /* Switch to the target stack. */ switch_v7m_sp(env, (type & 4) != 0); @@ -666,15 +681,15 @@ static void do_interrupt_v7m(CPUARMState *env) one we're raising. */ switch (env->exception_index) { case EXCP_UDEF: - armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE); + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); return; case EXCP_SWI: env->regs[15] += 2; - armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC); + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC); return; case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: - armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM); + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM); return; case EXCP_BKPT: if (semihosting_enabled) { @@ -686,10 +701,10 @@ static void do_interrupt_v7m(CPUARMState *env) return; } } - armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG); + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG); return; case EXCP_IRQ: - env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic); + env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic); break; case EXCP_EXCEPTION_EXIT: do_v7m_exception_exit(env); |