* [PATCH 1/5] hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
@ 2024-05-08 13:06 ` Jiaxun Yang
2024-05-08 16:22 ` Philippe Mathieu-Daudé
2024-05-08 13:06 ` [PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi Jiaxun Yang
` (4 subsequent siblings)
5 siblings, 1 reply; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-08 13:06 UTC (permalink / raw)
To: qemu-devel
Cc: Huacai Chen, Philippe Mathieu-Daudé, Song Gao, Jiaxun Yang
Since cpuid will be checked by ipi_getcpu anyway, there is
no point to enforce MAX_CPU here.
This also saved us from including loongarch board header.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
hw/intc/loongarch_ipi.c | 19 ++-----------------
hw/intc/trace-events | 2 --
2 files changed, 2 insertions(+), 19 deletions(-)
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index a184112b0923..44b3b9c138d6 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -6,6 +6,7 @@
*/
#include "qemu/osdep.h"
+#include "hw/boards.h"
#include "hw/sysbus.h"
#include "hw/intc/loongarch_ipi.h"
#include "hw/irq.h"
@@ -13,9 +14,8 @@
#include "qapi/error.h"
#include "qemu/log.h"
#include "exec/address-spaces.h"
-#include "hw/loongarch/virt.h"
#include "migration/vmstate.h"
-#include "target/loongarch/internals.h"
+#include "target/loongarch/cpu.h"
#include "trace.h"
static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
@@ -122,11 +122,6 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
CPUState *cs;
cpuid = extract32(val, 16, 10);
- if (cpuid >= LOONGARCH_MAX_CPUS) {
- trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid);
- return MEMTX_DECODE_ERROR;
- }
-
cs = ipi_getcpu(cpuid);
if (cs == NULL) {
return MEMTX_DECODE_ERROR;
@@ -146,11 +141,6 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
CPUState *cs;
cpuid = extract32(val, 16, 10);
- if (cpuid >= LOONGARCH_MAX_CPUS) {
- trace_loongarch_ipi_unsupported_cpuid("IOCSR_ANY_SEND", cpuid);
- return MEMTX_DECODE_ERROR;
- }
-
cs = ipi_getcpu(cpuid);
if (cs == NULL) {
return MEMTX_DECODE_ERROR;
@@ -201,11 +191,6 @@ static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
break;
case IOCSR_IPI_SEND:
cpuid = extract32(val, 16, 10);
- if (cpuid >= LOONGARCH_MAX_CPUS) {
- trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
- return MEMTX_DECODE_ERROR;
- }
-
/* IPI status vector */
vector = extract8(val, 0, 5);
cs = ipi_getcpu(cpuid);
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 47340b5bc138..a979784f9bee 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -294,8 +294,6 @@ sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
# loongarch_ipi.c
loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
-loongarch_ipi_unsupported_cpuid(const char *s, uint32_t cpuid) "%s unsupported cpuid 0x%" PRIx32
-
# loongarch_pch_pic.c
loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
2024-05-08 13:06 ` [PATCH 1/5] hw/intc/loongarch_ipi: Remove pointless MAX_CPU check Jiaxun Yang
@ 2024-05-08 13:06 ` Jiaxun Yang
2024-05-08 16:24 ` Philippe Mathieu-Daudé
2024-05-08 13:06 ` [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS Jiaxun Yang
` (3 subsequent siblings)
5 siblings, 1 reply; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-08 13:06 UTC (permalink / raw)
To: qemu-devel
Cc: Huacai Chen, Philippe Mathieu-Daudé, Song Gao, Jiaxun Yang
This device will be shared among LoongArch and MIPS
based Loongson machine, rename it as loongson_ipi
to reflect this nature.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
MAINTAINERS | 4 +
hw/intc/Kconfig | 2 +-
hw/intc/loongson_ipi.c | 347 +++++++++++++++++++++
hw/intc/meson.build | 2 +-
hw/intc/trace-events | 6 +-
hw/loongarch/Kconfig | 2 +-
hw/loongarch/virt.c | 4 +-
.../hw/intc/{loongarch_ipi.h => loongson_ipi.h} | 12 +-
include/hw/loongarch/virt.h | 2 +-
9 files changed, 366 insertions(+), 15 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2f08cc528eb6..290dc3227baf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1241,7 +1241,9 @@ F: configs/devices/loongarch64-softmmu/default.mak
F: hw/loongarch/
F: include/hw/loongarch/virt.h
F: include/hw/intc/loongarch_*.h
+F: include/hw/intc/loongson_ipi.h
F: hw/intc/loongarch_*.c
+F: hw/intc/loongson_ipi.c
F: include/hw/pci-host/ls7a.h
F: hw/rtc/ls7a_rtc.c
F: gdb-xml/loongarch*.xml
@@ -1375,10 +1377,12 @@ Loongson-3 virtual platforms
M: Huacai Chen <chenhuacai@kernel.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Maintained
+F: hw/intc/loongson_ipi.c
F: hw/intc/loongson_liointc.c
F: hw/mips/loongson3_bootp.c
F: hw/mips/loongson3_bootp.h
F: hw/mips/loongson3_virt.c
+F: include/hw/intc/loongson_ipi.h
F: include/hw/intc/loongson_liointc.h
F: tests/avocado/machine_mips_loongson3v.py
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index ad59abebaa1d..58b6d3a71003 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -87,7 +87,7 @@ config GOLDFISH_PIC
config M68K_IRQC
bool
-config LOONGARCH_IPI
+config LOONGSON_IPI
bool
config LOONGARCH_PCH_PIC
diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
new file mode 100644
index 000000000000..8c888da3b27c
--- /dev/null
+++ b/hw/intc/loongson_ipi.c
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongson ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+#include "hw/sysbus.h"
+#include "hw/intc/loongson_ipi.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "migration/vmstate.h"
+#include "target/loongarch/cpu.h"
+#include "trace.h"
+
+static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+ uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
+{
+ IPICore *s;
+ LoongsonIPI *ipi = opaque;
+ uint64_t ret = 0;
+ int index = 0;
+
+ s = &ipi->cpu[attrs.requester_id];
+ addr &= 0xff;
+ switch (addr) {
+ case CORE_STATUS_OFF:
+ ret = s->status;
+ break;
+ case CORE_EN_OFF:
+ ret = s->en;
+ break;
+ case CORE_SET_OFF:
+ ret = 0;
+ break;
+ case CORE_CLEAR_OFF:
+ ret = 0;
+ break;
+ case CORE_BUF_20 ... CORE_BUF_38 + 4:
+ index = (addr - CORE_BUF_20) >> 2;
+ ret = s->buf[index];
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
+ break;
+ }
+
+ trace_loongson_ipi_read(size, (uint64_t)addr, ret);
+ *data = ret;
+ return MEMTX_OK;
+}
+
+static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+ MemTxAttrs attrs)
+{
+ int i, mask = 0, data = 0;
+
+ /*
+ * bit 27-30 is mask for byte writing,
+ * if the mask is 0, we need not to do anything.
+ */
+ if ((val >> 27) & 0xf) {
+ data = address_space_ldl(env->address_space_iocsr, addr,
+ attrs, NULL);
+ for (i = 0; i < 4; i++) {
+ /* get mask for byte writing */
+ if (val & (0x1 << (27 + i))) {
+ mask |= 0xff << (i * 8);
+ }
+ }
+ }
+
+ data &= mask;
+ data |= (val >> 32) & ~mask;
+ address_space_stl(env->address_space_iocsr, addr,
+ data, attrs, NULL);
+}
+
+static int archid_cmp(const void *a, const void *b)
+{
+ CPUArchId *archid_a = (CPUArchId *)a;
+ CPUArchId *archid_b = (CPUArchId *)b;
+
+ return archid_a->arch_id - archid_b->arch_id;
+}
+
+static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
+{
+ CPUArchId apic_id, *found_cpu;
+
+ apic_id.arch_id = id;
+ found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus,
+ ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
+ archid_cmp);
+
+ return found_cpu;
+}
+
+static CPUState *ipi_getcpu(int arch_id)
+{
+ MachineState *machine = MACHINE(qdev_get_machine());
+ CPUArchId *archid;
+
+ archid = find_cpu_by_archid(machine, arch_id);
+ if (archid) {
+ return CPU(archid->cpu);
+ }
+
+ return NULL;
+}
+
+static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
+{
+ uint32_t cpuid;
+ hwaddr addr;
+ CPUState *cs;
+
+ cpuid = extract32(val, 16, 10);
+ cs = ipi_getcpu(cpuid);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
+ attrs.requester_id = cs->cpu_index;
+ send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
+ return MEMTX_OK;
+}
+
+static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
+{
+ uint32_t cpuid;
+ hwaddr addr;
+ CPUState *cs;
+
+ cpuid = extract32(val, 16, 10);
+ cs = ipi_getcpu(cpuid);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ addr = val & 0xffff;
+ attrs.requester_id = cs->cpu_index;
+ send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
+ return MEMTX_OK;
+}
+
+static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
+{
+ LoongsonIPI *ipi = opaque;
+ IPICore *s;
+ int index = 0;
+ uint32_t cpuid;
+ uint8_t vector;
+ CPUState *cs;
+
+ s = &ipi->cpu[attrs.requester_id];
+ addr &= 0xff;
+ trace_loongson_ipi_write(size, (uint64_t)addr, val);
+ switch (addr) {
+ case CORE_STATUS_OFF:
+ qemu_log_mask(LOG_GUEST_ERROR, "can not be written");
+ break;
+ case CORE_EN_OFF:
+ s->en = val;
+ break;
+ case CORE_SET_OFF:
+ s->status |= val;
+ if (s->status != 0 && (s->status & s->en) != 0) {
+ qemu_irq_raise(s->irq);
+ }
+ break;
+ case CORE_CLEAR_OFF:
+ s->status &= ~val;
+ if (s->status == 0 && s->en != 0) {
+ qemu_irq_lower(s->irq);
+ }
+ break;
+ case CORE_BUF_20 ... CORE_BUF_38 + 4:
+ index = (addr - CORE_BUF_20) >> 2;
+ s->buf[index] = val;
+ break;
+ case IOCSR_IPI_SEND:
+ cpuid = extract32(val, 16, 10);
+ /* IPI status vector */
+ vector = extract8(val, 0, 5);
+ cs = ipi_getcpu(cpuid);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ attrs.requester_id = cs->cpu_index;
+ loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
+ break;
+ }
+
+ return MEMTX_OK;
+}
+
+static const MemoryRegionOps loongson_ipi_ops = {
+ .read_with_attrs = loongson_ipi_readl,
+ .write_with_attrs = loongson_ipi_writel,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+/* mail send and any send only support writeq */
+static MemTxResult loongson_ipi_writeq(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
+{
+ MemTxResult ret = MEMTX_OK;
+
+ addr &= 0xfff;
+ switch (addr) {
+ case MAIL_SEND_OFFSET:
+ ret = mail_send(val, attrs);
+ break;
+ case ANY_SEND_OFFSET:
+ ret = any_send(val, attrs);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static const MemoryRegionOps loongson_ipi64_ops = {
+ .write_with_attrs = loongson_ipi_writeq,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void loongson_ipi_realize(DeviceState *dev, Error **errp)
+{
+ LoongsonIPI *s = LOONGSON_IPI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ int i;
+
+ if (s->num_cpu == 0) {
+ error_setg(errp, "num-cpu must be at least 1");
+ return;
+ }
+
+ memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongson_ipi_ops,
+ s, "loongson_ipi_iocsr", 0x48);
+
+ /* loongson_ipi_iocsr performs re-entrant IO through ipi_send */
+ s->ipi_iocsr_mem.disable_reentrancy_guard = true;
+
+ sysbus_init_mmio(sbd, &s->ipi_iocsr_mem);
+
+ memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev),
+ &loongson_ipi64_ops,
+ s, "loongson_ipi64_iocsr", 0x118);
+ sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem);
+
+ s->cpu = g_new0(IPICore, s->num_cpu);
+ if (s->cpu == NULL) {
+ error_setg(errp, "Memory allocation for ExtIOICore faile");
+ return;
+ }
+
+ for (i = 0; i < s->num_cpu; i++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].irq, 1);
+ }
+}
+
+static const VMStateDescription vmstate_ipi_core = {
+ .name = "ipi-single",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32(status, IPICore),
+ VMSTATE_UINT32(en, IPICore),
+ VMSTATE_UINT32(set, IPICore),
+ VMSTATE_UINT32(clear, IPICore),
+ VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_loongson_ipi = {
+ .name = TYPE_LOONGSON_IPI,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongsonIPI, num_cpu,
+ vmstate_ipi_core, IPICore),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property ipi_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", LoongsonIPI, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void loongson_ipi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = loongson_ipi_realize;
+ device_class_set_props(dc, ipi_properties);
+ dc->vmsd = &vmstate_loongson_ipi;
+}
+
+static void loongson_ipi_finalize(Object *obj)
+{
+ LoongsonIPI *s = LOONGSON_IPI(obj);
+
+ g_free(s->cpu);
+}
+
+static const TypeInfo loongson_ipi_info = {
+ .name = TYPE_LOONGSON_IPI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LoongsonIPI),
+ .class_init = loongson_ipi_class_init,
+ .instance_finalize = loongson_ipi_finalize,
+};
+
+static void loongson_ipi_register_types(void)
+{
+ type_register_static(&loongson_ipi_info);
+}
+
+type_init(loongson_ipi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 58140da5f293..f4b540e6a8b7 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -68,7 +68,7 @@ specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c'))
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
if_true: files('spapr_xive_kvm.c'))
specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
-specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
+specific_ss.add(when: 'CONFIG_LOONGSON_IPI', if_true: files('loongson_ipi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index a979784f9bee..b815cea129e2 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -291,9 +291,9 @@ sh_intc_read(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PR
sh_intc_write(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " <- 0x%lx"
sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
-# loongarch_ipi.c
-loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
-loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
+# loongson_ipi.c
+loongson_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
+loongson_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
# loongarch_pch_pic.c
loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 5727efed6d84..ccbcde5e55e5 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -8,7 +8,7 @@ config LOONGARCH_VIRT
select SERIAL
select VIRTIO_PCI
select PLATFORM_BUS
- select LOONGARCH_IPI
+ select LOONGSON_IPI
select LOONGARCH_PCH_PIC
select LOONGARCH_PCH_MSI
select LOONGARCH_EXTIOI
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c0999878df6a..517929cb1438 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -21,7 +21,7 @@
#include "net/net.h"
#include "hw/loader.h"
#include "elf.h"
-#include "hw/intc/loongarch_ipi.h"
+#include "hw/intc/loongson_ipi.h"
#include "hw/intc/loongarch_extioi.h"
#include "hw/intc/loongarch_pch_pic.h"
#include "hw/intc/loongarch_pch_msi.h"
@@ -697,7 +697,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
*/
/* Create IPI device */
- ipi = qdev_new(TYPE_LOONGARCH_IPI);
+ ipi = qdev_new(TYPE_LOONGSON_IPI);
qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus);
sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongson_ipi.h
similarity index 84%
rename from include/hw/intc/loongarch_ipi.h
rename to include/hw/intc/loongson_ipi.h
index 1c1e834849e0..2c0e8820f5ec 100644
--- a/include/hw/intc/loongarch_ipi.h
+++ b/include/hw/intc/loongson_ipi.h
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * LoongArch ipi interrupt header files
+ * Loongson ipi interrupt header files
*
* Copyright (C) 2021 Loongson Technology Corporation Limited
*/
-#ifndef HW_LOONGARCH_IPI_H
-#define HW_LOONGARCH_IPI_H
+#ifndef HW_LOONGSON_IPI_H
+#define HW_LOONGSON_IPI_H
#include "hw/sysbus.h"
@@ -30,8 +30,8 @@
#define IPI_MBX_NUM 4
-#define TYPE_LOONGARCH_IPI "loongarch_ipi"
-OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
+#define TYPE_LOONGSON_IPI "loongson_ipi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongsonIPI, LOONGSON_IPI)
typedef struct IPICore {
uint32_t status;
@@ -43,7 +43,7 @@ typedef struct IPICore {
qemu_irq irq;
} IPICore;
-struct LoongArchIPI {
+struct LoongsonIPI {
SysBusDevice parent_obj;
MemoryRegion ipi_iocsr_mem;
MemoryRegion ipi64_iocsr_mem;
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 4e14bf6060d0..e1a440a751c8 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -11,7 +11,7 @@
#include "target/loongarch/cpu.h"
#include "hw/boards.h"
#include "qemu/queue.h"
-#include "hw/intc/loongarch_ipi.h"
+#include "hw/intc/loongson_ipi.h"
#include "hw/block/flash.h"
#include "hw/loongarch/boot.h"
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi
2024-05-08 13:06 ` [PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi Jiaxun Yang
@ 2024-05-08 16:24 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-08 16:24 UTC (permalink / raw)
To: Jiaxun Yang, qemu-devel; +Cc: Huacai Chen, Song Gao
On 8/5/24 15:06, Jiaxun Yang wrote:
> This device will be shared among LoongArch and MIPS
> based Loongson machine, rename it as loongson_ipi
> to reflect this nature.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> MAINTAINERS | 4 +
> hw/intc/Kconfig | 2 +-
> hw/intc/loongson_ipi.c | 347 +++++++++++++++++++++
> hw/intc/meson.build | 2 +-
> hw/intc/trace-events | 6 +-
> hw/loongarch/Kconfig | 2 +-
> hw/loongarch/virt.c | 4 +-
> .../hw/intc/{loongarch_ipi.h => loongson_ipi.h} | 12 +-
> include/hw/loongarch/virt.h | 2 +-
> 9 files changed, 366 insertions(+), 15 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
2024-05-08 13:06 ` [PATCH 1/5] hw/intc/loongarch_ipi: Remove pointless MAX_CPU check Jiaxun Yang
2024-05-08 13:06 ` [PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi Jiaxun Yang
@ 2024-05-08 13:06 ` Jiaxun Yang
2024-05-08 16:21 ` Philippe Mathieu-Daudé
2024-06-03 15:45 ` Philippe Mathieu-Daudé
2024-05-08 13:06 ` [PATCH 4/5] hw/intc/loongson_ipi: Provide per core MMIO address spaces Jiaxun Yang
` (2 subsequent siblings)
5 siblings, 2 replies; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-08 13:06 UTC (permalink / raw)
To: qemu-devel
Cc: Huacai Chen, Philippe Mathieu-Daudé, Song Gao, Jiaxun Yang
Implement IOCSR address space get functions for MIPS/Loongson CPUs.
For MIPS/Loongson without IOCSR (i.e. Loongson-3A1000), get_cpu_iocsr_as
will return as null, and send_ipi_data will fail with MEMTX_DECODE_ERROR,
which matches expected behavior on hardware.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
I understand that there was a review comment stating that I shouldn't
use TARGET_* macros in device drivers. But I still think this is the
best way to handle architectural difference. There are many TARGET_*
usages in hw/virtio for similiar purpose.
---
hw/intc/loongson_ipi.c | 39 ++++++++++++++++++++++++++++++---------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 8c888da3b27c..93cc50a37a11 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -15,7 +15,12 @@
#include "qemu/log.h"
#include "exec/address-spaces.h"
#include "migration/vmstate.h"
+#ifdef TARGET_LOONGARCH64
#include "target/loongarch/cpu.h"
+#endif
+#ifdef TARGET_MIPS
+#include "target/mips/cpu.h"
+#endif
#include "trace.h"
static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
@@ -56,18 +61,35 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
return MEMTX_OK;
}
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
+{
+#ifdef TARGET_LOONGARCH64
+ return LOONGARCH_CPU(cpu)->env.address_space_iocsr;
+#endif
+#ifdef TARGET_MIPS
+ if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) {
+ return &MIPS_CPU(cpu)->env.iocsr.as;
+ }
+#endif
+ return NULL;
+}
+
+static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr,
MemTxAttrs attrs)
{
int i, mask = 0, data = 0;
+ AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu);
+
+ if (!iocsr_as) {
+ return MEMTX_DECODE_ERROR;
+ }
/*
* bit 27-30 is mask for byte writing,
* if the mask is 0, we need not to do anything.
*/
if ((val >> 27) & 0xf) {
- data = address_space_ldl(env->address_space_iocsr, addr,
- attrs, NULL);
+ data = address_space_ldl(iocsr_as, addr, attrs, NULL);
for (i = 0; i < 4; i++) {
/* get mask for byte writing */
if (val & (0x1 << (27 + i))) {
@@ -78,8 +100,9 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
data &= mask;
data |= (val >> 32) & ~mask;
- address_space_stl(env->address_space_iocsr, addr,
- data, attrs, NULL);
+ address_space_stl(iocsr_as, addr, data, attrs, NULL);
+
+ return MEMTX_OK;
}
static int archid_cmp(const void *a, const void *b)
@@ -130,8 +153,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
/* override requester_id */
addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
attrs.requester_id = cs->cpu_index;
- send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
- return MEMTX_OK;
+ return send_ipi_data(cs, val, addr, attrs);
}
static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
@@ -149,8 +171,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
/* override requester_id */
addr = val & 0xffff;
attrs.requester_id = cs->cpu_index;
- send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
- return MEMTX_OK;
+ return send_ipi_data(cs, val, addr, attrs);
}
static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
2024-05-08 13:06 ` [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS Jiaxun Yang
@ 2024-05-08 16:21 ` Philippe Mathieu-Daudé
2024-06-03 15:45 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-08 16:21 UTC (permalink / raw)
To: Jiaxun Yang, qemu-devel; +Cc: Huacai Chen, Song Gao
On 8/5/24 15:06, Jiaxun Yang wrote:
> Implement IOCSR address space get functions for MIPS/Loongson CPUs.
>
> For MIPS/Loongson without IOCSR (i.e. Loongson-3A1000), get_cpu_iocsr_as
> will return as null, and send_ipi_data will fail with MEMTX_DECODE_ERROR,
> which matches expected behavior on hardware.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> I understand that there was a review comment stating that I shouldn't
> use TARGET_* macros in device drivers. But I still think this is the
> best way to handle architectural difference. There are many TARGET_*
> usages in hw/virtio for similiar purpose.
> ---
> hw/intc/loongson_ipi.c | 39 ++++++++++++++++++++++++++++++---------
> 1 file changed, 30 insertions(+), 9 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
2024-05-08 13:06 ` [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS Jiaxun Yang
2024-05-08 16:21 ` Philippe Mathieu-Daudé
@ 2024-06-03 15:45 ` Philippe Mathieu-Daudé
2024-06-04 10:35 ` Jiaxun Yang
1 sibling, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-03 15:45 UTC (permalink / raw)
To: Jiaxun Yang, qemu-devel; +Cc: Huacai Chen, Song Gao
On 8/5/24 15:06, Jiaxun Yang wrote:
> Implement IOCSR address space get functions for MIPS/Loongson CPUs.
>
> For MIPS/Loongson without IOCSR (i.e. Loongson-3A1000), get_cpu_iocsr_as
> will return as null, and send_ipi_data will fail with MEMTX_DECODE_ERROR,
> which matches expected behavior on hardware.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> I understand that there was a review comment stating that I shouldn't
> use TARGET_* macros in device drivers. But I still think this is the
> best way to handle architectural difference. There are many TARGET_*
> usages in hw/virtio for similiar purpose.
> ---
> hw/intc/loongson_ipi.c | 39 ++++++++++++++++++++++++++++++---------
> 1 file changed, 30 insertions(+), 9 deletions(-)
> static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
> @@ -56,18 +61,35 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
> return MEMTX_OK;
> }
>
> -static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
> +static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
> +{
> +#ifdef TARGET_LOONGARCH64
> + return LOONGARCH_CPU(cpu)->env.address_space_iocsr;
> +#endif
> +#ifdef TARGET_MIPS
> + if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) {
> + return &MIPS_CPU(cpu)->env.iocsr.as;
> + }
> +#endif
> + return NULL;
> +}
> +
> +static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr,
> MemTxAttrs attrs)
> {
> int i, mask = 0, data = 0;
> + AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu);
LoongsonIPI should have an array of CPUState[] and MemoryRegion[].
(Or maybe add them to IPICore.)
Expose them as QOM link properties.
Caller wire them while creating the LoongsonIPI.
Then loongson_ipi_realize() resolves them once.
No need to call get_cpu_iocsr_as() and ipi_getcpu() for each MMIO
access IMO.
> +
> + if (!iocsr_as) {
> + return MEMTX_DECODE_ERROR;
> + }
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
2024-06-03 15:45 ` Philippe Mathieu-Daudé
@ 2024-06-04 10:35 ` Jiaxun Yang
2024-06-04 12:37 ` gaosong
0 siblings, 1 reply; 18+ messages in thread
From: Jiaxun Yang @ 2024-06-04 10:35 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, QEMU devel, Song Gao; +Cc: Huacai Chen
在2024年6月3日六月 下午4:45,Philippe Mathieu-Daudé写道:
[...]
>
> LoongsonIPI should have an array of CPUState[] and MemoryRegion[].
> (Or maybe add them to IPICore.)
> Expose them as QOM link properties.
>
> Caller wire them while creating the LoongsonIPI.
> Then loongson_ipi_realize() resolves them once.
> No need to call get_cpu_iocsr_as() and ipi_getcpu() for each MMIO
> access IMO.
I was tempted to do so but realized that arch_id might be discontinuous
for LoongArch.
@Song, can you confirm if it's viable?
Thanks
- Jiaxun
>
>> +
>> + if (!iocsr_as) {
>> + return MEMTX_DECODE_ERROR;
>> + }
--
- Jiaxun
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
2024-06-04 10:35 ` Jiaxun Yang
@ 2024-06-04 12:37 ` gaosong
0 siblings, 0 replies; 18+ messages in thread
From: gaosong @ 2024-06-04 12:37 UTC (permalink / raw)
To: Jiaxun Yang, Philippe Mathieu-Daudé, QEMU devel
Cc: Huacai Chen, bibo mao
在 2024/6/4 下午6:35, Jiaxun Yang 写道:
>
> 在2024年6月3日六月 下午4:45,Philippe Mathieu-Daudé写道:
> [...]
>> LoongsonIPI should have an array of CPUState[] and MemoryRegion[].
>> (Or maybe add them to IPICore.)
>> Expose them as QOM link properties.
>>
>> Caller wire them while creating the LoongsonIPI.
>> Then loongson_ipi_realize() resolves them once.
>> No need to call get_cpu_iocsr_as() and ipi_getcpu() for each MMIO
>> access IMO.
> I was tempted to do so but realized that arch_id might be discontinuous
> for LoongArch.
>
> @Song, can you confirm if it's viable?
I confirmed from Bibo that the arch_id may not be continuous in the future.
Thanks.
Song Gao
> Thanks
> - Jiaxun
>>> +
>>> + if (!iocsr_as) {
>>> + return MEMTX_DECODE_ERROR;
>>> + }
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/5] hw/intc/loongson_ipi: Provide per core MMIO address spaces
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
` (2 preceding siblings ...)
2024-05-08 13:06 ` [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS Jiaxun Yang
@ 2024-05-08 13:06 ` Jiaxun Yang
2024-05-08 13:06 ` [PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device Jiaxun Yang
2024-05-08 21:41 ` [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Philippe Mathieu-Daudé
5 siblings, 0 replies; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-08 13:06 UTC (permalink / raw)
To: qemu-devel
Cc: Huacai Chen, Philippe Mathieu-Daudé, Song Gao, Jiaxun Yang
The real IPI hardware have dedicated MMIO registers mapped into
memory address space for every core. This is not used by LoongArch
guest software but it is essential for CPU without IOCSR such as
Loongson-3A1000.
Implement it with existing infrastructure.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
hw/intc/loongson_ipi.c | 81 ++++++++++++++++++++++++++++++++----------
include/hw/intc/loongson_ipi.h | 2 ++
2 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 93cc50a37a11..c8a25b4eb8e2 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -23,16 +23,14 @@
#endif
#include "trace.h"
-static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr,
uint64_t *data,
unsigned size, MemTxAttrs attrs)
{
- IPICore *s;
- LoongsonIPI *ipi = opaque;
+ IPICore *s = opaque;
uint64_t ret = 0;
int index = 0;
- s = &ipi->cpu[attrs.requester_id];
addr &= 0xff;
switch (addr) {
case CORE_STATUS_OFF:
@@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
return MEMTX_OK;
}
+static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr,
+ uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
+{
+ LoongsonIPI *ipi = opaque;
+ IPICore *s;
+
+ if (attrs.requester_id >= ipi->num_cpu) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ s = &ipi->cpu[attrs.requester_id];
+ return loongson_ipi_core_readl(s, addr, data, size, attrs);
+}
+
static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
{
#ifdef TARGET_LOONGARCH64
@@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
return send_ipi_data(cs, val, addr, attrs);
}
-static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
- unsigned size, MemTxAttrs attrs)
+static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
{
- LoongsonIPI *ipi = opaque;
- IPICore *s;
+ IPICore *s = opaque;
+ LoongsonIPI *ipi = s->ipi;
int index = 0;
uint32_t cpuid;
uint8_t vector;
CPUState *cs;
- s = &ipi->cpu[attrs.requester_id];
addr &= 0xff;
trace_loongson_ipi_write(size, (uint64_t)addr, val);
switch (addr) {
@@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
/* IPI status vector */
vector = extract8(val, 0, 5);
cs = ipi_getcpu(cpuid);
- if (cs == NULL) {
+ if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
return MEMTX_DECODE_ERROR;
}
-
- /* override requester_id */
- attrs.requester_id = cs->cpu_index;
- loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
+ loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF,
+ BIT(vector), 4, attrs);
break;
default:
qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
@@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
return MEMTX_OK;
}
-static const MemoryRegionOps loongson_ipi_ops = {
- .read_with_attrs = loongson_ipi_readl,
- .write_with_attrs = loongson_ipi_writel,
+static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
+{
+ LoongsonIPI *ipi = opaque;
+ IPICore *s;
+
+ if (attrs.requester_id >= ipi->num_cpu) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ s = &ipi->cpu[attrs.requester_id];
+ return loongson_ipi_core_writel(s, addr, val, size, attrs);
+}
+
+static const MemoryRegionOps loongson_ipi_core_ops = {
+ .read_with_attrs = loongson_ipi_core_readl,
+ .write_with_attrs = loongson_ipi_core_writel,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static const MemoryRegionOps loongson_ipi_iocsr_ops = {
+ .read_with_attrs = loongson_ipi_iocsr_readl,
+ .write_with_attrs = loongson_ipi_iocsr_writel,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.valid.min_access_size = 4,
@@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp)
return;
}
- memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongson_ipi_ops,
+ memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongson_ipi_iocsr_ops,
s, "loongson_ipi_iocsr", 0x48);
/* loongson_ipi_iocsr performs re-entrant IO through ipi_send */
@@ -297,11 +333,18 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp)
s->cpu = g_new0(IPICore, s->num_cpu);
if (s->cpu == NULL) {
- error_setg(errp, "Memory allocation for ExtIOICore faile");
+ error_setg(errp, "Memory allocation for IPICore faile");
return;
}
for (i = 0; i < s->num_cpu; i++) {
+ s->cpu[i].ipi = s;
+ s->cpu[i].ipi_mmio_mem = g_new0(MemoryRegion, 1);
+ g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i);
+ memory_region_init_io(s->cpu[i].ipi_mmio_mem, OBJECT(dev),
+ &loongson_ipi_core_ops, &s->cpu[i], name, 0x48);
+ sysbus_init_mmio(sbd, s->cpu[i].ipi_mmio_mem);
+
qdev_init_gpio_out(dev, &s->cpu[i].irq, 1);
}
}
diff --git a/include/hw/intc/loongson_ipi.h b/include/hw/intc/loongson_ipi.h
index 2c0e8820f5ec..3f795edbf3cd 100644
--- a/include/hw/intc/loongson_ipi.h
+++ b/include/hw/intc/loongson_ipi.h
@@ -34,6 +34,8 @@
OBJECT_DECLARE_SIMPLE_TYPE(LoongsonIPI, LOONGSON_IPI)
typedef struct IPICore {
+ LoongsonIPI *ipi;
+ MemoryRegion *ipi_mmio_mem;
uint32_t status;
uint32_t en;
uint32_t set;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
` (3 preceding siblings ...)
2024-05-08 13:06 ` [PATCH 4/5] hw/intc/loongson_ipi: Provide per core MMIO address spaces Jiaxun Yang
@ 2024-05-08 13:06 ` Jiaxun Yang
2024-06-03 15:46 ` Philippe Mathieu-Daudé
2024-05-08 21:41 ` [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Philippe Mathieu-Daudé
5 siblings, 1 reply; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-08 13:06 UTC (permalink / raw)
To: qemu-devel
Cc: Huacai Chen, Philippe Mathieu-Daudé, Song Gao, Jiaxun Yang
Wire up loongson_ipi device for loongson3_virt machine, so we
can have SMP support for TCG backend as well.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
hw/mips/Kconfig | 1 +
hw/mips/loongson3_bootp.c | 2 --
hw/mips/loongson3_bootp.h | 3 +++
hw/mips/loongson3_virt.c | 39 +++++++++++++++++++++++++++++++++++++--
4 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 5c83ef49cf6f..6f09fedc946e 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -57,6 +57,7 @@ config LOONGSON3V
imply USB_OHCI_PCI
select SERIAL
select GOLDFISH_RTC
+ select LOONGSON_IPI
select LOONGSON_LIOINTC
select PCI_EXPRESS_GENERIC_BRIDGE
select MSI_NONBROKEN
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index f99af229327a..474d3556b2e5 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -25,8 +25,6 @@
#include "hw/boards.h"
#include "hw/mips/loongson3_bootp.h"
-#define LOONGSON3_CORE_PER_NODE 4
-
static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
{
struct efi_cpuinfo_loongson *c = g_cpuinfo;
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..9091265df7fc 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -200,6 +200,8 @@ struct boot_params {
struct efi_reset_system_t reset_system;
};
+#define LOONGSON3_CORE_PER_NODE 4
+
/* Overall MMIO & Memory layout */
enum {
VIRT_LOWMEM,
@@ -211,6 +213,7 @@ enum {
VIRT_BIOS_ROM,
VIRT_UART,
VIRT_LIOINTC,
+ VIRT_IPI,
VIRT_PCIE_MMIO,
VIRT_HIGHMEM
};
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index b10a611a98f4..1052fb7d6747 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -36,6 +36,7 @@
#include "hw/mips/loongson3_bootp.h"
#include "hw/misc/unimp.h"
#include "hw/intc/i8259.h"
+#include "hw/intc/loongson_ipi.h"
#include "hw/loader.h"
#include "hw/isa/superio.h"
#include "hw/pci/msi.h"
@@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = {
[VIRT_PCIE_ECAM] = { 0x1a000000, 0x2000000 },
[VIRT_BIOS_ROM] = { 0x1fc00000, 0x200000 },
[VIRT_UART] = { 0x1fe001e0, 0x8 },
+ [VIRT_IPI] = { 0x3ff01000, 0x400 },
[VIRT_LIOINTC] = { 0x3ff01400, 0x64 },
[VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
[VIRT_HIGHMEM] = { 0x80000000, 0x0 }, /* Variable */
@@ -466,6 +468,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
Clock *cpuclk;
CPUMIPSState *env;
DeviceState *liointc;
+ DeviceState *ipi = NULL;
char *filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *kernel_filename = machine->kernel_filename;
@@ -475,6 +478,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
MemoryRegion *iomem = g_new(MemoryRegion, 1);
+ MemoryRegion *iocsr = g_new(MemoryRegion, 1);
/* TODO: TCG will support all CPU types */
if (!kvm_enabled()) {
@@ -508,6 +512,19 @@ static void mips_loongson3_virt_init(MachineState *machine)
create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB);
create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB);
+ memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX);
+
+ /* IPI controller is in kernel for KVM */
+ if (!kvm_enabled()) {
+ ipi = qdev_new(TYPE_LOONGSON_IPI);
+ qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+ memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+ memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+ }
+
liointc = qdev_new("loongson.liointc");
sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal);
@@ -524,6 +541,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
for (i = 0; i < machine->smp.cpus; i++) {
+ int node = i / LOONGSON3_CORE_PER_NODE;
+ int core = i % LOONGSON3_CORE_PER_NODE;
int ip;
/* init CPUs */
@@ -534,12 +553,28 @@ static void mips_loongson3_virt_init(MachineState *machine)
cpu_mips_clock_init(cpu);
qemu_register_reset(main_cpu_reset, cpu);
- if (i >= 4) {
+ if (ipi) {
+ hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
+ base += core * 0x100;
+ qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
+ sysbus_mmio_map(SYS_BUS_DEVICE(ipi), i + 2, base);
+ }
+
+ if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) {
+ MemoryRegion *core_iocsr = g_new(MemoryRegion, 1);
+ g_autofree char *name = g_strdup_printf("loongson3.core%d_iocsr", i);
+ memory_region_init_alias(core_iocsr, OBJECT(machine), name,
+ iocsr, 0, UINT32_MAX);
+ memory_region_add_subregion(&MIPS_CPU(cpu)->env.iocsr.mr,
+ 0, core_iocsr);
+ }
+
+ if (node > 0) {
continue; /* Only node-0 can be connected to LIOINTC */
}
for (ip = 0; ip < 4 ; ip++) {
- int pin = i * 4 + ip;
+ int pin = core * LOONGSON3_CORE_PER_NODE + ip;
sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
pin, cpu->env.irq[ip + 2]);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device
2024-05-08 13:06 ` [PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device Jiaxun Yang
@ 2024-06-03 15:46 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-03 15:46 UTC (permalink / raw)
To: Jiaxun Yang, qemu-devel; +Cc: Huacai Chen, Song Gao
On 8/5/24 15:06, Jiaxun Yang wrote:
> Wire up loongson_ipi device for loongson3_virt machine, so we
> can have SMP support for TCG backend as well.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> hw/mips/Kconfig | 1 +
> hw/mips/loongson3_bootp.c | 2 --
> hw/mips/loongson3_bootp.h | 3 +++
> hw/mips/loongson3_virt.c | 39 +++++++++++++++++++++++++++++++++++++--
> 4 files changed, 41 insertions(+), 4 deletions(-)
> @@ -534,12 +553,28 @@ static void mips_loongson3_virt_init(MachineState *machine)
> cpu_mips_clock_init(cpu);
> qemu_register_reset(main_cpu_reset, cpu);
>
> - if (i >= 4) {
> + if (ipi) {
> + hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
> + base += core * 0x100;
> + qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
> + sysbus_mmio_map(SYS_BUS_DEVICE(ipi), i + 2, base);
> + }
> +
> + if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) {
> + MemoryRegion *core_iocsr = g_new(MemoryRegion, 1);
> + g_autofree char *name = g_strdup_printf("loongson3.core%d_iocsr", i);
> + memory_region_init_alias(core_iocsr, OBJECT(machine), name,
Region owner should be vCPU (core) IMO, not machine. But maybe need
another approach (see my comment on patch #3), although not sure if
easy with KVM.
> + iocsr, 0, UINT32_MAX);
> + memory_region_add_subregion(&MIPS_CPU(cpu)->env.iocsr.mr,
> + 0, core_iocsr);
> + }
> +
> + if (node > 0) {
> continue; /* Only node-0 can be connected to LIOINTC */
> }
>
> for (ip = 0; ip < 4 ; ip++) {
> - int pin = i * 4 + ip;
> + int pin = core * LOONGSON3_CORE_PER_NODE + ip;
> sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
> pin, cpu->env.irq[ip + 2]);
> }
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
2024-05-08 13:06 [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Jiaxun Yang
` (4 preceding siblings ...)
2024-05-08 13:06 ` [PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device Jiaxun Yang
@ 2024-05-08 21:41 ` Philippe Mathieu-Daudé
2024-05-16 10:53 ` Jiaxun Yang
5 siblings, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-08 21:41 UTC (permalink / raw)
To: Jiaxun Yang, qemu-devel; +Cc: Huacai Chen, Song Gao
On 8/5/24 15:06, Jiaxun Yang wrote:
> Hi all,
>
> This series enabled IPI support for loongson3 virt board, loosely
> based on my previous work[1].
> It generalized loongarch_ipi device to share among both loongarch
> and MIPS machines.
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> Jiaxun Yang (5):
> hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
> hw/intc/loongarch_ipi: Rename as loongson_ipi
> hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
So far patches 1-3 queued to hw-misc tree, thanks.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
2024-05-08 21:41 ` [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support Philippe Mathieu-Daudé
@ 2024-05-16 10:53 ` Jiaxun Yang
2024-06-03 15:35 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 18+ messages in thread
From: Jiaxun Yang @ 2024-05-16 10:53 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, QEMU devel; +Cc: Huacai Chen, Song Gao
在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道:
> On 8/5/24 15:06, Jiaxun Yang wrote:
>> Hi all,
>>
>> This series enabled IPI support for loongson3 virt board, loosely
>> based on my previous work[1].
>> It generalized loongarch_ipi device to share among both loongarch
>> and MIPS machines.
>
>
>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>> ---
>> Jiaxun Yang (5):
>> hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
>> hw/intc/loongarch_ipi: Rename as loongson_ipi
>> hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
>
> So far patches 1-3 queued to hw-misc tree, thanks.
Hi Philippe,
Thanks! What's your plan with the rest of the series and earlier MIPS
CPS SMP series?
Let me know if you need help on testing etc.
Thanks
--
- Jiaxun
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
2024-05-16 10:53 ` Jiaxun Yang
@ 2024-06-03 15:35 ` Philippe Mathieu-Daudé
2024-06-04 12:55 ` gaosong
0 siblings, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-03 15:35 UTC (permalink / raw)
To: Jiaxun Yang, QEMU devel; +Cc: Huacai Chen, Song Gao
On 16/5/24 12:53, Jiaxun Yang wrote:
>
>
> 在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道:
>> On 8/5/24 15:06, Jiaxun Yang wrote:
>>> Hi all,
>>>
>>> This series enabled IPI support for loongson3 virt board, loosely
>>> based on my previous work[1].
>>> It generalized loongarch_ipi device to share among both loongarch
>>> and MIPS machines.
>>
>>
>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> ---
>>> Jiaxun Yang (5):
>>> hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
>>> hw/intc/loongarch_ipi: Rename as loongson_ipi
>>> hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
>>
>> So far patches 1-3 queued to hw-misc tree, thanks.
>
> Hi Philippe,
>
> Thanks! What's your plan with the rest of the series
Patches LGTM, but I'd like an Acked-by from Song Gao ;)
> and earlier MIPS CPS SMP series?
No plan, just lack of time :/
> Let me know if you need help on testing etc.
>
> Thanks
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
2024-06-03 15:35 ` Philippe Mathieu-Daudé
@ 2024-06-04 12:55 ` gaosong
2024-06-04 14:24 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 18+ messages in thread
From: gaosong @ 2024-06-04 12:55 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, Jiaxun Yang, QEMU devel; +Cc: Huacai Chen
在 2024/6/3 下午11:35, Philippe Mathieu-Daudé 写道:
> On 16/5/24 12:53, Jiaxun Yang wrote:
>>
>>
>> 在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道:
>>> On 8/5/24 15:06, Jiaxun Yang wrote:
>>>> Hi all,
>>>>
>>>> This series enabled IPI support for loongson3 virt board, loosely
>>>> based on my previous work[1].
>>>> It generalized loongarch_ipi device to share among both loongarch
>>>> and MIPS machines.
>>>
>>>
>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>> ---
>>>> Jiaxun Yang (5):
>>>> hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
>>>> hw/intc/loongarch_ipi: Rename as loongson_ipi
>>>> hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
>>>
>>> So far patches 1-3 queued to hw-misc tree, thanks.
>>
>> Hi Philippe,
>>
>> Thanks! What's your plan with the rest of the series
>
> Patches LGTM, but I'd like an Acked-by from Song Gao ;)
>
Patch 1 - 4:
Acked-by: Song Gao <gaosong@loongson.cn>
and patch2 missed to delete the file loongarch_ipi.c.
Thanks.
Song Gao
>> and earlier MIPS CPS SMP series?
>
> No plan, just lack of time :/
>
>> Let me know if you need help on testing etc.
>>
>> Thanks
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
2024-06-04 12:55 ` gaosong
@ 2024-06-04 14:24 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-06-04 14:24 UTC (permalink / raw)
To: gaosong, Jiaxun Yang, QEMU devel; +Cc: Huacai Chen
On 4/6/24 14:55, gaosong wrote:
> 在 2024/6/3 下午11:35, Philippe Mathieu-Daudé 写道:
>> On 16/5/24 12:53, Jiaxun Yang wrote:
>>> 在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道:
>>>> On 8/5/24 15:06, Jiaxun Yang wrote:
>>>>> Hi all,
>>>>>
>>>>> This series enabled IPI support for loongson3 virt board, loosely
>>>>> based on my previous work[1].
>>>>> It generalized loongarch_ipi device to share among both loongarch
>>>>> and MIPS machines.
>>>>
>>>>
>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> ---
>>>>> Jiaxun Yang (5):
>>>>> hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
>>>>> hw/intc/loongarch_ipi: Rename as loongson_ipi
>>>>> hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
>>>>
>>>> So far patches 1-3 queued to hw-misc tree, thanks.
>>>
>>> Hi Philippe,
>>>
>>> Thanks! What's your plan with the rest of the series
>>
>> Patches LGTM, but I'd like an Acked-by from Song Gao ;)
>>
> Patch 1 - 4:
> Acked-by: Song Gao <gaosong@loongson.cn>
Thanks!
> and patch2 missed to delete the file loongarch_ipi.c.
Jiaxun, I can not apply this series anymore, could you respin?
Regards,
Phil.
^ permalink raw reply [flat|nested] 18+ messages in thread