gic_v3_distributor.cc revision 14257
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Jairo Balart
41 */
42
43#include "dev/arm/gic_v3_distributor.hh"
44
45#include <algorithm>
46
47#include "base/intmath.hh"
48#include "debug/GIC.hh"
49#include "dev/arm/gic_v3.hh"
50#include "dev/arm/gic_v3_cpu_interface.hh"
51#include "dev/arm/gic_v3_redistributor.hh"
52
53const AddrRange Gicv3Distributor::GICD_IGROUPR   (0x0080, 0x00ff);
54const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
55const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
56const AddrRange Gicv3Distributor::GICD_ISPENDR   (0x0200, 0x027f);
57const AddrRange Gicv3Distributor::GICD_ICPENDR   (0x0280, 0x02ff);
58const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
59const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
60const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
61const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
62const AddrRange Gicv3Distributor::GICD_ICFGR     (0x0c00, 0x0cff);
63const AddrRange Gicv3Distributor::GICD_IGRPMODR  (0x0d00, 0x0d7f);
64const AddrRange Gicv3Distributor::GICD_NSACR     (0x0e00, 0x0eff);
65const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
66const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
67const AddrRange Gicv3Distributor::GICD_IROUTER   (0x6000, 0x7fe0);
68
69Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
70    : gic(gic),
71      itLines(it_lines),
72      irqGroup(it_lines),
73      irqEnabled(it_lines),
74      irqPending(it_lines),
75      irqActive(it_lines),
76      irqPriority(it_lines),
77      irqConfig(it_lines),
78      irqGrpmod(it_lines),
79      irqNsacr(it_lines),
80      irqAffinityRouting(it_lines),
81      gicdTyper(0),
82      gicdPidr0(0x92),
83      gicdPidr1(0xb4),
84      gicdPidr2(0x3b),
85      gicdPidr3(0),
86      gicdPidr4(0x44)
87{
88    panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
89    /*
90     * RSS           [26]    == 1
91     * (The implementation does supports targeted SGIs with affinity
92     * level 0 values of 0 - 255)
93     * No1N          [25]    == 1
94     * (1 of N SPI interrupts are not supported)
95     * A3V           [24]    == 1
96     * (Supports nonzero values of Affinity level 3)
97     * IDbits        [23:19] == 0xf
98     * (The number of interrupt identifier bits supported, minus one)
99     * DVIS          [18]    == 0
100     * (The implementation does not support Direct Virtual LPI
101     * injection)
102     * LPIS          [17]    == 1
103     * (The implementation does not support LPIs)
104     * MBIS          [16]    == 1
105     * (The implementation supports message-based interrupts
106     * by writing to Distributor registers)
107     * SecurityExtn  [10]    == X
108     * (The GIC implementation supports two Security states)
109     * CPUNumber     [7:5]   == 0
110     * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
111     * ITLinesNumber [4:0]   == N
112     * (MaxSPIIntId = 32 (N + 1) - 1)
113     */
114    int max_spi_int_id = itLines - 1;
115    int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1;
116    gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
117        (1 << 17) | (1 << 16) |
118        ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) |
119        (it_lines_number << 0);
120}
121
122void
123Gicv3Distributor::init()
124{
125}
126
127void
128Gicv3Distributor::initState()
129{
130    reset();
131}
132
133void
134Gicv3Distributor::reset()
135{
136    std::fill(irqGroup.begin(), irqGroup.end(), 0);
137    // Imp. defined reset value
138    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
139    std::fill(irqPending.begin(), irqPending.end(), false);
140    std::fill(irqActive.begin(), irqActive.end(), false);
141    // Imp. defined reset value
142    std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA);
143    std::fill(irqConfig.begin(), irqConfig.end(),
144              Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value
145    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
146    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
147    /*
148     * For our implementation affinity routing is always enabled,
149     * no GICv2 legacy
150     */
151    ARE = true;
152
153    if (gic->getSystem()->haveSecurity()) {
154        DS = false;
155    } else {
156        DS = true;
157    }
158
159    EnableGrp0 = 0;
160    EnableGrp1NS = 0;
161    EnableGrp1S = 0;
162}
163
164uint64_t
165Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
166{
167    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
168        uint64_t val = 0x0;
169
170        if (!DS && !is_secure_access) {
171            // RAZ/WI for non-secure accesses
172            return 0;
173        }
174
175        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
176
177        if (isNotSPI(first_intid)) {
178            return 0;
179        }
180
181        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
182             i++, int_id++) {
183            val |= irqGroup[int_id] << i;
184        }
185
186        return val;
187    } else if (GICD_ISENABLER.contains(addr)) {
188        // Interrupt Set-Enable Registers
189        uint64_t val = 0x0;
190        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
191
192        if (isNotSPI(first_intid)) {
193            return 0;
194        }
195
196        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
197             i++, int_id++) {
198
199            if (nsAccessToSecInt(int_id, is_secure_access))
200            {
201                continue;
202            }
203
204            val |= irqEnabled[int_id] << i;
205        }
206
207        return val;
208    } else if (GICD_ICENABLER.contains(addr)) {
209        // Interrupt Clear-Enable Registers
210        uint64_t val = 0x0;
211        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
212
213        if (isNotSPI(first_intid)) {
214            return 0;
215        }
216
217        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
218             i++, int_id++) {
219
220            if (nsAccessToSecInt(int_id, is_secure_access))
221            {
222                continue;
223            }
224
225            val |= (irqEnabled[int_id] << i);
226        }
227
228        return val;
229    } else if (GICD_ISPENDR.contains(addr)) {
230        // Interrupt Set-Pending Registers
231        uint64_t val = 0x0;
232        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
233
234        if (isNotSPI(first_intid)) {
235            return 0;
236        }
237
238        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
239             i++, int_id++) {
240
241            if (nsAccessToSecInt(int_id, is_secure_access))
242            {
243                if (irqNsacr[int_id] == 0) {
244                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
245                    continue;
246                }
247            }
248
249            val |= (irqPending[int_id] << i);
250        }
251
252        return val;
253    } else if (GICD_ICPENDR.contains(addr)) {
254        // Interrupt Clear-Pending Registers
255        uint64_t val = 0x0;
256        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
257
258        if (isNotSPI(first_intid)) {
259            return 0;
260        }
261
262        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
263             i++, int_id++) {
264
265            if (nsAccessToSecInt(int_id, is_secure_access))
266            {
267                if (irqNsacr[int_id] < 2) {
268                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
269                    continue;
270                }
271            }
272
273            val |= (irqPending[int_id] << i);
274        }
275
276        return val;
277    } else if (GICD_ISACTIVER.contains(addr)) {
278        // Interrupt Set-Active Registers
279        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
280
281        if (isNotSPI(first_intid)) {
282            return 0;
283        }
284
285        uint64_t val = 0x0;
286
287        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
288             i++, int_id++) {
289
290            if (nsAccessToSecInt(int_id, is_secure_access))
291            {
292                // Group 0 or Secure Group 1 interrupts are RAZ/WI
293                if (irqNsacr[int_id] < 2) {
294                    continue;
295                }
296            }
297
298            val |= (irqActive[int_id] << i);
299        }
300
301        return val;
302    } else if (GICD_ICACTIVER.contains(addr)) {
303        // Interrupt Clear-Active Registers
304        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
305
306        if (isNotSPI(first_intid)) {
307            return 0;
308        }
309
310        uint64_t val = 0x0;
311
312        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
313             i++, int_id++) {
314
315            if (nsAccessToSecInt(int_id, is_secure_access))
316            {
317                if (irqNsacr[int_id] < 2) {
318                    continue;
319                }
320            }
321
322            val |= (irqActive[int_id] << i);
323        }
324
325        return val;
326    } else if (GICD_IPRIORITYR.contains(addr)) {
327        // Interrupt Priority Registers
328        uint64_t val = 0x0;
329        int first_intid = addr - GICD_IPRIORITYR.start();
330
331        if (isNotSPI(first_intid)) {
332            return 0;
333        }
334
335        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
336             i++, int_id++) {
337
338            uint8_t prio = irqPriority[int_id];
339
340            if (!DS && !is_secure_access) {
341                if (getIntGroup(int_id) != Gicv3::G1NS) {
342                    // RAZ/WI for non-secure accesses for secure interrupts
343                    continue;
344                } else {
345                    // NS view
346                    prio = (prio << 1) & 0xff;
347                }
348            }
349
350            val |= prio << (i * 8);
351        }
352
353        return val;
354    } else if (GICD_ITARGETSR.contains(addr)) {
355        // Interrupt Processor Targets Registers
356        // ARE always on, RAZ/WI
357        warn("Gicv3Distributor::read(): "
358             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
359        return 0;
360    } else if (GICD_ICFGR.contains(addr)) {
361        // Interrupt Configuration Registers
362        int first_intid = (addr - GICD_ICFGR.start()) * 4;
363
364        if (isNotSPI(first_intid)) {
365            return 0;
366        }
367
368        uint64_t val = 0x0;
369
370        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
371             i = i + 2, int_id++) {
372
373            if (nsAccessToSecInt(int_id, is_secure_access))
374            {
375                continue;
376            }
377
378            if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
379                val |= (0x2 << i);
380            }
381        }
382
383        return val;
384    } else if (GICD_IGRPMODR.contains(addr)) {
385        // Interrupt Group Modifier Registers
386        if (DS) {
387            // RAZ/WI if security disabled
388            return 0;
389        } else {
390            if (!is_secure_access) {
391                // RAZ/WI for non-secure accesses
392                return 0;
393            } else {
394                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
395
396                if (isNotSPI(first_intid)) {
397                    return 0;
398                }
399
400                uint64_t val = 0x0;
401
402                for (int i = 0, int_id = first_intid;
403                     i < 8 * size && int_id < itLines; i++, int_id++) {
404                    val |= irqGrpmod[int_id] << i;
405                }
406
407                return val;
408            }
409        }
410    } else if (GICD_NSACR.contains(addr)) {
411        // Non-secure Access Control Registers
412        // 2 bits per interrupt
413        int first_intid = (addr - GICD_NSACR.start()) * 4;
414
415        if (isNotSPI(first_intid)) {
416            return 0;
417        }
418
419        if (DS || (!DS && !is_secure_access)) {
420            return 0;
421        }
422
423        uint64_t val = 0x0;
424
425        for (int i = 0, int_id = first_intid;
426             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
427            val |= irqNsacr[int_id] << i;
428        }
429
430        return val;
431    } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
432        // ARE always on, RAZ/WI
433        warn("Gicv3Distributor::read(): "
434             "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
435        return 0x0;
436    } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
437        // ARE always on, RAZ/WI
438        warn("Gicv3Distributor::read(): "
439             "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
440        return 0x0;
441    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
442        // 64 bit registers. 2 or 1 access.
443        int int_id = (addr - GICD_IROUTER.start()) / 8;
444
445        if (isNotSPI(int_id)) {
446            return 0;
447        }
448
449        if (nsAccessToSecInt(int_id, is_secure_access))
450        {
451            if (irqNsacr[int_id] < 3) {
452                return 0;
453            }
454        }
455
456        if (size == 4) {
457            if (addr & 7) { // high half of 64 bit register
458                return irqAffinityRouting[int_id] >> 32;
459            } else { // high low of 64 bit register
460                return irqAffinityRouting[int_id] & 0xFFFFFFFF;
461            }
462        } else {
463            return irqAffinityRouting[int_id];
464        }
465    }
466
467    switch (addr) {
468      case GICD_CTLR: // Control Register
469        if (!DS) {
470            if (is_secure_access) {
471                // E1NWF [7] RAZ/WI
472                // DS [6] - Disable Security
473                // ARE_NS [5] RAO/WI
474                // ARE_S [4] RAO/WI
475                // EnableGrp1S [2]
476                // EnableGrp1NS [1]
477                // EnableGrp0 [0]
478                return (EnableGrp0 << 0) |
479                    (EnableGrp1NS << 1) |
480                    (EnableGrp1S << 2) |
481                    (1 << 4) |
482                    (1 << 5) |
483                    (DS << 6);
484            } else {
485                // ARE_NS [4] RAO/WI;
486                // EnableGrp1A [1] is a read-write alias of the Secure
487                // GICD_CTLR.EnableGrp1NS
488                // EnableGrp1 [0] RES0
489                return (1 << 4) | (EnableGrp1NS << 1);
490            }
491        } else {
492            return (DS << 6) | (ARE << 4) |
493                (EnableGrp1NS << 1) | (EnableGrp0 << 0);
494        }
495
496      case GICD_TYPER: // Interrupt Controller Type Register
497        return gicdTyper;
498
499      case GICD_IIDR: // Implementer Identification Register
500        //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
501        return 0;
502
503      case GICD_STATUSR: // Error Reporting Status Register
504        // Optional register, RAZ/WI
505        return 0x0;
506
507      case GICD_PIDR0: // Peripheral ID0 Register
508        return gicdPidr0;
509
510      case GICD_PIDR1: // Peripheral ID1 Register
511        return gicdPidr1;
512
513      case GICD_PIDR2: // Peripheral ID2 Register
514        return gicdPidr2;
515
516      case GICD_PIDR3: // Peripheral ID3 Register
517        return gicdPidr3;
518
519      case GICD_PIDR4: // Peripheral ID4 Register
520        return gicdPidr4;
521
522      case GICD_PIDR5: // Peripheral ID5 Register
523      case GICD_PIDR6: // Peripheral ID6 Register
524      case GICD_PIDR7: // Peripheral ID7 Register
525        return 0; // RES0
526
527      default:
528        panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
529        break;
530    }
531}
532
533void
534Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
535                        bool is_secure_access)
536{
537    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
538        if (!DS && !is_secure_access) {
539            // RAZ/WI for non-secure accesses
540            return;
541        }
542
543        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
544
545        if (isNotSPI(first_intid)) {
546            return;
547        }
548
549        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
550             i++, int_id++) {
551            irqGroup[int_id] = data & (1 << i) ? 1 : 0;
552            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
553                    int_id, irqGroup[int_id]);
554        }
555
556        return;
557    } else if (GICD_ISENABLER.contains(addr)) {
558        // Interrupt Set-Enable Registers
559        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
560
561        if (isNotSPI(first_intid)) {
562            return;
563        }
564
565        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
566             i++, int_id++) {
567
568            if (nsAccessToSecInt(int_id, is_secure_access))
569            {
570                continue;
571            }
572
573            bool enable = data & (1 << i) ? 1 : 0;
574
575            if (enable) {
576                if (!irqEnabled[int_id]) {
577                    DPRINTF(GIC, "Gicv3Distributor::write(): "
578                            "int_id %d enabled\n", int_id);
579                }
580
581                irqEnabled[int_id] = true;
582            }
583        }
584
585        return;
586    } else if (GICD_ICENABLER.contains(addr)) {
587        // Interrupt Clear-Enable Registers
588        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
589
590        if (isNotSPI(first_intid)) {
591            return;
592        }
593
594        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
595             i++, int_id++) {
596
597            if (nsAccessToSecInt(int_id, is_secure_access))
598            {
599                continue;
600            }
601
602            bool disable = data & (1 << i) ? 1 : 0;
603
604            if (disable) {
605                if (irqEnabled[int_id]) {
606                    DPRINTF(GIC, "Gicv3Distributor::write(): "
607                            "int_id %d disabled\n", int_id);
608                }
609
610                irqEnabled[int_id] = false;
611            }
612        }
613
614        return;
615    } else if (GICD_ISPENDR.contains(addr)) {
616        // Interrupt Set-Pending Registers
617        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
618
619        if (isNotSPI(first_intid)) {
620            return;
621        }
622
623        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
624             i++, int_id++) {
625
626            if (nsAccessToSecInt(int_id, is_secure_access))
627            {
628                if (irqNsacr[int_id] == 0) {
629                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
630                    continue;
631                }
632            }
633
634            bool pending = data & (1 << i) ? 1 : 0;
635
636            if (pending) {
637                DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
638                        "int_id %d (SPI) pending bit set\n", int_id);
639                irqPending[int_id] = true;
640            }
641        }
642
643        update();
644        return;
645    } else if (GICD_ICPENDR.contains(addr)) {
646        // Interrupt Clear-Pending Registers
647        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
648
649        if (isNotSPI(first_intid)) {
650            return;
651        }
652
653        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
654             i++, int_id++) {
655
656            if (nsAccessToSecInt(int_id, is_secure_access))
657            {
658                if (irqNsacr[int_id] < 2) {
659                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
660                    continue;
661                }
662            }
663
664            bool clear = data & (1 << i) ? 1 : 0;
665
666            if (clear) {
667                irqPending[int_id] = false;
668                clearIrqCpuInterface(int_id);
669            }
670        }
671
672        update();
673        return;
674    } else if (GICD_ISACTIVER.contains(addr)) {
675        // Interrupt Set-Active Registers
676        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
677
678        if (isNotSPI(first_intid)) {
679            return;
680        }
681
682        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
683             i++, int_id++) {
684
685            if (nsAccessToSecInt(int_id, is_secure_access))
686            {
687                continue;
688            }
689
690            bool active = data & (1 << i) ? 1 : 0;
691
692            if (active) {
693                irqActive[int_id] = 1;
694            }
695        }
696
697        return;
698    } else if (GICD_ICACTIVER.contains(addr)) {
699        // Interrupt Clear-Active Registers
700        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
701
702        if (isNotSPI(first_intid)) {
703            return;
704        }
705
706        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
707             i++, int_id++) {
708
709            if (nsAccessToSecInt(int_id, is_secure_access))
710            {
711                continue;
712            }
713
714            bool clear = data & (1 << i) ? 1 : 0;
715
716            if (clear) {
717                if (irqActive[int_id]) {
718                    DPRINTF(GIC, "Gicv3Distributor::write(): "
719                            "int_id %d active cleared\n", int_id);
720                }
721
722                irqActive[int_id] = false;
723            }
724        }
725
726        return;
727    } else if (GICD_IPRIORITYR.contains(addr)) {
728        // Interrupt Priority Registers
729        int first_intid = addr - GICD_IPRIORITYR.start();
730
731        if (isNotSPI(first_intid)) {
732            return;
733        }
734
735        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
736                i++, int_id++) {
737            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
738
739            if (!DS && !is_secure_access) {
740                if (getIntGroup(int_id) != Gicv3::G1NS) {
741                    // RAZ/WI for non-secure accesses to secure interrupts
742                    continue;
743                } else {
744                    prio = 0x80 | (prio >> 1);
745                }
746            }
747
748            irqPriority[int_id] = prio;
749            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
750                    int_id, irqPriority[int_id]);
751        }
752
753        return;
754    } else if (GICD_ITARGETSR.contains(addr)) {
755        // Interrupt Processor Targets Registers
756        // ARE always on, RAZ/WI
757        warn("Gicv3Distributor::write(): "
758             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
759        return;
760    } else if (GICD_ICFGR.contains(addr)) {
761        // Interrupt Configuration Registers
762        // for x = 0 to 15:
763        //   GICD_ICFGR[2x] = RES0
764        //   GICD_ICFGR[2x + 1] =
765        //     0 level-sensitive
766        //     1 edge-triggered
767        int first_intid = (addr - GICD_ICFGR.start()) * 4;
768
769        if (isNotSPI(first_intid)) {
770            return;
771        }
772
773        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
774             i = i + 2, int_id++) {
775            irqConfig[int_id] = data & (0x2 << i) ?
776                                Gicv3::INT_EDGE_TRIGGERED :
777                                Gicv3::INT_LEVEL_SENSITIVE;
778            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
779                    int_id, irqConfig[int_id]);
780        }
781
782        return;
783    } else if (GICD_IGRPMODR.contains(addr)) {
784        // Interrupt Group Modifier Registers
785        if (DS) {
786            return;
787        } else {
788            if (!is_secure_access) {
789                // RAZ/WI for non-secure accesses
790                return;
791            } else {
792                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
793
794                if (isNotSPI(first_intid)) {
795                    return;
796                }
797
798                for (int i = 0, int_id = first_intid;
799                     i < 8 * size && int_id < itLines; i++, int_id++) {
800                    irqGrpmod[int_id] = bits(data, i);
801                }
802
803                return ;
804            }
805        }
806
807    } else if (GICD_NSACR.contains(addr)) {
808        // Non-secure Access Control Registers
809        // 2 bits per interrupt
810        int first_intid = (addr - GICD_NSACR.start()) * 4;
811
812        if (isNotSPI(first_intid)) {
813            return;
814        }
815
816        if (DS || (!DS && !is_secure_access)) {
817            return;
818        }
819
820        for (int i = 0, int_id = first_intid;
821             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
822            irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
823        }
824
825        return;
826    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
827        // 64 bit registers. 2 accesses.
828        int int_id = (addr - GICD_IROUTER.start()) / 8;
829
830        if (isNotSPI(int_id)) {
831            return;
832        }
833
834        if (nsAccessToSecInt(int_id, is_secure_access))
835        {
836            if (irqNsacr[int_id] < 3) {
837                // Group 0 or Secure Group 1 interrupts are RAZ/WI
838                return;
839            }
840        }
841
842        if (size == 4) {
843            if (addr & 7) { // high half of 64 bit register
844                irqAffinityRouting[int_id] =
845                    (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
846            } else { // low half of 64 bit register
847                irqAffinityRouting[int_id] =
848                    (irqAffinityRouting[int_id] & 0xffffffff00000000) |
849                    (data & 0xffffffff);
850            }
851        } else {
852            irqAffinityRouting[int_id] = data;
853        }
854
855        DPRINTF(GIC, "Gicv3Distributor::write(): "
856                "int_id %d GICD_IROUTER %#llx\n",
857                int_id, irqAffinityRouting[int_id]);
858        return;
859    }
860
861    switch (addr) {
862      case GICD_CTLR: // Control Register
863        if (DS) {
864            /*
865             * E1NWF [7]
866             * 1 of N wakeup functionality not supported, RAZ/WI
867             * DS [6] - RAO/WI
868             * ARE [4]
869             * affinity routing always on, no GICv2 legacy, RAO/WI
870             * EnableGrp1 [1]
871             * EnableGrp0 [0]
872             */
873            if ((data & (1 << 4)) == 0) {
874                warn("Gicv3Distributor::write(): "
875                        "setting ARE to 0 is not supported!\n");
876            }
877
878            EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
879            EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
880            DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
881                    "EnableGrp1NS %d EnableGrp0 %d\n",
882                    EnableGrp1NS, EnableGrp0);
883        } else {
884            if (is_secure_access) {
885                /*
886                 * E1NWF [7]
887                 * 1 of N wakeup functionality not supported, RAZ/WI
888                 * DS [6]
889                 * ARE_NS [5]
890                 * affinity routing always on, no GICv2 legacy, RAO/WI
891                 * ARE_S [4]
892                 * affinity routing always on, no GICv2 legacy, RAO/WI
893                 * EnableGrp1S [2]
894                 * EnableGrp1NS [1]
895                 * EnableGrp0 [0]
896                 */
897                if ((data & (1 << 5)) == 0) {
898                    warn("Gicv3Distributor::write(): "
899                            "setting ARE_NS to 0 is not supported!\n");
900                }
901
902                if ((data & (1 << 4)) == 0) {
903                    warn("Gicv3Distributor::write(): "
904                            "setting ARE_S to 0 is not supported!\n");
905                }
906
907                DS = data & GICD_CTLR_DS;
908                EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S;
909                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
910                EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
911                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
912                        "DS %d "
913                        "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
914                        DS, EnableGrp1S, EnableGrp1NS, EnableGrp0);
915
916                if (data & GICD_CTLR_DS) {
917                    EnableGrp1S = 0;
918                }
919            } else {
920                /*
921                 * ARE_NS [4] RAO/WI;
922                 * EnableGrp1A [1] is a read-write alias of the Secure
923                 * GICD_CTLR.EnableGrp1NS
924                 * EnableGrp1 [0] RES0
925                 */
926                if ((data & (1 << 4)) == 0) {
927                    warn("Gicv3Distributor::write(): "
928                            "setting ARE_NS to 0 is not supported!\n");
929                }
930
931                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A;
932                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
933                        "EnableGrp1NS %d\n", EnableGrp1NS);
934            }
935        }
936
937        update();
938
939        break;
940
941      case GICD_SGIR: // Error Reporting Status Register
942        // Only if affinity routing is disabled, RES0
943        break;
944
945      case GICD_SETSPI_NSR: {
946        // Writes to this register have no effect if:
947        // * The value written specifies an invalid SPI.
948        // * The SPI is already pending.
949        // * The value written specifies a Secure SPI, the value is
950        // written by a Non-secure access, and the value of the
951        // corresponding GICD_NSACR<n> register is 0.
952        const uint32_t intid = bits(data, 9, 0);
953        if (isNotSPI(intid) || irqPending[intid] ||
954            (nsAccessToSecInt(intid, is_secure_access) &&
955             irqNsacr[intid] == 0)) {
956            return;
957        } else {
958            // Valid SPI, set interrupt pending
959            sendInt(intid);
960        }
961        break;
962      }
963
964      case GICD_CLRSPI_NSR: {
965        // Writes to this register have no effect if:
966        // * The value written specifies an invalid SPI.
967        // * The SPI is not pending.
968        // * The value written specifies a Secure SPI, the value is
969        // written by a Non-secure access, and the value of the
970        // corresponding GICD_NSACR<n> register is less than 0b10.
971        const uint32_t intid = bits(data, 9, 0);
972        if (isNotSPI(intid) || !irqPending[intid] ||
973            (nsAccessToSecInt(intid, is_secure_access) &&
974             irqNsacr[intid] < 2)) {
975            return;
976        } else {
977            // Valid SPI, clear interrupt pending
978            deassertSPI(intid);
979        }
980        break;
981      }
982
983      case GICD_SETSPI_SR: {
984        // Writes to this register have no effect if:
985        // * GICD_CTLR.DS = 1 (WI)
986        // * The value written specifies an invalid SPI.
987        // * The SPI is already pending.
988        // * The value is written by a Non-secure access.
989        const uint32_t intid = bits(data, 9, 0);
990        if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) {
991            return;
992        } else {
993            // Valid SPI, set interrupt pending
994            sendInt(intid);
995        }
996        break;
997      }
998
999      case GICD_CLRSPI_SR: {
1000        // Writes to this register have no effect if:
1001        // * GICD_CTLR.DS = 1 (WI)
1002        // * The value written specifies an invalid SPI.
1003        // * The SPI is not pending.
1004        // * The value is written by a Non-secure access.
1005        const uint32_t intid = bits(data, 9, 0);
1006        if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) {
1007            return;
1008        } else {
1009            // Valid SPI, clear interrupt pending
1010            deassertSPI(intid);
1011        }
1012        break;
1013      }
1014
1015      default:
1016        panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
1017        break;
1018    }
1019}
1020
1021void
1022Gicv3Distributor::sendInt(uint32_t int_id)
1023{
1024    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1025    panic_if(int_id > itLines, "Invalid SPI!");
1026    irqPending[int_id] = true;
1027    DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
1028            "int_id %d (SPI) pending bit set\n", int_id);
1029    update();
1030}
1031
1032void
1033Gicv3Distributor::deassertSPI(uint32_t int_id)
1034{
1035    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1036    panic_if(int_id > itLines, "Invalid SPI!");
1037    irqPending[int_id] = false;
1038    clearIrqCpuInterface(int_id);
1039
1040    update();
1041}
1042
1043Gicv3CPUInterface*
1044Gicv3Distributor::route(uint32_t int_id)
1045{
1046    IROUTER affinity_routing = irqAffinityRouting[int_id];
1047    Gicv3Redistributor * target_redistributor = nullptr;
1048
1049    const Gicv3::GroupId int_group = getIntGroup(int_id);
1050
1051    if (affinity_routing.IRM) {
1052        // Interrupts routed to any PE defined as a participating node
1053        for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1054            Gicv3Redistributor * redistributor_i =
1055                gic->getRedistributor(i);
1056
1057            if (redistributor_i->
1058                    canBeSelectedFor1toNInterrupt(int_group)) {
1059                target_redistributor = redistributor_i;
1060                break;
1061            }
1062        }
1063    } else {
1064        uint32_t affinity = (affinity_routing.Aff3 << 24) |
1065                            (affinity_routing.Aff2 << 16) |
1066                            (affinity_routing.Aff1 << 8) |
1067                            (affinity_routing.Aff0 << 0);
1068        target_redistributor =
1069            gic->getRedistributorByAffinity(affinity);
1070    }
1071
1072    if (!target_redistributor) {
1073        // Interrrupts targeting not present cpus must remain pending
1074        return nullptr;
1075    } else {
1076        return target_redistributor->getCPUInterface();
1077    }
1078}
1079
1080void
1081Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id)
1082{
1083    auto cpu_interface = route(int_id);
1084    if (cpu_interface)
1085        cpu_interface->hppi.prio = 0xff;
1086}
1087
1088void
1089Gicv3Distributor::update()
1090{
1091    // Find the highest priority pending SPI
1092    for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
1093         int_id++) {
1094        Gicv3::GroupId int_group = getIntGroup(int_id);
1095        bool group_enabled = groupEnabled(int_group);
1096
1097        if (irqPending[int_id] && irqEnabled[int_id] &&
1098            !irqActive[int_id] && group_enabled) {
1099
1100            // Find the cpu interface where to route the interrupt
1101            Gicv3CPUInterface *target_cpu_interface = route(int_id);
1102
1103            // Invalid routing
1104            if (!target_cpu_interface) continue;
1105
1106            if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
1107                (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
1108                int_id < target_cpu_interface->hppi.intid)) {
1109
1110                target_cpu_interface->hppi.intid = int_id;
1111                target_cpu_interface->hppi.prio = irqPriority[int_id];
1112                target_cpu_interface->hppi.group = int_group;
1113            }
1114        }
1115    }
1116
1117    // Update all redistributors
1118    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1119        gic->getRedistributor(i)->update();
1120    }
1121}
1122
1123Gicv3::IntStatus
1124Gicv3Distributor::intStatus(uint32_t int_id) const
1125{
1126    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1127    panic_if(int_id > itLines, "Invalid SPI!");
1128
1129    if (irqPending[int_id]) {
1130        if (irqActive[int_id]) {
1131            return Gicv3::INT_ACTIVE_PENDING;
1132        }
1133
1134        return Gicv3::INT_PENDING;
1135    } else if (irqActive[int_id]) {
1136        return Gicv3::INT_ACTIVE;
1137    } else {
1138        return Gicv3::INT_INACTIVE;
1139    }
1140}
1141
1142Gicv3::GroupId
1143Gicv3Distributor::getIntGroup(int int_id) const
1144{
1145    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1146    panic_if(int_id > itLines, "Invalid SPI!");
1147
1148    if (DS) {
1149        if (irqGroup[int_id] == 1) {
1150            return Gicv3::G1NS;
1151        } else {
1152            return Gicv3::G0S;
1153        }
1154    } else {
1155        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
1156            return Gicv3::G0S;
1157        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
1158            return Gicv3::G1NS;
1159        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
1160            return Gicv3::G1S;
1161        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
1162            return Gicv3::G1NS;
1163        }
1164    }
1165
1166    M5_UNREACHABLE;
1167}
1168
1169void
1170Gicv3Distributor::activateIRQ(uint32_t int_id)
1171{
1172    irqPending[int_id] = false;
1173    irqActive[int_id] = true;
1174}
1175
1176void
1177Gicv3Distributor::deactivateIRQ(uint32_t int_id)
1178{
1179    irqActive[int_id] = false;
1180}
1181
1182void
1183Gicv3Distributor::serialize(CheckpointOut & cp) const
1184{
1185    SERIALIZE_SCALAR(ARE);
1186    SERIALIZE_SCALAR(DS);
1187    SERIALIZE_SCALAR(EnableGrp1S);
1188    SERIALIZE_SCALAR(EnableGrp1NS);
1189    SERIALIZE_SCALAR(EnableGrp0);
1190    SERIALIZE_CONTAINER(irqGroup);
1191    SERIALIZE_CONTAINER(irqEnabled);
1192    SERIALIZE_CONTAINER(irqPending);
1193    SERIALIZE_CONTAINER(irqActive);
1194    SERIALIZE_CONTAINER(irqPriority);
1195    SERIALIZE_CONTAINER(irqConfig);
1196    SERIALIZE_CONTAINER(irqGrpmod);
1197    SERIALIZE_CONTAINER(irqNsacr);
1198    SERIALIZE_CONTAINER(irqAffinityRouting);
1199}
1200
1201void
1202Gicv3Distributor::unserialize(CheckpointIn & cp)
1203{
1204    UNSERIALIZE_SCALAR(ARE);
1205    UNSERIALIZE_SCALAR(DS);
1206    UNSERIALIZE_SCALAR(EnableGrp1S);
1207    UNSERIALIZE_SCALAR(EnableGrp1NS);
1208    UNSERIALIZE_SCALAR(EnableGrp0);
1209    UNSERIALIZE_CONTAINER(irqGroup);
1210    UNSERIALIZE_CONTAINER(irqEnabled);
1211    UNSERIALIZE_CONTAINER(irqPending);
1212    UNSERIALIZE_CONTAINER(irqActive);
1213    UNSERIALIZE_CONTAINER(irqPriority);
1214    UNSERIALIZE_CONTAINER(irqConfig);
1215    UNSERIALIZE_CONTAINER(irqGrpmod);
1216    UNSERIALIZE_CONTAINER(irqNsacr);
1217    UNSERIALIZE_CONTAINER(irqAffinityRouting);
1218}
1219