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 <[email protected]>
---
 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


Reply via email to