aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-03-05 21:57:15 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2025-03-05 21:57:15 +0800
commitcf2f8cf3b7b2d4eadb4023eb18f4ae45b294fe82 (patch)
treea0f53429519942f2cbfa55e52f4fcde7d0d7c1af /hw/intc
parent9ee727802012ddb32e193d84052a44e382088277 (diff)
parent0a629c827300d514cc1f61806414d214fcf75051 (diff)
downloadqemu-cf2f8cf3b7b2d4eadb4023eb18f4ae45b294fe82.zip
qemu-cf2f8cf3b7b2d4eadb4023eb18f4ae45b294fe82.tar.gz
qemu-cf2f8cf3b7b2d4eadb4023eb18f4ae45b294fe82.tar.bz2
Merge tag 'pull-loongarch-20250305' of https://gitlab.com/bibo-mao/qemu into staging
loongarch queue # -----BEGIN PGP SIGNATURE----- # # iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ8ezJgAKCRAfewwSUazn # 0T9pAQCKb+C69kbf9cEVg7PU/z5I0ALFtCNWCKxSkWZPDPik4gEA3IYwdrJ+csuX # 8nWL0fzyk+8+LDzEwEgCYoNcMnttRQw= # =P8mi # -----END PGP SIGNATURE----- # gpg: Signature made Wed 05 Mar 2025 10:12:54 HKT # gpg: using EDDSA key 0D8642A3A2659F80B0B3D1A41F7B0C1251ACE7D1 # gpg: Good signature from "bibo mao <maobibo@loongson.cn>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 7044 3A00 19C0 E97A 31C7 13C4 8E86 8FB7 A176 9D4C # Subkey fingerprint: 0D86 42A3 A265 9F80 B0B3 D1A4 1F7B 0C12 51AC E7D1 * tag 'pull-loongarch-20250305' of https://gitlab.com/bibo-mao/qemu: target/loongarch: Adjust the cpu reset action to a proper position hw/loongarch/virt: Enable cpu hotplug feature on virt machine hw/loongarch/virt: Update the ACPI table for hotplug cpu hw/loongarch/virt: Implement cpu plug interface hw/loongarch/virt: Implement cpu unplug interface hw/loongarch/virt: Add basic cpu plug interface framework hw/loongarch/virt: Add topo properties on CPU object hw/loongarch/virt: Add CPU topology support hw/intc/loongarch_extioi: Use cpu plug notification hw/intc/loongarch_extioi: Implment cpu hotplug interface hw/intc/loongarch_extioi: Add basic hotplug framework hw/intc/loongarch_extioi: Move gpio irq initial to common code hw/intc/loongarch_ipi: Notify ipi object when cpu is plugged hw/intc/loongarch_ipi: Implment cpu hotplug interface hw/intc/loongarch_ipi: Add basic hotplug framework Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/loongarch_extioi.c8
-rw-r--r--hw/intc/loongarch_extioi_common.c84
-rw-r--r--hw/intc/loongarch_ipi.c71
3 files changed, 155 insertions, 8 deletions
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index f3055ec..a51a215 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -343,7 +343,7 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_GET_CLASS(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
Error *local_err = NULL;
- int i, pin;
+ int i;
lec->parent_realize(dev, &local_err);
if (local_err) {
@@ -368,12 +368,6 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
} else {
s->status |= BIT(EXTIOI_ENABLE);
}
-
- for (i = 0; i < s->num_cpu; i++) {
- for (pin = 0; pin < LS3A_INTC_IP; pin++) {
- qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1);
- }
- }
}
static void loongarch_extioi_unrealize(DeviceState *dev)
diff --git a/hw/intc/loongarch_extioi_common.c b/hw/intc/loongarch_extioi_common.c
index fd56253..ff3974f 100644
--- a/hw/intc/loongarch_extioi_common.c
+++ b/hw/intc/loongarch_extioi_common.c
@@ -4,11 +4,82 @@
* Copyright (C) 2024 Loongson Technology Corporation Limited
*/
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qapi/error.h"
#include "hw/qdev-properties.h"
#include "hw/intc/loongarch_extioi_common.h"
#include "migration/vmstate.h"
+#include "target/loongarch/cpu.h"
+
+static ExtIOICore *loongarch_extioi_get_cpu(LoongArchExtIOICommonState *s,
+ DeviceState *dev)
+{
+ CPUClass *k = CPU_GET_CLASS(dev);
+ uint64_t arch_id = k->get_arch_id(CPU(dev));
+ int i;
+
+ for (i = 0; i < s->num_cpu; i++) {
+ if (s->cpu[i].arch_id == arch_id) {
+ return &s->cpu[i];
+ }
+ }
+
+ return NULL;
+}
+
+static void loongarch_extioi_cpu_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ ExtIOICore *core;
+ int pin, index;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch extioi: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+
+ core = loongarch_extioi_get_cpu(s, dev);
+ if (!core) {
+ return;
+ }
+
+ core->cpu = CPU(dev);
+ index = core - s->cpu;
+
+ /*
+ * connect extioi irq to the cpu irq
+ * cpu_pin[LS3A_INTC_IP + 2 : 2] <= intc_pin[LS3A_INTC_IP : 0]
+ */
+ for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+ qdev_connect_gpio_out(DEVICE(s), index * LS3A_INTC_IP + pin,
+ qdev_get_gpio_in(dev, pin + 2));
+ }
+}
+
+static void loongarch_extioi_cpu_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ ExtIOICore *core;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch extioi: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+
+ core = loongarch_extioi_get_cpu(s, dev);
+ if (!core) {
+ return;
+ }
+
+ core->cpu = NULL;
+}
static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp)
{
@@ -16,7 +87,7 @@ static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp)
MachineState *machine = MACHINE(qdev_get_machine());
MachineClass *mc = MACHINE_GET_CLASS(machine);
const CPUArchIdList *id_list;
- int i;
+ int i, pin;
assert(mc->possible_cpu_arch_ids);
id_list = mc->possible_cpu_arch_ids(machine);
@@ -30,6 +101,10 @@ static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_cpu; i++) {
s->cpu[i].arch_id = id_list->cpus[i].arch_id;
s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
+
+ for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1);
+ }
}
}
@@ -103,11 +178,14 @@ static void loongarch_extioi_common_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
device_class_set_parent_realize(dc, loongarch_extioi_common_realize,
&lecc->parent_realize);
device_class_set_props(dc, extioi_properties);
dc->vmsd = &vmstate_loongarch_extioi;
+ hc->plug = loongarch_extioi_cpu_plug;
+ hc->unplug = loongarch_extioi_cpu_unplug;
}
static const TypeInfo loongarch_extioi_common_types[] = {
@@ -117,6 +195,10 @@ static const TypeInfo loongarch_extioi_common_types[] = {
.instance_size = sizeof(LoongArchExtIOICommonState),
.class_size = sizeof(LoongArchExtIOICommonClass),
.class_init = loongarch_extioi_common_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ },
.abstract = true,
}
};
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 5376f1e..b10641d 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -6,6 +6,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
#include "hw/boards.h"
#include "qapi/error.h"
#include "hw/intc/loongarch_ipi.h"
@@ -48,6 +49,22 @@ static int loongarch_cpu_by_arch_id(LoongsonIPICommonState *lics,
return MEMTX_ERROR;
}
+static IPICore *loongarch_ipi_get_cpu(LoongsonIPICommonState *lics,
+ DeviceState *dev)
+{
+ CPUClass *k = CPU_GET_CLASS(dev);
+ uint64_t arch_id = k->get_arch_id(CPU(dev));
+ int i;
+
+ for (i = 0; i < lics->num_cpu; i++) {
+ if (lics->cpu[i].arch_id == arch_id) {
+ return &lics->cpu[i];
+ }
+ }
+
+ return NULL;
+}
+
static void loongarch_ipi_realize(DeviceState *dev, Error **errp)
{
LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(dev);
@@ -76,9 +93,57 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp)
}
}
+static void loongarch_ipi_cpu_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ IPICore *core;
+ int index;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch extioi: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+
+ core = loongarch_ipi_get_cpu(lics, dev);
+ if (!core) {
+ return;
+ }
+
+ core->cpu = CPU(dev);
+ index = core - lics->cpu;
+
+ /* connect ipi irq to cpu irq */
+ qdev_connect_gpio_out(DEVICE(lics), index, qdev_get_gpio_in(dev, IRQ_IPI));
+}
+
+static void loongarch_ipi_cpu_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ IPICore *core;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch extioi: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+
+ core = loongarch_ipi_get_cpu(lics, dev);
+ if (!core) {
+ return;
+ }
+
+ core->cpu = NULL;
+}
+
static void loongarch_ipi_class_init(ObjectClass *klass, void *data)
{
LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -86,6 +151,8 @@ static void loongarch_ipi_class_init(ObjectClass *klass, void *data)
&lic->parent_realize);
licc->get_iocsr_as = get_iocsr_as;
licc->cpu_by_arch_id = loongarch_cpu_by_arch_id;
+ hc->plug = loongarch_ipi_cpu_plug;
+ hc->unplug = loongarch_ipi_cpu_unplug;
}
static const TypeInfo loongarch_ipi_types[] = {
@@ -95,6 +162,10 @@ static const TypeInfo loongarch_ipi_types[] = {
.instance_size = sizeof(LoongarchIPIState),
.class_size = sizeof(LoongarchIPIClass),
.class_init = loongarch_ipi_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ },
}
};