Skip to content

Commit e765115

Browse files
committed
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-gsoc-queue-jun-27-2020' into staging
MIPS + TCG Continuous Benchmarking queue for June 27th, 2020 # gpg: Signature made Sat 27 Jun 2020 20:30:48 BST # gpg: using RSA key D4972A8967F75A65 # gpg: Good signature from "Aleksandar Markovic <[email protected]>" [full] # Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01 DD75 D497 2A89 67F7 5A65 * remotes/amarkovic/tags/mips-gsoc-queue-jun-27-2020: MAINTAINERS: Add 'Performance Tools and Tests' subsection scripts/performance: Add topN_callgrind.py script scripts/performance: Add topN_perf.py script MAINTAINERS: Add Loongson-3 maintainer and reviewer hw/intc: Add Loongson LIOINTC support hw/mips: Implement the kvm_type() hook in MachineClass Signed-off-by: Peter Maydell <[email protected]>
2 parents 553cf5d + 53fb8bf commit e765115

File tree

8 files changed

+585
-0
lines changed

8 files changed

+585
-0
lines changed

MAINTAINERS

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,12 @@ F: hw/isa/vt82c686.c
10961096
F: hw/pci-host/bonito.c
10971097
F: include/hw/isa/vt82c686.h
10981098

1099+
Loongson-3 virtual platforms
1100+
M: Huacai Chen <[email protected]>
1101+
R: Jiaxun Yang <[email protected]>
1102+
S: Maintained
1103+
F: hw/intc/loongson_liointc.c
1104+
10991105
Boston
11001106
M: Paul Burton <[email protected]>
11011107
R: Aleksandar Rikalo <[email protected]>
@@ -3019,3 +3025,10 @@ M: Peter Maydell <[email protected]>
30193025
S: Maintained
30203026
F: docs/conf.py
30213027
F: docs/*/conf.py
3028+
3029+
Miscellaneous
3030+
-------------
3031+
Performance Tools and Tests
3032+
M: Ahmed Karaman <[email protected]>
3033+
S: Maintained
3034+
F: scripts/performance/

hw/intc/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,6 @@ config OMPIC
6464

6565
config RX_ICU
6666
bool
67+
68+
config LOONGSON_LIOINTC
69+
bool

hw/intc/Makefile.objs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ obj-$(CONFIG_MIPS_CPS) += mips_gic.o
5151
obj-$(CONFIG_NIOS2) += nios2_iic.o
5252
obj-$(CONFIG_OMPIC) += ompic.o
5353
obj-$(CONFIG_IBEX) += ibex_plic.o
54+
obj-$(CONFIG_LOONGSON_LIOINTC) += loongson_liointc.o

hw/intc/loongson_liointc.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
* QEMU Loongson Local I/O interrupt controler.
3+
*
4+
* Copyright (c) 2020 Jiaxun Yang <[email protected]>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*
19+
*/
20+
21+
#include "qemu/osdep.h"
22+
#include "hw/sysbus.h"
23+
#include "qemu/module.h"
24+
#include "hw/irq.h"
25+
#include "hw/qdev-properties.h"
26+
27+
#define D(x)
28+
29+
#define NUM_IRQS 32
30+
31+
#define NUM_CORES 4
32+
#define NUM_IPS 4
33+
#define NUM_PARENTS (NUM_CORES * NUM_IPS)
34+
#define PARENT_COREx_IPy(x, y) (NUM_IPS * x + y)
35+
36+
#define R_MAPPER_START 0x0
37+
#define R_MAPPER_END 0x20
38+
#define R_ISR R_MAPPER_END
39+
#define R_IEN 0x24
40+
#define R_IEN_SET 0x28
41+
#define R_IEN_CLR 0x2c
42+
#define R_PERCORE_ISR(x) (0x40 + 0x8 * x)
43+
#define R_END 0x64
44+
45+
#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
46+
#define LOONGSON_LIOINTC(obj) \
47+
OBJECT_CHECK(struct loongson_liointc, (obj), TYPE_LOONGSON_LIOINTC)
48+
49+
struct loongson_liointc {
50+
SysBusDevice parent_obj;
51+
52+
MemoryRegion mmio;
53+
qemu_irq parent_irq[NUM_PARENTS];
54+
55+
uint8_t mapper[NUM_IRQS]; /* 0:3 for core, 4:7 for IP */
56+
uint32_t isr;
57+
uint32_t ien;
58+
uint32_t per_core_isr[NUM_CORES];
59+
60+
/* state of the interrupt input pins */
61+
uint32_t pin_state;
62+
bool parent_state[NUM_PARENTS];
63+
};
64+
65+
static void update_irq(struct loongson_liointc *p)
66+
{
67+
uint32_t irq, core, ip;
68+
uint32_t per_ip_isr[NUM_IPS] = {0};
69+
70+
/* level triggered interrupt */
71+
p->isr = p->pin_state;
72+
73+
/* Clear disabled IRQs */
74+
p->isr &= p->ien;
75+
76+
/* Clear per_core_isr */
77+
for (core = 0; core < NUM_CORES; core++) {
78+
p->per_core_isr[core] = 0;
79+
}
80+
81+
/* Update per_core_isr and per_ip_isr */
82+
for (irq = 0; irq < NUM_IRQS; irq++) {
83+
if (!(p->isr & (1 << irq))) {
84+
continue;
85+
}
86+
87+
for (core = 0; core < NUM_CORES; core++) {
88+
if ((p->mapper[irq] & (1 << core))) {
89+
p->per_core_isr[core] |= (1 << irq);
90+
}
91+
}
92+
93+
for (ip = 0; ip < NUM_IPS; ip++) {
94+
if ((p->mapper[irq] & (1 << (ip + 4)))) {
95+
per_ip_isr[ip] |= (1 << irq);
96+
}
97+
}
98+
}
99+
100+
/* Emit IRQ to parent! */
101+
for (core = 0; core < NUM_CORES; core++) {
102+
for (ip = 0; ip < NUM_IPS; ip++) {
103+
int parent = PARENT_COREx_IPy(core, ip);
104+
if (p->parent_state[parent] !=
105+
(!!p->per_core_isr[core] && !!per_ip_isr[ip])) {
106+
p->parent_state[parent] = !p->parent_state[parent];
107+
qemu_set_irq(p->parent_irq[parent], p->parent_state[parent]);
108+
}
109+
}
110+
}
111+
}
112+
113+
static uint64_t
114+
liointc_read(void *opaque, hwaddr addr, unsigned int size)
115+
{
116+
struct loongson_liointc *p = opaque;
117+
uint32_t r = 0;
118+
119+
/* Mapper is 1 byte */
120+
if (size == 1 && addr < R_MAPPER_END) {
121+
r = p->mapper[addr];
122+
goto out;
123+
}
124+
125+
/* Rest is 4 byte */
126+
if (size != 4 || (addr % 4)) {
127+
goto out;
128+
}
129+
130+
if (addr >= R_PERCORE_ISR(0) &&
131+
addr < R_PERCORE_ISR(NUM_CORES)) {
132+
int core = (addr - R_PERCORE_ISR(0)) / 4;
133+
r = p->per_core_isr[core];
134+
goto out;
135+
}
136+
137+
switch (addr) {
138+
case R_ISR:
139+
r = p->isr;
140+
break;
141+
case R_IEN:
142+
r = p->ien;
143+
break;
144+
default:
145+
break;
146+
}
147+
148+
out:
149+
D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
150+
return r;
151+
}
152+
153+
static void
154+
liointc_write(void *opaque, hwaddr addr,
155+
uint64_t val64, unsigned int size)
156+
{
157+
struct loongson_liointc *p = opaque;
158+
uint32_t value = val64;
159+
160+
D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
161+
162+
/* Mapper is 1 byte */
163+
if (size == 1 && addr < R_MAPPER_END) {
164+
p->mapper[addr] = value;
165+
goto out;
166+
}
167+
168+
/* Rest is 4 byte */
169+
if (size != 4 || (addr % 4)) {
170+
goto out;
171+
}
172+
173+
if (addr >= R_PERCORE_ISR(0) &&
174+
addr < R_PERCORE_ISR(NUM_CORES)) {
175+
int core = (addr - R_PERCORE_ISR(0)) / 4;
176+
p->per_core_isr[core] = value;
177+
goto out;
178+
}
179+
180+
switch (addr) {
181+
case R_IEN_SET:
182+
p->ien |= value;
183+
break;
184+
case R_IEN_CLR:
185+
p->ien &= ~value;
186+
break;
187+
default:
188+
break;
189+
}
190+
191+
out:
192+
update_irq(p);
193+
}
194+
195+
static const MemoryRegionOps pic_ops = {
196+
.read = liointc_read,
197+
.write = liointc_write,
198+
.endianness = DEVICE_NATIVE_ENDIAN,
199+
.valid = {
200+
.min_access_size = 1,
201+
.max_access_size = 4
202+
}
203+
};
204+
205+
static void irq_handler(void *opaque, int irq, int level)
206+
{
207+
struct loongson_liointc *p = opaque;
208+
209+
p->pin_state &= ~(1 << irq);
210+
p->pin_state |= level << irq;
211+
update_irq(p);
212+
}
213+
214+
static void loongson_liointc_init(Object *obj)
215+
{
216+
struct loongson_liointc *p = LOONGSON_LIOINTC(obj);
217+
int i;
218+
219+
qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
220+
221+
for (i = 0; i < NUM_PARENTS; i++) {
222+
sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq[i]);
223+
}
224+
225+
memory_region_init_io(&p->mmio, obj, &pic_ops, p,
226+
"loongson.liointc", R_END);
227+
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
228+
}
229+
230+
static const TypeInfo loongson_liointc_info = {
231+
.name = TYPE_LOONGSON_LIOINTC,
232+
.parent = TYPE_SYS_BUS_DEVICE,
233+
.instance_size = sizeof(struct loongson_liointc),
234+
.instance_init = loongson_liointc_init,
235+
};
236+
237+
static void loongson_liointc_register_types(void)
238+
{
239+
type_register_static(&loongson_liointc_info);
240+
}
241+
242+
type_init(loongson_liointc_register_types)

0 commit comments

Comments
 (0)