hw/arm/boot: Add manually register and trigger of CPU reset

We need to register and trigger CPU reset manually for hotplugged
CPU. Besides, we gather CPU reset handlers of all CPUs because CPU
reset should happen before GIC reset.

Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
(cherry picked from commit e38ab50a87d6f581d282e606ac12db5e8238c1e1)
This commit is contained in:
Chen Qun 2020-04-09 09:31:22 +08:00 committed by yezengruan
parent 714d5e6ecc
commit c78f79898b

View File

@ -0,0 +1,116 @@
From 9dc22ff87eb61a8b2bcc5892961ec432986893c9 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Thu, 9 Apr 2020 09:31:22 +0800
Subject: [PATCH] hw/arm/boot: Add manually register and trigger of CPU reset
We need to register and trigger CPU reset manually for hotplugged
CPU. Besides, we gather CPU reset handlers of all CPUs because CPU
reset should happen before GIC reset.
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
hw/arm/boot.c | 18 ++++++++++++++++++
hw/core/reset.c | 25 +++++++++++++++++++++++++
include/hw/arm/boot.h | 3 +++
include/sysemu/reset.h | 4 ++++
4 files changed, 50 insertions(+)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 21024f7999..3d45de1772 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -814,6 +814,24 @@ static void do_cpu_reset(void *opaque)
}
}
+void cpu_hotplug_register_reset(int ncpu)
+{
+ CPUState *cpu_0 = qemu_get_cpu(0);
+ CPUState *cpu = qemu_get_cpu(ncpu);
+ QEMUResetEntry *entry = qemu_get_reset_entry(do_cpu_reset, cpu_0);
+
+ assert(entry);
+ /* Gather the reset handlers of all CPUs */
+ qemu_register_reset_after(entry, do_cpu_reset, cpu);
+}
+
+void cpu_hotplug_reset_manually(int ncpu)
+{
+ CPUState *cpu = qemu_get_cpu(ncpu);
+
+ do_cpu_reset(cpu);
+}
+
/**
* load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
* by key.
diff --git a/hw/core/reset.c b/hw/core/reset.c
index e923723d38..314d332111 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -48,6 +48,31 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
}
+QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func,
+ void *opaque)
+{
+ QEMUResetEntry *re;
+
+ QTAILQ_FOREACH(re, &reset_handlers, entry) {
+ if (re->func == func && re->opaque == opaque) {
+ return re;
+ }
+ }
+
+ return NULL;
+}
+
+void qemu_register_reset_after(QEMUResetEntry *entry,
+ QEMUResetHandler *func,
+ void *opaque)
+{
+ QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
+
+ re->func = func;
+ re->opaque = opaque;
+ QTAILQ_INSERT_AFTER(&reset_handlers, entry, re, entry);
+}
+
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
{
QEMUResetEntry *re;
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
index ce2b48b88b..c3c4d3ea79 100644
--- a/include/hw/arm/boot.h
+++ b/include/hw/arm/boot.h
@@ -119,6 +119,9 @@ struct arm_boot_info {
arm_endianness endianness;
};
+void cpu_hotplug_register_reset(int ncpu);
+void cpu_hotplug_reset_manually(int ncpu);
+
/**
* arm_load_kernel - Loads memory with everything needed to boot
*
diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h
index 0b0d6d7598..f3ff26c637 100644
--- a/include/sysemu/reset.h
+++ b/include/sysemu/reset.h
@@ -2,7 +2,11 @@
#define QEMU_SYSEMU_RESET_H
typedef void QEMUResetHandler(void *opaque);
+typedef struct QEMUResetEntry QEMUResetEntry;
+QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, void *opaque);
+void qemu_register_reset_after(QEMUResetEntry *entry,
+ QEMUResetHandler *func, void *opaque);
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
void qemu_devices_reset(void);
--
2.27.0