[RFC PATCH v2 03/14] hw/m68k: transition virt machine to multi-phase reset

Alex Bennée posted 14 patches 1 month, 3 weeks ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Thomas Huth <huth@tuxfamily.org>, Laurent Vivier <laurent@vivier.eu>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, Peter Maydell <peter.maydell@linaro.org>, Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Aleksandar Rikalo <arikalo@gmail.com>, Bastian Koppelmann <kbastian@rumtueddeln.de>
[RFC PATCH v2 03/14] hw/m68k: transition virt machine to multi-phase reset
Posted by Alex Bennée 1 month, 3 weeks ago
We don't need to re-create the architectural reset behaviour now it is
handled in the core m68k CPU reset code. We do however need to add
support for direct kernel booting so we stash that value in
env->direct_kernel_boot_pc and enhance m68k_cpu_reset_exit() to use it
if set.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - re-write to use proper 3-phase logic, so dropped all tags
  - favour cpu_reset over resettable_reset(cs)
---
 target/m68k/cpu.h |  2 ++
 hw/m68k/virt.c    | 34 ++++++++++------------------------
 target/m68k/cpu.c |  5 +++++
 3 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 7911ab9de30..d3b604689ab 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -155,6 +155,8 @@ typedef struct CPUArchState {
 
     /* Fields from here on are preserved across CPU reset. */
     uint64_t features;
+    /* Override the normal reset vector with a direct kernel boot */
+    uint32_t direct_kernel_boot_pc;
 } CPUM68KState;
 
 /*
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e67900c727d..b2e651ebcfd 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -87,23 +87,6 @@
 #define VIRT_VIRTIO_MMIO_BASE 0xff010000     /* MMIO: 0xff010000 - 0xff01ffff */
 #define VIRT_VIRTIO_IRQ_BASE  PIC_IRQ(2, 1)  /* PIC: 2, 3, 4, 5, IRQ: ALL */
 
-typedef struct {
-    M68kCPU *cpu;
-    hwaddr initial_pc;
-    hwaddr initial_stack;
-} ResetInfo;
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetInfo *reset_info = opaque;
-    M68kCPU *cpu = reset_info->cpu;
-    CPUState *cs = CPU(cpu);
-
-    cpu_reset(cs);
-    cpu->env.aregs[7] = reset_info->initial_stack;
-    cpu->env.pc = reset_info->initial_pc;
-}
-
 static void rerandomize_rng_seed(void *opaque)
 {
     struct bi_record *rng_seed = opaque;
@@ -111,6 +94,14 @@ static void rerandomize_rng_seed(void *opaque)
                                 be16_to_cpu(*(uint16_t *)rng_seed->data));
 }
 
+static void virt_machine_reset(MachineState *ms, ResetType type)
+{
+    CPUState *cs = first_cpu;
+
+    qemu_devices_reset(type);
+    cpu_reset(cs);
+}
+
 static void virt_init(MachineState *machine)
 {
     M68kCPU *cpu = NULL;
@@ -129,7 +120,6 @@ static void virt_init(MachineState *machine)
     SysBusDevice *sysbus;
     hwaddr io_base;
     int i;
-    ResetInfo *reset_info;
     uint8_t rng_seed[32];
 
     if (ram_size > 3399672 * KiB) {
@@ -142,14 +132,9 @@ static void virt_init(MachineState *machine)
         exit(1);
     }
 
-    reset_info = g_new0(ResetInfo, 1);
-
     /* init CPUs */
     cpu = M68K_CPU(cpu_create(machine->cpu_type));
 
-    reset_info->cpu = cpu;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
     /* RAM */
     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
 
@@ -235,7 +220,7 @@ static void virt_init(MachineState *machine)
             error_report("could not load kernel '%s'", kernel_filename);
             exit(1);
         }
-        reset_info->initial_pc = elf_entry;
+        cpu->env.direct_kernel_boot_pc = elf_entry;
         parameters_base = (high + 1) & ~1;
         param_ptr = param_blob;
 
@@ -315,6 +300,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
     MachineClass *mc = MACHINE_CLASS(oc);
     mc->desc = "QEMU M68K Virtual Machine";
     mc->init = virt_init;
+    mc->reset = virt_machine_reset;
     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
     mc->max_cpus = 1;
     mc->no_floppy = 1;
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 0dce8ef282e..71393b9fa19 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -193,6 +193,11 @@ static void m68k_cpu_reset_exit(Object *obj, ResetType type)
                                          MEMTXATTRS_UNSPECIFIED, NULL);
     env->pc = address_space_ldl_be(cs->as, 4,
                                    MEMTXATTRS_UNSPECIFIED, NULL);
+
+    /* some machine models support direct kernel boot */
+    if (env->direct_kernel_boot_pc) {
+        env->pc = env->direct_kernel_boot_pc;
+    }
 #endif
 }
 
-- 
2.47.3


Re: [RFC PATCH v2 03/14] hw/m68k: transition virt machine to multi-phase reset
Posted by Peter Maydell 1 month, 2 weeks ago
On Thu, 19 Feb 2026 at 17:18, Alex Bennée <alex.bennee@linaro.org> wrote:
>
> We don't need to re-create the architectural reset behaviour now it is
> handled in the core m68k CPU reset code. We do however need to add
> support for direct kernel booting so we stash that value in
> env->direct_kernel_boot_pc and enhance m68k_cpu_reset_exit() to use it
> if set.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
> ---
> v2
>   - re-write to use proper 3-phase logic, so dropped all tags
>   - favour cpu_reset over resettable_reset(cs)

The commit message says it's doing three-phase reset, but
the actual code is not:

> +static void virt_machine_reset(MachineState *ms, ResetType type)
> +{
> +    CPUState *cs = first_cpu;
> +
> +    qemu_devices_reset(type);
> +    cpu_reset(cs);

This first resets the whole system (going through its
three phases) and then the CPU (which does its phases
separately). Three-phase support would imply having the
CPU do its enter phase at the same time as the other devices,
its hold phase with the others, and so on.

If you wanted that you could do it by using
qemu_register_resettable(OBJECT(cpu)) instead of having
a MachineClass::reset method, given that the only two
things you're doing in it are the default thing and a
cpu_reset() call.

> @@ -315,6 +300,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
>      MachineClass *mc = MACHINE_CLASS(oc);
>      mc->desc = "QEMU M68K Virtual Machine";
>      mc->init = virt_init;
> +    mc->reset = virt_machine_reset;
>      mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
>      mc->max_cpus = 1;
>      mc->no_floppy = 1;

I did have a plan to look at making MachineClass a subset of
Device so that it could be three-phase-reset aware rather than
having its own special-snowflake reset method.

thanks
-- PMM
Re: [RFC PATCH v2 03/14] hw/m68k: transition virt machine to multi-phase reset
Posted by Pierrick Bouvier 1 month, 3 weeks ago
On 2/19/26 9:17 AM, Alex Bennée wrote:
> We don't need to re-create the architectural reset behaviour now it is
> handled in the core m68k CPU reset code. We do however need to add
> support for direct kernel booting so we stash that value in
> env->direct_kernel_boot_pc and enhance m68k_cpu_reset_exit() to use it
> if set.
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> 
> ---
> v2
>    - re-write to use proper 3-phase logic, so dropped all tags
>    - favour cpu_reset over resettable_reset(cs)
> ---
>   target/m68k/cpu.h |  2 ++
>   hw/m68k/virt.c    | 34 ++++++++++------------------------
>   target/m68k/cpu.c |  5 +++++
>   3 files changed, 17 insertions(+), 24 deletions(-)
> 

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>