All 68k chips should be able to follow the architectural behaviour on
reset which is to load the initial sp/pc from the first 8 bytes of the
address space.
To avoid any potential issues with un-reset memory controllers we
punt the final setting of the register to the exit phase when
everything else is guaranteed to have been through the hold phase.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
target/m68k/cpu.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index d849a4a90fc..0dce8ef282e 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -25,6 +25,7 @@
#ifndef CONFIG_USER_ONLY
#include "migration/vmstate.h"
+#include "system/memory.h"
#endif
#include "cpu.h"
@@ -174,9 +175,25 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
}
cpu_m68k_set_fpcr(env, 0);
env->fpsr = 0;
+}
- /* TODO: We should set PC from the interrupt vector. */
- env->pc = 0;
+/*
+ * We defer the final setting of the PC to the exit phase to ensure
+ * if any memory controllers need to be reset they are before we read
+ * the initial reset vector. This is a NOP for user-mode which will
+ * set the PC in init_main_thread() after the CPU is reset.
+ */
+static void m68k_cpu_reset_exit(Object *obj, ResetType type)
+{
+#ifndef CONFIG_USER_ONLY
+ CPUState *cs = CPU(obj);
+ CPUM68KState *env = cpu_env(cs);
+
+ env->aregs[7] = address_space_ldl_be(cs->as, 0,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+ env->pc = address_space_ldl_be(cs->as, 4,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+#endif
}
static void m68k_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
@@ -396,7 +413,6 @@ static void m68k_cpu_realizefn(DeviceState *dev, Error **errp)
m68k_cpu_init_gdb(cpu);
- cpu_reset(cs);
qemu_init_vcpu(cs);
mcc->parent_realize(dev, errp);
@@ -641,7 +657,8 @@ static void m68k_cpu_class_init(ObjectClass *c, const void *data)
device_class_set_parent_realize(dc, m68k_cpu_realizefn,
&mcc->parent_realize);
- resettable_class_set_parent_phases(rc, NULL, m68k_cpu_reset_hold, NULL,
+ resettable_class_set_parent_phases(rc, NULL,
+ m68k_cpu_reset_hold, m68k_cpu_reset_exit,
&mcc->parent_phases);
cc->class_by_name = m68k_cpu_class_by_name;
--
2.47.3