aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/arm/cpu.c18
-rw-r--r--target/arm/cpu.h3
2 files changed, 17 insertions, 4 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 291ff0b..27d9e90 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -187,6 +187,7 @@ static void arm_cpu_reset(CPUState *s)
uint32_t initial_msp; /* Loaded from 0x0 */
uint32_t initial_pc; /* Loaded from 0x4 */
uint8_t *rom;
+ uint32_t vecbase;
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
env->v7m.secure = true;
@@ -214,8 +215,11 @@ static void arm_cpu_reset(CPUState *s)
/* Unlike A/R profile, M profile defines the reset LR value */
env->regs[14] = 0xffffffff;
- /* Load the initial SP and PC from the vector table at address 0 */
- rom = rom_ptr(0);
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
+
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
+ vecbase = env->v7m.vecbase[env->v7m.secure];
+ rom = rom_ptr(vecbase);
if (rom) {
/* Address zero is covered by ROM which hasn't yet been
* copied into physical memory.
@@ -228,8 +232,8 @@ static void arm_cpu_reset(CPUState *s)
* 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);
+ initial_msp = ldl_phys(s->as, vecbase);
+ initial_pc = ldl_phys(s->as, vecbase + 4);
}
env->regs[13] = initial_msp & 0xFFFFFFFC;
@@ -624,6 +628,10 @@ static Property arm_cpu_pmsav7_dregion_property =
pmsav7_dregion,
qdev_prop_uint32, uint32_t);
+/* M profile: initial value of the Secure VTOR */
+static Property arm_cpu_initsvtor_property =
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
+
static void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -694,6 +702,8 @@ static void arm_cpu_post_init(Object *obj)
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
+ &error_abort);
}
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4710a43..72b5668 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -731,6 +731,9 @@ struct ARMCPU {
*/
uint32_t psci_conduit;
+ /* For v8M, initial value of the Secure VTOR */
+ uint32_t init_svtor;
+
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
*/