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