1 /*
2 * RISC-V APLIC (Advanced Platform Level Interrupt Controller)
3 *
4 * Copyright (c) 2021 Western Digital Corporation or its affiliates.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "qemu/osdep.h"
20 #include "qapi/error.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
23 #include "qemu/error-report.h"
24 #include "qemu/bswap.h"
25 #include "exec/address-spaces.h"
26 #include "hw/sysbus.h"
27 #include "hw/pci/msi.h"
28 #include "hw/boards.h"
29 #include "hw/qdev-properties.h"
30 #include "hw/intc/riscv_aplic.h"
31 #include "hw/irq.h"
32 #include "target/riscv/cpu.h"
33 #include "sysemu/sysemu.h"
34 #include "sysemu/kvm.h"
35 #include "kvm/kvm_riscv.h"
36 #include "migration/vmstate.h"
37
38 #define APLIC_MAX_IDC (1UL << 14)
39 #define APLIC_MAX_SOURCE 1024
40 #define APLIC_MIN_IPRIO_BITS 1
41 #define APLIC_MAX_IPRIO_BITS 8
42 #define APLIC_MAX_CHILDREN 1024
43
44 #define APLIC_DOMAINCFG 0x0000
45 #define APLIC_DOMAINCFG_RDONLY 0x80000000
46 #define APLIC_DOMAINCFG_IE (1 << 8)
47 #define APLIC_DOMAINCFG_DM (1 << 2)
48 #define APLIC_DOMAINCFG_BE (1 << 0)
49
50 #define APLIC_SOURCECFG_BASE 0x0004
51 #define APLIC_SOURCECFG_D (1 << 10)
52 #define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff
53 #define APLIC_SOURCECFG_SM_MASK 0x00000007
54 #define APLIC_SOURCECFG_SM_INACTIVE 0x0
55 #define APLIC_SOURCECFG_SM_DETACH 0x1
56 #define APLIC_SOURCECFG_SM_EDGE_RISE 0x4
57 #define APLIC_SOURCECFG_SM_EDGE_FALL 0x5
58 #define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6
59 #define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7
60
61 #define APLIC_MMSICFGADDR 0x1bc0
62 #define APLIC_MMSICFGADDRH 0x1bc4
63 #define APLIC_SMSICFGADDR 0x1bc8
64 #define APLIC_SMSICFGADDRH 0x1bcc
65
66 #define APLIC_xMSICFGADDRH_L (1UL << 31)
67 #define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f
68 #define APLIC_xMSICFGADDRH_HHXS_SHIFT 24
69 #define APLIC_xMSICFGADDRH_LHXS_MASK 0x7
70 #define APLIC_xMSICFGADDRH_LHXS_SHIFT 20
71 #define APLIC_xMSICFGADDRH_HHXW_MASK 0x7
72 #define APLIC_xMSICFGADDRH_HHXW_SHIFT 16
73 #define APLIC_xMSICFGADDRH_LHXW_MASK 0xf
74 #define APLIC_xMSICFGADDRH_LHXW_SHIFT 12
75 #define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff
76
77 #define APLIC_xMSICFGADDR_PPN_SHIFT 12
78
79 #define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \
80 ((1UL << (__lhxs)) - 1)
81
82 #define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \
83 ((1UL << (__lhxw)) - 1)
84 #define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \
85 ((__lhxs))
86 #define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \
87 (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << \
88 APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs))
89
90 #define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \
91 ((1UL << (__hhxw)) - 1)
92 #define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \
93 ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT)
94 #define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \
95 (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
96 APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
97
98 #define APLIC_xMSICFGADDRH_VALID_MASK \
99 (APLIC_xMSICFGADDRH_L | \
100 (APLIC_xMSICFGADDRH_HHXS_MASK << APLIC_xMSICFGADDRH_HHXS_SHIFT) | \
101 (APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \
102 (APLIC_xMSICFGADDRH_HHXW_MASK << APLIC_xMSICFGADDRH_HHXW_SHIFT) | \
103 (APLIC_xMSICFGADDRH_LHXW_MASK << APLIC_xMSICFGADDRH_LHXW_SHIFT) | \
104 APLIC_xMSICFGADDRH_BAPPN_MASK)
105
106 #define APLIC_SETIP_BASE 0x1c00
107 #define APLIC_SETIPNUM 0x1cdc
108
109 #define APLIC_CLRIP_BASE 0x1d00
110 #define APLIC_CLRIPNUM 0x1ddc
111
112 #define APLIC_SETIE_BASE 0x1e00
113 #define APLIC_SETIENUM 0x1edc
114
115 #define APLIC_CLRIE_BASE 0x1f00
116 #define APLIC_CLRIENUM 0x1fdc
117
118 #define APLIC_SETIPNUM_LE 0x2000
119 #define APLIC_SETIPNUM_BE 0x2004
120
121 #define APLIC_ISTATE_PENDING (1U << 0)
122 #define APLIC_ISTATE_ENABLED (1U << 1)
123 #define APLIC_ISTATE_ENPEND (APLIC_ISTATE_ENABLED | \
124 APLIC_ISTATE_PENDING)
125 #define APLIC_ISTATE_INPUT (1U << 8)
126
127 #define APLIC_GENMSI 0x3000
128
129 #define APLIC_TARGET_BASE 0x3004
130 #define APLIC_TARGET_HART_IDX_SHIFT 18
131 #define APLIC_TARGET_HART_IDX_MASK 0x3fff
132 #define APLIC_TARGET_GUEST_IDX_SHIFT 12
133 #define APLIC_TARGET_GUEST_IDX_MASK 0x3f
134 #define APLIC_TARGET_IPRIO_MASK 0xff
135 #define APLIC_TARGET_EIID_MASK 0x7ff
136
137 #define APLIC_IDC_BASE 0x4000
138 #define APLIC_IDC_SIZE 32
139
140 #define APLIC_IDC_IDELIVERY 0x00
141
142 #define APLIC_IDC_IFORCE 0x04
143
144 #define APLIC_IDC_ITHRESHOLD 0x08
145
146 #define APLIC_IDC_TOPI 0x18
147 #define APLIC_IDC_TOPI_ID_SHIFT 16
148 #define APLIC_IDC_TOPI_ID_MASK 0x3ff
149 #define APLIC_IDC_TOPI_PRIO_MASK 0xff
150
151 #define APLIC_IDC_CLAIMI 0x1c
152
153 /*
154 * KVM AIA only supports APLIC MSI, fallback to QEMU emulation if we want to use
155 * APLIC Wired.
156 */
is_kvm_aia(bool msimode)157 static bool is_kvm_aia(bool msimode)
158 {
159 return kvm_irqchip_in_kernel() && msimode;
160 }
161
riscv_aplic_irq_rectified_val(RISCVAPLICState * aplic,uint32_t irq)162 static bool riscv_aplic_irq_rectified_val(RISCVAPLICState *aplic,
163 uint32_t irq)
164 {
165 uint32_t sourcecfg, sm, raw_input, irq_inverted;
166
167 if (!irq || aplic->num_irqs <= irq) {
168 return false;
169 }
170
171 sourcecfg = aplic->sourcecfg[irq];
172 if (sourcecfg & APLIC_SOURCECFG_D) {
173 return false;
174 }
175
176 sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
177 if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
178 return false;
179 }
180
181 raw_input = (aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0;
182 irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
183 sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
184
185 return !!(raw_input ^ irq_inverted);
186 }
187
riscv_aplic_read_input_word(RISCVAPLICState * aplic,uint32_t word)188 static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
189 uint32_t word)
190 {
191 uint32_t i, irq, rectified_val, ret = 0;
192
193 for (i = 0; i < 32; i++) {
194 irq = word * 32 + i;
195
196 rectified_val = riscv_aplic_irq_rectified_val(aplic, irq);
197 ret |= rectified_val << i;
198 }
199
200 return ret;
201 }
202
riscv_aplic_read_pending_word(RISCVAPLICState * aplic,uint32_t word)203 static uint32_t riscv_aplic_read_pending_word(RISCVAPLICState *aplic,
204 uint32_t word)
205 {
206 uint32_t i, irq, ret = 0;
207
208 for (i = 0; i < 32; i++) {
209 irq = word * 32 + i;
210 if (!irq || aplic->num_irqs <= irq) {
211 continue;
212 }
213
214 ret |= ((aplic->state[irq] & APLIC_ISTATE_PENDING) ? 1 : 0) << i;
215 }
216
217 return ret;
218 }
219
riscv_aplic_set_pending_raw(RISCVAPLICState * aplic,uint32_t irq,bool pending)220 static void riscv_aplic_set_pending_raw(RISCVAPLICState *aplic,
221 uint32_t irq, bool pending)
222 {
223 if (pending) {
224 aplic->state[irq] |= APLIC_ISTATE_PENDING;
225 } else {
226 aplic->state[irq] &= ~APLIC_ISTATE_PENDING;
227 }
228 }
229
riscv_aplic_set_pending(RISCVAPLICState * aplic,uint32_t irq,bool pending)230 static void riscv_aplic_set_pending(RISCVAPLICState *aplic,
231 uint32_t irq, bool pending)
232 {
233 uint32_t sourcecfg, sm;
234
235 if ((irq <= 0) || (aplic->num_irqs <= irq)) {
236 return;
237 }
238
239 sourcecfg = aplic->sourcecfg[irq];
240 if (sourcecfg & APLIC_SOURCECFG_D) {
241 return;
242 }
243
244 sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
245 if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
246 return;
247 }
248
249 if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
250 (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
251 if (!aplic->msimode || (aplic->msimode && !pending)) {
252 return;
253 }
254 if ((aplic->state[irq] & APLIC_ISTATE_INPUT) &&
255 (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
256 return;
257 }
258 if (!(aplic->state[irq] & APLIC_ISTATE_INPUT) &&
259 (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH)) {
260 return;
261 }
262 }
263
264 riscv_aplic_set_pending_raw(aplic, irq, pending);
265 }
266
riscv_aplic_set_pending_word(RISCVAPLICState * aplic,uint32_t word,uint32_t value,bool pending)267 static void riscv_aplic_set_pending_word(RISCVAPLICState *aplic,
268 uint32_t word, uint32_t value,
269 bool pending)
270 {
271 uint32_t i, irq;
272
273 for (i = 0; i < 32; i++) {
274 irq = word * 32 + i;
275 if (!irq || aplic->num_irqs <= irq) {
276 continue;
277 }
278
279 if (value & (1U << i)) {
280 riscv_aplic_set_pending(aplic, irq, pending);
281 }
282 }
283 }
284
riscv_aplic_read_enabled_word(RISCVAPLICState * aplic,int word)285 static uint32_t riscv_aplic_read_enabled_word(RISCVAPLICState *aplic,
286 int word)
287 {
288 uint32_t i, irq, ret = 0;
289
290 for (i = 0; i < 32; i++) {
291 irq = word * 32 + i;
292 if (!irq || aplic->num_irqs <= irq) {
293 continue;
294 }
295
296 ret |= ((aplic->state[irq] & APLIC_ISTATE_ENABLED) ? 1 : 0) << i;
297 }
298
299 return ret;
300 }
301
riscv_aplic_set_enabled_raw(RISCVAPLICState * aplic,uint32_t irq,bool enabled)302 static void riscv_aplic_set_enabled_raw(RISCVAPLICState *aplic,
303 uint32_t irq, bool enabled)
304 {
305 if (enabled) {
306 aplic->state[irq] |= APLIC_ISTATE_ENABLED;
307 } else {
308 aplic->state[irq] &= ~APLIC_ISTATE_ENABLED;
309 }
310 }
311
riscv_aplic_set_enabled(RISCVAPLICState * aplic,uint32_t irq,bool enabled)312 static void riscv_aplic_set_enabled(RISCVAPLICState *aplic,
313 uint32_t irq, bool enabled)
314 {
315 uint32_t sourcecfg, sm;
316
317 if ((irq <= 0) || (aplic->num_irqs <= irq)) {
318 return;
319 }
320
321 sourcecfg = aplic->sourcecfg[irq];
322 if (sourcecfg & APLIC_SOURCECFG_D) {
323 return;
324 }
325
326 sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
327 if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
328 return;
329 }
330
331 riscv_aplic_set_enabled_raw(aplic, irq, enabled);
332 }
333
riscv_aplic_set_enabled_word(RISCVAPLICState * aplic,uint32_t word,uint32_t value,bool enabled)334 static void riscv_aplic_set_enabled_word(RISCVAPLICState *aplic,
335 uint32_t word, uint32_t value,
336 bool enabled)
337 {
338 uint32_t i, irq;
339
340 for (i = 0; i < 32; i++) {
341 irq = word * 32 + i;
342 if (!irq || aplic->num_irqs <= irq) {
343 continue;
344 }
345
346 if (value & (1U << i)) {
347 riscv_aplic_set_enabled(aplic, irq, enabled);
348 }
349 }
350 }
351
riscv_aplic_msi_send(RISCVAPLICState * aplic,uint32_t hart_idx,uint32_t guest_idx,uint32_t eiid)352 static void riscv_aplic_msi_send(RISCVAPLICState *aplic,
353 uint32_t hart_idx, uint32_t guest_idx,
354 uint32_t eiid)
355 {
356 uint64_t addr;
357 MemTxResult result;
358 RISCVAPLICState *aplic_m;
359 uint32_t lhxs, lhxw, hhxs, hhxw, group_idx, msicfgaddr, msicfgaddrH;
360
361 aplic_m = aplic;
362 while (aplic_m && !aplic_m->mmode) {
363 aplic_m = aplic_m->parent;
364 }
365 if (!aplic_m) {
366 qemu_log_mask(LOG_GUEST_ERROR, "%s: m-level APLIC not found\n",
367 __func__);
368 return;
369 }
370
371 if (aplic->mmode) {
372 msicfgaddr = aplic_m->mmsicfgaddr;
373 msicfgaddrH = aplic_m->mmsicfgaddrH;
374 } else {
375 msicfgaddr = aplic_m->smsicfgaddr;
376 msicfgaddrH = aplic_m->smsicfgaddrH;
377 }
378
379 lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) &
380 APLIC_xMSICFGADDRH_LHXS_MASK;
381 lhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXW_SHIFT) &
382 APLIC_xMSICFGADDRH_LHXW_MASK;
383 hhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXS_SHIFT) &
384 APLIC_xMSICFGADDRH_HHXS_MASK;
385 hhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXW_SHIFT) &
386 APLIC_xMSICFGADDRH_HHXW_MASK;
387
388 group_idx = hart_idx >> lhxw;
389 hart_idx &= APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw);
390
391 addr = msicfgaddr;
392 addr |= ((uint64_t)(msicfgaddrH & APLIC_xMSICFGADDRH_BAPPN_MASK)) << 32;
393 addr |= ((uint64_t)(group_idx & APLIC_xMSICFGADDR_PPN_HHX_MASK(hhxw))) <<
394 APLIC_xMSICFGADDR_PPN_HHX_SHIFT(hhxs);
395 addr |= ((uint64_t)(hart_idx & APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw))) <<
396 APLIC_xMSICFGADDR_PPN_LHX_SHIFT(lhxs);
397 addr |= (uint64_t)(guest_idx & APLIC_xMSICFGADDR_PPN_HART(lhxs));
398 addr <<= APLIC_xMSICFGADDR_PPN_SHIFT;
399
400 address_space_stl_le(&address_space_memory, addr,
401 eiid, MEMTXATTRS_UNSPECIFIED, &result);
402 if (result != MEMTX_OK) {
403 qemu_log_mask(LOG_GUEST_ERROR, "%s: MSI write failed for "
404 "hart_index=%d guest_index=%d eiid=%d\n",
405 __func__, hart_idx, guest_idx, eiid);
406 }
407 }
408
riscv_aplic_msi_irq_update(RISCVAPLICState * aplic,uint32_t irq)409 static void riscv_aplic_msi_irq_update(RISCVAPLICState *aplic, uint32_t irq)
410 {
411 uint32_t hart_idx, guest_idx, eiid;
412
413 if (!aplic->msimode || (aplic->num_irqs <= irq) ||
414 !(aplic->domaincfg & APLIC_DOMAINCFG_IE)) {
415 return;
416 }
417
418 if ((aplic->state[irq] & APLIC_ISTATE_ENPEND) != APLIC_ISTATE_ENPEND) {
419 return;
420 }
421
422 riscv_aplic_set_pending_raw(aplic, irq, false);
423
424 hart_idx = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
425 hart_idx &= APLIC_TARGET_HART_IDX_MASK;
426 if (aplic->mmode) {
427 /* M-level APLIC ignores guest_index */
428 guest_idx = 0;
429 } else {
430 guest_idx = aplic->target[irq] >> APLIC_TARGET_GUEST_IDX_SHIFT;
431 guest_idx &= APLIC_TARGET_GUEST_IDX_MASK;
432 }
433 eiid = aplic->target[irq] & APLIC_TARGET_EIID_MASK;
434 riscv_aplic_msi_send(aplic, hart_idx, guest_idx, eiid);
435 }
436
riscv_aplic_idc_topi(RISCVAPLICState * aplic,uint32_t idc)437 static uint32_t riscv_aplic_idc_topi(RISCVAPLICState *aplic, uint32_t idc)
438 {
439 uint32_t best_irq, best_iprio;
440 uint32_t irq, iprio, ihartidx, ithres;
441
442 if (aplic->num_harts <= idc) {
443 return 0;
444 }
445
446 ithres = aplic->ithreshold[idc];
447 best_irq = best_iprio = UINT32_MAX;
448 for (irq = 1; irq < aplic->num_irqs; irq++) {
449 if ((aplic->state[irq] & APLIC_ISTATE_ENPEND) !=
450 APLIC_ISTATE_ENPEND) {
451 continue;
452 }
453
454 ihartidx = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
455 ihartidx &= APLIC_TARGET_HART_IDX_MASK;
456 if (ihartidx != idc) {
457 continue;
458 }
459
460 iprio = aplic->target[irq] & aplic->iprio_mask;
461 if (ithres && iprio >= ithres) {
462 continue;
463 }
464
465 if (iprio < best_iprio) {
466 best_irq = irq;
467 best_iprio = iprio;
468 }
469 }
470
471 if (best_irq < aplic->num_irqs && best_iprio <= aplic->iprio_mask) {
472 return (best_irq << APLIC_IDC_TOPI_ID_SHIFT) | best_iprio;
473 }
474
475 return 0;
476 }
477
riscv_aplic_idc_update(RISCVAPLICState * aplic,uint32_t idc)478 static void riscv_aplic_idc_update(RISCVAPLICState *aplic, uint32_t idc)
479 {
480 uint32_t topi;
481
482 if (aplic->msimode || aplic->num_harts <= idc) {
483 return;
484 }
485
486 topi = riscv_aplic_idc_topi(aplic, idc);
487 if ((aplic->domaincfg & APLIC_DOMAINCFG_IE) &&
488 aplic->idelivery[idc] &&
489 (aplic->iforce[idc] || topi)) {
490 qemu_irq_raise(aplic->external_irqs[idc]);
491 } else {
492 qemu_irq_lower(aplic->external_irqs[idc]);
493 }
494 }
495
riscv_aplic_idc_claimi(RISCVAPLICState * aplic,uint32_t idc)496 static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
497 {
498 uint32_t irq, state, sm, topi = riscv_aplic_idc_topi(aplic, idc);
499
500 if (!topi) {
501 aplic->iforce[idc] = 0;
502 riscv_aplic_idc_update(aplic, idc);
503 return 0;
504 }
505
506 irq = (topi >> APLIC_IDC_TOPI_ID_SHIFT) & APLIC_IDC_TOPI_ID_MASK;
507 sm = aplic->sourcecfg[irq] & APLIC_SOURCECFG_SM_MASK;
508 state = aplic->state[irq];
509 riscv_aplic_set_pending_raw(aplic, irq, false);
510 if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) &&
511 (state & APLIC_ISTATE_INPUT)) {
512 riscv_aplic_set_pending_raw(aplic, irq, true);
513 } else if ((sm == APLIC_SOURCECFG_SM_LEVEL_LOW) &&
514 !(state & APLIC_ISTATE_INPUT)) {
515 riscv_aplic_set_pending_raw(aplic, irq, true);
516 }
517 riscv_aplic_idc_update(aplic, idc);
518
519 return topi;
520 }
521
riscv_aplic_request(void * opaque,int irq,int level)522 static void riscv_aplic_request(void *opaque, int irq, int level)
523 {
524 bool update = false;
525 RISCVAPLICState *aplic = opaque;
526 uint32_t sourcecfg, childidx, state, idc;
527
528 assert((0 < irq) && (irq < aplic->num_irqs));
529
530 sourcecfg = aplic->sourcecfg[irq];
531 if (sourcecfg & APLIC_SOURCECFG_D) {
532 childidx = sourcecfg & APLIC_SOURCECFG_CHILDIDX_MASK;
533 if (childidx < aplic->num_children) {
534 riscv_aplic_request(aplic->children[childidx], irq, level);
535 }
536 return;
537 }
538
539 state = aplic->state[irq];
540 switch (sourcecfg & APLIC_SOURCECFG_SM_MASK) {
541 case APLIC_SOURCECFG_SM_EDGE_RISE:
542 if ((level > 0) && !(state & APLIC_ISTATE_INPUT) &&
543 !(state & APLIC_ISTATE_PENDING)) {
544 riscv_aplic_set_pending_raw(aplic, irq, true);
545 update = true;
546 }
547 break;
548 case APLIC_SOURCECFG_SM_EDGE_FALL:
549 if ((level <= 0) && (state & APLIC_ISTATE_INPUT) &&
550 !(state & APLIC_ISTATE_PENDING)) {
551 riscv_aplic_set_pending_raw(aplic, irq, true);
552 update = true;
553 }
554 break;
555 case APLIC_SOURCECFG_SM_LEVEL_HIGH:
556 if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
557 riscv_aplic_set_pending_raw(aplic, irq, true);
558 update = true;
559 }
560 break;
561 case APLIC_SOURCECFG_SM_LEVEL_LOW:
562 if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
563 riscv_aplic_set_pending_raw(aplic, irq, true);
564 update = true;
565 }
566 break;
567 default:
568 break;
569 }
570
571 if (level <= 0) {
572 aplic->state[irq] &= ~APLIC_ISTATE_INPUT;
573 } else {
574 aplic->state[irq] |= APLIC_ISTATE_INPUT;
575 }
576
577 if (update) {
578 if (aplic->msimode) {
579 riscv_aplic_msi_irq_update(aplic, irq);
580 } else {
581 idc = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
582 idc &= APLIC_TARGET_HART_IDX_MASK;
583 riscv_aplic_idc_update(aplic, idc);
584 }
585 }
586 }
587
riscv_aplic_read(void * opaque,hwaddr addr,unsigned size)588 static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
589 {
590 uint32_t irq, word, idc;
591 RISCVAPLICState *aplic = opaque;
592
593 /* Reads must be 4 byte words */
594 if ((addr & 0x3) != 0) {
595 goto err;
596 }
597
598 if (addr == APLIC_DOMAINCFG) {
599 return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
600 (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
601 } else if ((APLIC_SOURCECFG_BASE <= addr) &&
602 (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
603 irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
604 return aplic->sourcecfg[irq];
605 } else if (aplic->mmode && aplic->msimode &&
606 (addr == APLIC_MMSICFGADDR)) {
607 return aplic->mmsicfgaddr;
608 } else if (aplic->mmode && aplic->msimode &&
609 (addr == APLIC_MMSICFGADDRH)) {
610 return aplic->mmsicfgaddrH;
611 } else if (aplic->mmode && aplic->msimode &&
612 (addr == APLIC_SMSICFGADDR)) {
613 /*
614 * Registers SMSICFGADDR and SMSICFGADDRH are implemented only if:
615 * (a) the interrupt domain is at machine level
616 * (b) the domain's harts implement supervisor mode
617 * (c) the domain has one or more child supervisor-level domains
618 * that support MSI delivery mode (domaincfg.DM is not read-
619 * only zero in at least one of the supervisor-level child
620 * domains).
621 */
622 return (aplic->num_children) ? aplic->smsicfgaddr : 0;
623 } else if (aplic->mmode && aplic->msimode &&
624 (addr == APLIC_SMSICFGADDRH)) {
625 return (aplic->num_children) ? aplic->smsicfgaddrH : 0;
626 } else if ((APLIC_SETIP_BASE <= addr) &&
627 (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
628 word = (addr - APLIC_SETIP_BASE) >> 2;
629 return riscv_aplic_read_pending_word(aplic, word);
630 } else if (addr == APLIC_SETIPNUM) {
631 return 0;
632 } else if ((APLIC_CLRIP_BASE <= addr) &&
633 (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
634 word = (addr - APLIC_CLRIP_BASE) >> 2;
635 return riscv_aplic_read_input_word(aplic, word);
636 } else if (addr == APLIC_CLRIPNUM) {
637 return 0;
638 } else if ((APLIC_SETIE_BASE <= addr) &&
639 (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
640 word = (addr - APLIC_SETIE_BASE) >> 2;
641 return riscv_aplic_read_enabled_word(aplic, word);
642 } else if (addr == APLIC_SETIENUM) {
643 return 0;
644 } else if ((APLIC_CLRIE_BASE <= addr) &&
645 (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
646 return 0;
647 } else if (addr == APLIC_CLRIENUM) {
648 return 0;
649 } else if (addr == APLIC_SETIPNUM_LE) {
650 return 0;
651 } else if (addr == APLIC_SETIPNUM_BE) {
652 return 0;
653 } else if (addr == APLIC_GENMSI) {
654 return (aplic->msimode) ? aplic->genmsi : 0;
655 } else if ((APLIC_TARGET_BASE <= addr) &&
656 (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
657 irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
658 return aplic->target[irq];
659 } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
660 (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
661 idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
662 switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
663 case APLIC_IDC_IDELIVERY:
664 return aplic->idelivery[idc];
665 case APLIC_IDC_IFORCE:
666 return aplic->iforce[idc];
667 case APLIC_IDC_ITHRESHOLD:
668 return aplic->ithreshold[idc];
669 case APLIC_IDC_TOPI:
670 return riscv_aplic_idc_topi(aplic, idc);
671 case APLIC_IDC_CLAIMI:
672 return riscv_aplic_idc_claimi(aplic, idc);
673 default:
674 goto err;
675 };
676 }
677
678 err:
679 qemu_log_mask(LOG_GUEST_ERROR,
680 "%s: Invalid register read 0x%" HWADDR_PRIx "\n",
681 __func__, addr);
682 return 0;
683 }
684
riscv_aplic_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)685 static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
686 unsigned size)
687 {
688 RISCVAPLICState *aplic = opaque;
689 uint32_t irq, word, idc = UINT32_MAX;
690
691 /* Writes must be 4 byte words */
692 if ((addr & 0x3) != 0) {
693 goto err;
694 }
695
696 if (addr == APLIC_DOMAINCFG) {
697 /* Only IE bit writable at the moment */
698 value &= APLIC_DOMAINCFG_IE;
699 aplic->domaincfg = value;
700 } else if ((APLIC_SOURCECFG_BASE <= addr) &&
701 (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
702 irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
703 if (!aplic->num_children && (value & APLIC_SOURCECFG_D)) {
704 value = 0;
705 }
706 if (value & APLIC_SOURCECFG_D) {
707 value &= (APLIC_SOURCECFG_D | APLIC_SOURCECFG_CHILDIDX_MASK);
708 } else {
709 value &= (APLIC_SOURCECFG_D | APLIC_SOURCECFG_SM_MASK);
710 }
711 aplic->sourcecfg[irq] = value;
712 if ((aplic->sourcecfg[irq] & APLIC_SOURCECFG_D) ||
713 (aplic->sourcecfg[irq] == 0)) {
714 riscv_aplic_set_pending_raw(aplic, irq, false);
715 riscv_aplic_set_enabled_raw(aplic, irq, false);
716 } else {
717 if (riscv_aplic_irq_rectified_val(aplic, irq)) {
718 riscv_aplic_set_pending_raw(aplic, irq, true);
719 }
720 }
721 } else if (aplic->mmode && aplic->msimode &&
722 (addr == APLIC_MMSICFGADDR)) {
723 if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
724 aplic->mmsicfgaddr = value;
725 }
726 } else if (aplic->mmode && aplic->msimode &&
727 (addr == APLIC_MMSICFGADDRH)) {
728 if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
729 aplic->mmsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
730 }
731 } else if (aplic->mmode && aplic->msimode &&
732 (addr == APLIC_SMSICFGADDR)) {
733 /*
734 * Registers SMSICFGADDR and SMSICFGADDRH are implemented only if:
735 * (a) the interrupt domain is at machine level
736 * (b) the domain's harts implement supervisor mode
737 * (c) the domain has one or more child supervisor-level domains
738 * that support MSI delivery mode (domaincfg.DM is not read-
739 * only zero in at least one of the supervisor-level child
740 * domains).
741 */
742 if (aplic->num_children &&
743 !(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
744 aplic->smsicfgaddr = value;
745 }
746 } else if (aplic->mmode && aplic->msimode &&
747 (addr == APLIC_SMSICFGADDRH)) {
748 if (aplic->num_children &&
749 !(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
750 aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
751 }
752 } else if ((APLIC_SETIP_BASE <= addr) &&
753 (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
754 word = (addr - APLIC_SETIP_BASE) >> 2;
755 riscv_aplic_set_pending_word(aplic, word, value, true);
756 } else if (addr == APLIC_SETIPNUM) {
757 riscv_aplic_set_pending(aplic, value, true);
758 } else if ((APLIC_CLRIP_BASE <= addr) &&
759 (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
760 word = (addr - APLIC_CLRIP_BASE) >> 2;
761 riscv_aplic_set_pending_word(aplic, word, value, false);
762 } else if (addr == APLIC_CLRIPNUM) {
763 riscv_aplic_set_pending(aplic, value, false);
764 } else if ((APLIC_SETIE_BASE <= addr) &&
765 (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
766 word = (addr - APLIC_SETIE_BASE) >> 2;
767 riscv_aplic_set_enabled_word(aplic, word, value, true);
768 } else if (addr == APLIC_SETIENUM) {
769 riscv_aplic_set_enabled(aplic, value, true);
770 } else if ((APLIC_CLRIE_BASE <= addr) &&
771 (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
772 word = (addr - APLIC_CLRIE_BASE) >> 2;
773 riscv_aplic_set_enabled_word(aplic, word, value, false);
774 } else if (addr == APLIC_CLRIENUM) {
775 riscv_aplic_set_enabled(aplic, value, false);
776 } else if (addr == APLIC_SETIPNUM_LE) {
777 riscv_aplic_set_pending(aplic, value, true);
778 } else if (addr == APLIC_SETIPNUM_BE) {
779 riscv_aplic_set_pending(aplic, bswap32(value), true);
780 } else if (addr == APLIC_GENMSI) {
781 if (aplic->msimode) {
782 aplic->genmsi = value & ~(APLIC_TARGET_GUEST_IDX_MASK <<
783 APLIC_TARGET_GUEST_IDX_SHIFT);
784 riscv_aplic_msi_send(aplic,
785 value >> APLIC_TARGET_HART_IDX_SHIFT,
786 0,
787 value & APLIC_TARGET_EIID_MASK);
788 }
789 } else if ((APLIC_TARGET_BASE <= addr) &&
790 (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
791 irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
792 if (aplic->msimode) {
793 aplic->target[irq] = value;
794 } else {
795 aplic->target[irq] = (value & ~APLIC_TARGET_IPRIO_MASK) |
796 ((value & aplic->iprio_mask) ?
797 (value & aplic->iprio_mask) : 1);
798 }
799 } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
800 (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
801 idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
802 switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
803 case APLIC_IDC_IDELIVERY:
804 aplic->idelivery[idc] = value & 0x1;
805 break;
806 case APLIC_IDC_IFORCE:
807 aplic->iforce[idc] = value & 0x1;
808 break;
809 case APLIC_IDC_ITHRESHOLD:
810 aplic->ithreshold[idc] = value & aplic->iprio_mask;
811 break;
812 default:
813 goto err;
814 };
815 } else {
816 goto err;
817 }
818
819 if (aplic->msimode) {
820 for (irq = 1; irq < aplic->num_irqs; irq++) {
821 riscv_aplic_msi_irq_update(aplic, irq);
822 }
823 } else {
824 if (idc == UINT32_MAX) {
825 for (idc = 0; idc < aplic->num_harts; idc++) {
826 riscv_aplic_idc_update(aplic, idc);
827 }
828 } else {
829 riscv_aplic_idc_update(aplic, idc);
830 }
831 }
832
833 return;
834
835 err:
836 qemu_log_mask(LOG_GUEST_ERROR,
837 "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
838 __func__, addr);
839 }
840
841 static const MemoryRegionOps riscv_aplic_ops = {
842 .read = riscv_aplic_read,
843 .write = riscv_aplic_write,
844 .endianness = DEVICE_LITTLE_ENDIAN,
845 .valid = {
846 .min_access_size = 4,
847 .max_access_size = 4
848 }
849 };
850
riscv_aplic_realize(DeviceState * dev,Error ** errp)851 static void riscv_aplic_realize(DeviceState *dev, Error **errp)
852 {
853 uint32_t i;
854 RISCVAPLICState *aplic = RISCV_APLIC(dev);
855
856 if (!is_kvm_aia(aplic->msimode)) {
857 aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
858 aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
859 aplic->state = g_new0(uint32_t, aplic->num_irqs);
860 aplic->target = g_new0(uint32_t, aplic->num_irqs);
861 if (!aplic->msimode) {
862 for (i = 0; i < aplic->num_irqs; i++) {
863 aplic->target[i] = 1;
864 }
865 }
866 aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
867 aplic->iforce = g_new0(uint32_t, aplic->num_harts);
868 aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
869
870 memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops,
871 aplic, TYPE_RISCV_APLIC, aplic->aperture_size);
872 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
873 }
874
875 /*
876 * Only root APLICs have hardware IRQ lines. All non-root APLICs
877 * have IRQ lines delegated by their parent APLIC.
878 */
879 if (!aplic->parent) {
880 if (kvm_enabled() && is_kvm_aia(aplic->msimode)) {
881 qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
882 } else {
883 qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
884 }
885 }
886
887 /* Create output IRQ lines for non-MSI mode */
888 if (!aplic->msimode) {
889 aplic->external_irqs = g_malloc(sizeof(qemu_irq) * aplic->num_harts);
890 qdev_init_gpio_out(dev, aplic->external_irqs, aplic->num_harts);
891
892 /* Claim the CPU interrupt to be triggered by this APLIC */
893 for (i = 0; i < aplic->num_harts; i++) {
894 RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(aplic->hartid_base + i));
895 if (riscv_cpu_claim_interrupts(cpu,
896 (aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
897 error_report("%s already claimed",
898 (aplic->mmode) ? "MEIP" : "SEIP");
899 exit(1);
900 }
901 }
902 }
903
904 msi_nonbroken = true;
905 }
906
907 static Property riscv_aplic_properties[] = {
908 DEFINE_PROP_UINT32("aperture-size", RISCVAPLICState, aperture_size, 0),
909 DEFINE_PROP_UINT32("hartid-base", RISCVAPLICState, hartid_base, 0),
910 DEFINE_PROP_UINT32("num-harts", RISCVAPLICState, num_harts, 0),
911 DEFINE_PROP_UINT32("iprio-mask", RISCVAPLICState, iprio_mask, 0),
912 DEFINE_PROP_UINT32("num-irqs", RISCVAPLICState, num_irqs, 0),
913 DEFINE_PROP_BOOL("msimode", RISCVAPLICState, msimode, 0),
914 DEFINE_PROP_BOOL("mmode", RISCVAPLICState, mmode, 0),
915 DEFINE_PROP_END_OF_LIST(),
916 };
917
918 static const VMStateDescription vmstate_riscv_aplic = {
919 .name = "riscv_aplic",
920 .version_id = 1,
921 .minimum_version_id = 1,
922 .fields = (const VMStateField[]) {
923 VMSTATE_UINT32(domaincfg, RISCVAPLICState),
924 VMSTATE_UINT32(mmsicfgaddr, RISCVAPLICState),
925 VMSTATE_UINT32(mmsicfgaddrH, RISCVAPLICState),
926 VMSTATE_UINT32(smsicfgaddr, RISCVAPLICState),
927 VMSTATE_UINT32(smsicfgaddrH, RISCVAPLICState),
928 VMSTATE_UINT32(genmsi, RISCVAPLICState),
929 VMSTATE_VARRAY_UINT32(sourcecfg, RISCVAPLICState,
930 num_irqs, 0,
931 vmstate_info_uint32, uint32_t),
932 VMSTATE_VARRAY_UINT32(state, RISCVAPLICState,
933 num_irqs, 0,
934 vmstate_info_uint32, uint32_t),
935 VMSTATE_VARRAY_UINT32(target, RISCVAPLICState,
936 num_irqs, 0,
937 vmstate_info_uint32, uint32_t),
938 VMSTATE_VARRAY_UINT32(idelivery, RISCVAPLICState,
939 num_harts, 0,
940 vmstate_info_uint32, uint32_t),
941 VMSTATE_VARRAY_UINT32(iforce, RISCVAPLICState,
942 num_harts, 0,
943 vmstate_info_uint32, uint32_t),
944 VMSTATE_VARRAY_UINT32(ithreshold, RISCVAPLICState,
945 num_harts, 0,
946 vmstate_info_uint32, uint32_t),
947 VMSTATE_END_OF_LIST()
948 }
949 };
950
riscv_aplic_class_init(ObjectClass * klass,void * data)951 static void riscv_aplic_class_init(ObjectClass *klass, void *data)
952 {
953 DeviceClass *dc = DEVICE_CLASS(klass);
954
955 device_class_set_props(dc, riscv_aplic_properties);
956 dc->realize = riscv_aplic_realize;
957 dc->vmsd = &vmstate_riscv_aplic;
958 }
959
960 static const TypeInfo riscv_aplic_info = {
961 .name = TYPE_RISCV_APLIC,
962 .parent = TYPE_SYS_BUS_DEVICE,
963 .instance_size = sizeof(RISCVAPLICState),
964 .class_init = riscv_aplic_class_init,
965 };
966
riscv_aplic_register_types(void)967 static void riscv_aplic_register_types(void)
968 {
969 type_register_static(&riscv_aplic_info);
970 }
971
type_init(riscv_aplic_register_types)972 type_init(riscv_aplic_register_types)
973
974 /*
975 * Add a APLIC device to another APLIC device as child for
976 * interrupt delegation.
977 */
978 void riscv_aplic_add_child(DeviceState *parent, DeviceState *child)
979 {
980 RISCVAPLICState *caplic, *paplic;
981
982 assert(parent && child);
983 caplic = RISCV_APLIC(child);
984 paplic = RISCV_APLIC(parent);
985
986 assert(paplic->num_irqs == caplic->num_irqs);
987 assert(paplic->num_children <= QEMU_APLIC_MAX_CHILDREN);
988
989 caplic->parent = paplic;
990 paplic->children[paplic->num_children] = caplic;
991 paplic->num_children++;
992 }
993
994 /*
995 * Create APLIC device.
996 */
riscv_aplic_create(hwaddr addr,hwaddr size,uint32_t hartid_base,uint32_t num_harts,uint32_t num_sources,uint32_t iprio_bits,bool msimode,bool mmode,DeviceState * parent)997 DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
998 uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
999 uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent)
1000 {
1001 DeviceState *dev = qdev_new(TYPE_RISCV_APLIC);
1002 uint32_t i;
1003
1004 assert(num_harts < APLIC_MAX_IDC);
1005 assert((APLIC_IDC_BASE + (num_harts * APLIC_IDC_SIZE)) <= size);
1006 assert(num_sources < APLIC_MAX_SOURCE);
1007 assert(APLIC_MIN_IPRIO_BITS <= iprio_bits);
1008 assert(iprio_bits <= APLIC_MAX_IPRIO_BITS);
1009
1010 qdev_prop_set_uint32(dev, "aperture-size", size);
1011 qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
1012 qdev_prop_set_uint32(dev, "num-harts", num_harts);
1013 qdev_prop_set_uint32(dev, "iprio-mask", ((1U << iprio_bits) - 1));
1014 qdev_prop_set_uint32(dev, "num-irqs", num_sources + 1);
1015 qdev_prop_set_bit(dev, "msimode", msimode);
1016 qdev_prop_set_bit(dev, "mmode", mmode);
1017
1018 if (parent) {
1019 riscv_aplic_add_child(parent, dev);
1020 }
1021
1022 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1023
1024 if (!is_kvm_aia(msimode)) {
1025 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
1026 }
1027
1028 if (!msimode) {
1029 for (i = 0; i < num_harts; i++) {
1030 CPUState *cpu = cpu_by_arch_id(hartid_base + i);
1031
1032 qdev_connect_gpio_out_named(dev, NULL, i,
1033 qdev_get_gpio_in(DEVICE(cpu),
1034 (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
1035 }
1036 }
1037
1038 return dev;
1039 }
1040