With generic cpu reset interface, pc register is entry of FLASH for UEFI BIOS. However with direct kernel booting requirement, there is a little different, pc register of primary cpu is entry address of ELF file.
At the same time with requirement of cpu hotplug, hot-added CPU should register reset interface for this cpu object. Now reset callback is not registered for hot-added CPU. With this patch reset callback for CPU is register when CPU instance is created, and reset interface is added for virt-machine board. In reset interface of virt-machine, reset for direct kernel booting requirement is called. Signed-off-by: Bibo Mao <maob...@loongson.cn> --- v1 ... v2: 1. Add qemu_unregister_reset() in function loongarch_cpu_unrealizefn(), remove reset callback if vCPU is unrealized. --- Signed-off-by: Bibo Mao <maob...@loongson.cn> --- hw/loongarch/boot.c | 9 +-------- hw/loongarch/virt.c | 14 ++++++++++++++ include/hw/loongarch/boot.h | 1 + target/loongarch/cpu.c | 11 +++++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c index 14d6c52d4e..4919758a20 100644 --- a/hw/loongarch/boot.c +++ b/hw/loongarch/boot.c @@ -324,12 +324,11 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info) return kernel_entry; } -static void reset_load_elf(void *opaque) +void reset_load_elf(void *opaque) { LoongArchCPU *cpu = opaque; CPULoongArchState *env = &cpu->env; - cpu_reset(CPU(cpu)); if (env->load_elf) { if (cpu == LOONGARCH_CPU(first_cpu)) { env->gpr[4] = env->boot_info->a0; @@ -429,12 +428,6 @@ static void loongarch_direct_kernel_boot(MachineState *ms, void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info) { LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms); - int i; - - /* register reset function */ - for (i = 0; i < ms->smp.cpus; i++) { - qemu_register_reset(reset_load_elf, LOONGARCH_CPU(qemu_get_cpu(i))); - } info->kernel_filename = ms->kernel_filename; info->kernel_cmdline = ms->kernel_cmdline; diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index b15ada2078..4fc8506c10 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -1199,6 +1199,19 @@ static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx) } } +static void virt_reset(MachineState *machine, ResetType type) +{ + CPUState *cs; + + /* Reset all devices including CPU devices */ + qemu_devices_reset(type); + + /* Reset PC and register context for kernel direct booting method */ + CPU_FOREACH(cs) { + reset_load_elf(LOONGARCH_CPU(cs)); + } +} + static void virt_class_init(ObjectClass *oc, const void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1223,6 +1236,7 @@ static void virt_class_init(ObjectClass *oc, const void *data) mc->has_hotpluggable_cpus = true; mc->get_hotplug_handler = virt_get_hotplug_handler; mc->default_nic = "virtio-net-pci"; + mc->reset = virt_reset; hc->plug = virt_device_plug_cb; hc->pre_plug = virt_device_pre_plug; hc->unplug_request = virt_device_unplug_request; diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h index 9819f7fbe3..386b4406ad 100644 --- a/include/hw/loongarch/boot.h +++ b/include/hw/loongarch/boot.h @@ -114,5 +114,6 @@ struct memmap_entry { }; void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info); +void reset_load_elf(void *opaque); #endif /* HW_LOONGARCH_BOOT_H */ diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 3a7621c0ea..61c8acb3c2 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -652,6 +652,13 @@ static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) info->print_insn = print_insn_loongarch; } +#ifndef CONFIG_USER_ONLY +static void loongarch_cpu_reset_cb(void *opaque) +{ + cpu_reset((CPUState *) opaque); +} +#endif + static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -668,6 +675,9 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) qemu_init_vcpu(cs); cpu_reset(cs); +#ifndef CONFIG_USER_ONLY + qemu_register_reset(loongarch_cpu_reset_cb, dev); +#endif lacc->parent_realize(dev, errp); } @@ -678,6 +688,7 @@ static void loongarch_cpu_unrealizefn(DeviceState *dev) #ifndef CONFIG_USER_ONLY cpu_remove_sync(CPU(dev)); + qemu_unregister_reset(loongarch_cpu_reset_cb, dev); #endif lacc->parent_unrealize(dev); base-commit: 91589bcd9fee0e66b241d04e5f37cd4f218187a2 -- 2.39.3