diff mbox series

[4/5] target/rx: Load reset vector from memory after first run

Message ID 20250215021654.1786679-5-keithp@keithp.com (mailing list archive)
State New
Headers show
Series Renesas RX target fixes | expand

Commit Message

Keith Packard Feb. 15, 2025, 2:16 a.m. UTC
The ROM images all get deleted as they've been loaded to memory, so we
can't go fetch the reset vector from there. Instead, fetch it from
memory. To make that work, we need to execute the delayed mmu setup
function tcg_commit_cpu as that wires up memory dispatching.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 target/rx/cpu.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

Comments

Richard Henderson Feb. 15, 2025, 6:24 p.m. UTC | #1
On 2/14/25 18:16, Keith Packard via wrote:
> The ROM images all get deleted as they've been loaded to memory, so we
> can't go fetch the reset vector from there. Instead, fetch it from
> memory. To make that work, we need to execute the delayed mmu setup
> function tcg_commit_cpu as that wires up memory dispatching.
> 
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>   target/rx/cpu.c | 24 +++++++++++++++++++-----
>   1 file changed, 19 insertions(+), 5 deletions(-)

IIRC this is where the cpu needs to be part of the 3-phase reset process.
ROM gets reset too, but with unspecified ordering wrt the cpu itself.
By delaying the load of the reset vector to the reset_exit phase,
you can always load from rom.

I believe Peter most recently handled a very similar situation with armv7m.


r~
Peter Maydell Feb. 17, 2025, 9:49 a.m. UTC | #2
On Sat, 15 Feb 2025 at 18:24, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 2/14/25 18:16, Keith Packard via wrote:
> > The ROM images all get deleted as they've been loaded to memory, so we
> > can't go fetch the reset vector from there. Instead, fetch it from
> > memory. To make that work, we need to execute the delayed mmu setup
> > function tcg_commit_cpu as that wires up memory dispatching.
> >
> > Signed-off-by: Keith Packard <keithp@keithp.com>
> > ---
> >   target/rx/cpu.c | 24 +++++++++++++++++++-----
> >   1 file changed, 19 insertions(+), 5 deletions(-)
>
> IIRC this is where the cpu needs to be part of the 3-phase reset process.
> ROM gets reset too, but with unspecified ordering wrt the cpu itself.
> By delaying the load of the reset vector to the reset_exit phase,
> you can always load from rom.
>
> I believe Peter most recently handled a very similar situation with armv7m.

v7m still does the same thing this patch does, where you call
rom_ptr_for_as() and look at the return value to see what's
going on -- see the code and comments in
target/arm/cpu.c:arm_cpu_reset_hold() ("Load the initial SP and PC").

Now that we do a full three phase reset for everything, I
think this probably could be cleaned up, but there's a
fair chance that there's some unexpected issue in there
that I won't find out until I try it. So I'm definitely
not going to require that somebody else does that before
I've had a go at it on the v7m code.

So I'm OK with this patch doing this the way it does,
except that I have one question: what's that
process_queued_cpu_work() call doing? We don't need
that on the Arm equivalent...

Also, if() statements always have braces in QEMU, even
if the body of the if is a single statement. But since
if you don't set env->pc it is zero anyway, you don't
need the if() at all I think and can directly set
env->pc unconditionally.

thanks
-- PMM
Keith Packard Feb. 18, 2025, 8:11 p.m. UTC | #3
From: Richard Henderson <richard.henderson@linaro.org>
Date: Sat, 15 Feb 2025 10:24:05 -0800

> By delaying the load of the reset vector to the reset_exit phase,
> you can always load from rom.

I'm not sure how -- the ROM image is discarded when it gets loaded into
read-only memory. If loaded to read-write memory, I bet it would
stay around.
Keith Packard Feb. 18, 2025, 8:18 p.m. UTC | #4
> > By delaying the load of the reset vector to the reset_exit phase,
> > you can always load from rom.

> I'm not sure how -- the ROM image is discarded when it gets loaded into
> read-only memory. If loaded to read-write memory, I bet it would
> stay around.

Ah, but by delaying until after cpu_reset has finished, I can always
load it from target memory. I bet that's what you meant, and yes it
works fine.
Keith Packard Feb. 18, 2025, 8:22 p.m. UTC | #5
> So I'm OK with this patch doing this the way it does,
> except that I have one question: what's that
> process_queued_cpu_work() call doing? We don't need
> that on the Arm equivalent...

Yup, I needed that because I was running this bit at cpu_reset_hold
time, not waiting until after cpu reset was finished. At cpu_reset_hold
time, the re-initialization of memory_dispatch hadn't been executed yet,
so attempts to resolve addresses crashed unless I synchronously flushed
the work queue where the call to tcg_commit_cpu was pending.

All fixed now that I'm setting the pc after the call to cpu_reset has
completed.

> Also, if() statements always have braces in QEMU, even
> if the body of the if is a single statement. But since
> if you don't set env->pc it is zero anyway, you don't
> need the if() at all I think and can directly set
> env->pc unconditionally.

Thanks for the formatting advice; I'll get it cleaned up.
diff mbox series

Patch

diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 04dd34b310..a32b410bb1 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -24,6 +24,7 @@ 
 #include "exec/exec-all.h"
 #include "exec/page-protection.h"
 #include "exec/translation-block.h"
+#include "exec/cpu_ldst.h"
 #include "hw/loader.h"
 #include "fpu/softfloat.h"
 #include "tcg/debug-assert.h"
@@ -77,7 +78,8 @@  static void rx_cpu_reset_hold(Object *obj, ResetType type)
     CPUState *cs = CPU(obj);
     RXCPUClass *rcc = RX_CPU_GET_CLASS(obj);
     CPURXState *env = cpu_env(cs);
-    uint32_t *resetvec;
+    uint32_t *resetvec_p;
+    vaddr resetvec;
 
     if (rcc->parent_phases.hold) {
         rcc->parent_phases.hold(obj, type);
@@ -85,11 +87,23 @@  static void rx_cpu_reset_hold(Object *obj, ResetType type)
 
     memset(env, 0, offsetof(CPURXState, end_reset_fields));
 
-    resetvec = rom_ptr(0xfffffffc, 4);
-    if (resetvec) {
-        /* In the case of kernel, it is ignored because it is not set. */
-        env->pc = ldl_p(resetvec);
+    /*
+     * During the first reset phase, the memory dispatching hook
+     * hasn't been set, so we can't fetch the reset vector from
+     * memory. After that, the ROM image will have been discarded, so
+     * we can't fetch the reset vector from there. So we have two
+     * paths here.
+     */
+    resetvec_p = rom_ptr_for_as(cs->as, 0xfffffffc, 4);
+    if (resetvec_p)
+        resetvec = ldl_p(resetvec_p);
+    else {
+        process_queued_cpu_work(cs);
+        resetvec = cpu_ldl_data(env, 0xfffffffc);
     }
+    if (resetvec)
+        env->pc = resetvec;
+
     rx_cpu_unpack_psw(env, 0, 1);
     env->regs[0] = env->isp = env->usp = 0;
     env->fpsw = 0;