Skip to content

Commit 7b59aa1

Browse files
committed
Merge tag 'pull-loongarch-20250928' of https://github.com/gaosong715/qemu into staging
pull-loongarch-20250928 v2: fix build win64 errors. # -----BEGIN PGP SIGNATURE----- # # iLMEAAEIAB0WIQTKRzxE1qCcGJoZP81FK5aFKyaCFgUCaNkDHQAKCRBFK5aFKyaC # Fn06A/0SQKLVcktq2lX+aRurdGw/LKt/1mtSFJes6s5VVCrNuFFzmkXzjs/m0CcX # scgDF67Z+PhJpLtNLRV8FiJ+z3bOH/j+yRHqj1xnvvITb+i5bUYbt+A81wrzX6Bi # J/Ayqu49oQj33hX3lqTcTBmwYDBc2v7nu0PfvFqOUi9bTvYgfA== # =C4NB # -----END PGP SIGNATURE----- # gpg: Signature made Sun 28 Sep 2025 02:42:53 AM PDT # gpg: using RSA key CA473C44D6A09C189A193FCD452B96852B268216 # gpg: Good signature from "Song Gao <gaosong@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: CA47 3C44 D6A0 9C18 9A19 3FCD 452B 9685 2B26 8216 * tag 'pull-loongarch-20250928' of https://github.com/gaosong715/qemu: hw/loongarch: Implement DINTC plug/unplug interfaces target/loongarch:Implement csrrd CSR_MSGIR register target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts. hw/loongarch: Implement dintc set irq hw/loongarch: Implement dintc realize and unrealize hw/loongarch: DINTC add a MemoryRegion target/loongarch: add msg interrupt CSR registers loongarch: add a direct interrupt controller device hw/loongarch: add misc register support dmsi hw/loongarch: add virt feature dmsi support target/loongarch: move some machine define to virt.h Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2 parents d6dfd8d + 7470657 commit 7b59aa1

File tree

16 files changed

+499
-27
lines changed

16 files changed

+499
-27
lines changed

hw/intc/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,6 @@ config LOONGARCH_PCH_MSI
109109

110110
config LOONGARCH_EXTIOI
111111
bool
112+
113+
config LOONGARCH_DINTC
114+
bool

hw/intc/loongarch_dintc.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* QEMU LoongArch direct interrupt controller.
4+
*
5+
* Copyright (C) 2025 Loongson Technology Corporation Limited
6+
*/
7+
8+
#include "qemu/osdep.h"
9+
#include "hw/sysbus.h"
10+
#include "hw/irq.h"
11+
#include "hw/intc/loongarch_pch_msi.h"
12+
#include "hw/intc/loongarch_pch_pic.h"
13+
#include "hw/intc/loongarch_dintc.h"
14+
#include "hw/pci/msi.h"
15+
#include "hw/misc/unimp.h"
16+
#include "migration/vmstate.h"
17+
#include "trace.h"
18+
#include "hw/qdev-properties.h"
19+
#include "target/loongarch/cpu.h"
20+
#include "qemu/error-report.h"
21+
#include "system/hw_accel.h"
22+
23+
/* msg addr field */
24+
FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
25+
FIELD(MSG_ADDR, CPU_NUM, 12, 8)
26+
FIELD(MSG_ADDR, FIX, 28, 12)
27+
28+
static uint64_t loongarch_dintc_mem_read(void *opaque,
29+
hwaddr addr, unsigned size)
30+
{
31+
return 0;
32+
}
33+
34+
static void do_set_vcpu_dintc_irq(CPUState *cs, run_on_cpu_data data)
35+
{
36+
int irq = data.host_int;
37+
CPULoongArchState *env;
38+
39+
env = &LOONGARCH_CPU(cs)->env;
40+
cpu_synchronize_state(cs);
41+
set_bit(irq, (unsigned long *)&env->CSR_MSGIS);
42+
}
43+
44+
static void loongarch_dintc_mem_write(void *opaque, hwaddr addr,
45+
uint64_t val, unsigned size)
46+
{
47+
int irq_num, cpu_num = 0;
48+
LoongArchDINTCState *s = LOONGARCH_DINTC(opaque);
49+
uint64_t msg_addr = addr + VIRT_DINTC_BASE;
50+
CPUState *cs;
51+
52+
cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
53+
cs = cpu_by_arch_id(cpu_num);
54+
irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
55+
56+
async_run_on_cpu(cs, do_set_vcpu_dintc_irq,
57+
RUN_ON_CPU_HOST_INT(irq_num));
58+
qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
59+
}
60+
61+
static const MemoryRegionOps loongarch_dintc_ops = {
62+
.read = loongarch_dintc_mem_read,
63+
.write = loongarch_dintc_mem_write,
64+
.endianness = DEVICE_LITTLE_ENDIAN,
65+
};
66+
67+
static void loongarch_dintc_realize(DeviceState *dev, Error **errp)
68+
{
69+
LoongArchDINTCState *s = LOONGARCH_DINTC(dev);
70+
LoongArchDINTCClass *lac = LOONGARCH_DINTC_GET_CLASS(dev);
71+
MachineState *machine = MACHINE(qdev_get_machine());
72+
MachineClass *mc = MACHINE_GET_CLASS(machine);
73+
const CPUArchIdList *id_list;
74+
int i;
75+
76+
Error *local_err = NULL;
77+
lac->parent_realize(dev, &local_err);
78+
if (local_err) {
79+
error_propagate(errp, local_err);
80+
return;
81+
}
82+
83+
assert(mc->possible_cpu_arch_ids);
84+
id_list = mc->possible_cpu_arch_ids(machine);
85+
s->num_cpu = id_list->len;
86+
s->cpu = g_new(DINTCCore, s->num_cpu);
87+
if (s->cpu == NULL) {
88+
error_setg(errp, "Memory allocation for DINTCCore fail");
89+
return;
90+
}
91+
92+
for (i = 0; i < s->num_cpu; i++) {
93+
s->cpu[i].arch_id = id_list->cpus[i].arch_id;
94+
s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
95+
qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
96+
}
97+
98+
return;
99+
}
100+
101+
static void loongarch_dintc_unrealize(DeviceState *dev)
102+
{
103+
LoongArchDINTCState *s = LOONGARCH_DINTC(dev);
104+
g_free(s->cpu);
105+
}
106+
107+
static void loongarch_dintc_init(Object *obj)
108+
{
109+
LoongArchDINTCState *s = LOONGARCH_DINTC(obj);
110+
SysBusDevice *shd = SYS_BUS_DEVICE(obj);
111+
memory_region_init_io(&s->dintc_mmio, OBJECT(s), &loongarch_dintc_ops,
112+
s, TYPE_LOONGARCH_DINTC, VIRT_DINTC_SIZE);
113+
sysbus_init_mmio(shd, &s->dintc_mmio);
114+
msi_nonbroken = true;
115+
return;
116+
}
117+
118+
static DINTCCore *loongarch_dintc_get_cpu(LoongArchDINTCState *s,
119+
DeviceState *dev)
120+
{
121+
CPUClass *k = CPU_GET_CLASS(dev);
122+
uint64_t arch_id = k->get_arch_id(CPU(dev));
123+
int i;
124+
125+
for (i = 0; i < s->num_cpu; i++) {
126+
if (s->cpu[i].arch_id == arch_id) {
127+
return &s->cpu[i];
128+
}
129+
}
130+
131+
return NULL;
132+
}
133+
134+
static void loongarch_dintc_cpu_plug(HotplugHandler *hotplug_dev,
135+
DeviceState *dev, Error **errp)
136+
{
137+
LoongArchDINTCState *s = LOONGARCH_DINTC(hotplug_dev);
138+
Object *obj = OBJECT(dev);
139+
DINTCCore *core;
140+
int index;
141+
142+
if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
143+
warn_report("LoongArch DINTC: Invalid %s device type",
144+
object_get_typename(obj));
145+
return;
146+
}
147+
core = loongarch_dintc_get_cpu(s, dev);
148+
if (!core) {
149+
return;
150+
}
151+
152+
core->cpu = CPU(dev);
153+
index = core - s->cpu;
154+
155+
/* connect dintc msg irq to cpu irq */
156+
qdev_connect_gpio_out(DEVICE(s), index, qdev_get_gpio_in(dev, INT_DMSI));
157+
return;
158+
}
159+
160+
static void loongarch_dintc_cpu_unplug(HotplugHandler *hotplug_dev,
161+
DeviceState *dev, Error **errp)
162+
{
163+
LoongArchDINTCState *s = LOONGARCH_DINTC(hotplug_dev);
164+
Object *obj = OBJECT(dev);
165+
DINTCCore *core;
166+
167+
if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
168+
warn_report("LoongArch DINTC: Invalid %s device type",
169+
object_get_typename(obj));
170+
return;
171+
}
172+
173+
core = loongarch_dintc_get_cpu(s, dev);
174+
175+
if (!core) {
176+
return;
177+
}
178+
179+
core->cpu = NULL;
180+
}
181+
182+
static void loongarch_dintc_class_init(ObjectClass *klass, const void *data)
183+
{
184+
DeviceClass *dc = DEVICE_CLASS(klass);
185+
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
186+
LoongArchDINTCClass *lac = LOONGARCH_DINTC_CLASS(klass);
187+
188+
dc->unrealize = loongarch_dintc_unrealize;
189+
device_class_set_parent_realize(dc, loongarch_dintc_realize,
190+
&lac->parent_realize);
191+
hc->plug = loongarch_dintc_cpu_plug;
192+
hc->unplug = loongarch_dintc_cpu_unplug;
193+
}
194+
195+
static const TypeInfo loongarch_dintc_info = {
196+
.name = TYPE_LOONGARCH_DINTC,
197+
.parent = TYPE_SYS_BUS_DEVICE,
198+
.instance_size = sizeof(LoongArchDINTCState),
199+
.instance_init = loongarch_dintc_init,
200+
.class_init = loongarch_dintc_class_init,
201+
.interfaces = (const InterfaceInfo[]) {
202+
{ TYPE_HOTPLUG_HANDLER },
203+
{ }
204+
},
205+
};
206+
207+
static void loongarch_dintc_register_types(void)
208+
{
209+
type_register_static(&loongarch_dintc_info);
210+
}
211+
212+
type_init(loongarch_dintc_register_types)

hw/intc/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_
8080
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c'))
8181
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_EXTIOI'],
8282
if_true: files('loongarch_extioi_kvm.c'))
83+
specific_ss.add(when: 'CONFIG_LOONGARCH_DINTC', if_true: files('loongarch_dintc.c'))

hw/loongarch/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ config LOONGARCH_VIRT
1515
select LOONGARCH_PCH_PIC
1616
select LOONGARCH_PCH_MSI
1717
select LOONGARCH_EXTIOI
18+
select LOONGARCH_DINTC
1819
select LS7A_RTC
1920
select SMBIOS
2021
select ACPI_CPU_HOTPLUG

0 commit comments

Comments
 (0)