gic_v3_redistributor.cc revision 13920
1/*
2 * Copyright (c) 2018 Metempsy Technology Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Jairo Balart
29 */
30
31#include "dev/arm/gic_v3_redistributor.hh"
32
33#include "arch/arm/utility.hh"
34#include "debug/GIC.hh"
35#include "dev/arm/gic_v3_cpu_interface.hh"
36#include "dev/arm/gic_v3_distributor.hh"
37#include "mem/fs_translating_port_proxy.hh"
38
39const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
40                                                    SGI_base + 0x041f);
41
42Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
43    : gic(gic),
44      distributor(nullptr),
45      cpuInterface(nullptr),
46      cpuId(cpu_id),
47      irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
48      irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
49      irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
50      irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
51      irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
52      irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
53      irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
54      irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
55      addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
56{
57}
58
59void
60Gicv3Redistributor::init()
61{
62    distributor = gic->getDistributor();
63    cpuInterface = gic->getCPUInterface(cpuId);
64}
65
66void
67Gicv3Redistributor::initState()
68{
69    reset();
70}
71
72void
73Gicv3Redistributor::reset()
74{
75    peInLowPowerState = true;
76    std::fill(irqGroup.begin(), irqGroup.end(), 0);
77    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
78    std::fill(irqPending.begin(), irqPending.end(), false);
79    std::fill(irqActive.begin(), irqActive.end(), false);
80    std::fill(irqPriority.begin(), irqPriority.end(), 0);
81
82    // SGIs have edge-triggered behavior
83    for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
84        irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
85    }
86
87    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
88    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
89    DPG1S = false;
90    DPG1NS = false;
91    DPG0 = false;
92    EnableLPIs = false;
93    lpiConfigurationTablePtr = 0;
94    lpiIDBits = 0;
95    lpiPendingTablePtr = 0;
96}
97
98uint64_t
99Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
100{
101    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
102        uint64_t value = 0;
103        int first_intid = addr - GICR_IPRIORITYR.start();
104
105        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
106            uint8_t prio = irqPriority[int_id];
107
108            if (!distributor->DS && !is_secure_access) {
109                if (getIntGroup(int_id) != Gicv3::G1NS) {
110                    // RAZ/WI for non-secure accesses for secure interrupts
111                    continue;
112                } else {
113                    // NS view
114                    prio = (prio << 1) & 0xff;
115                }
116            }
117
118            value |= prio << (i * 8);
119        }
120
121        return value;
122    }
123
124    switch (addr) {
125      case GICR_CTLR: { // Control Register
126          uint64_t value = 0;
127
128          if (DPG1S) {
129              value |= GICR_CTLR_DPG1S;
130          }
131
132          if (DPG1NS) {
133              value |= GICR_CTLR_DPG1NS;
134          }
135
136          if (DPG0) {
137              value |= GICR_CTLR_DPG0;
138          }
139
140          if (EnableLPIs) {
141              value |= GICR_CTLR_ENABLE_LPIS;
142          }
143
144          return value;
145      }
146
147      case GICR_IIDR: // Implementer Identification Register
148        //return 0x43b; // r0p0 GIC-500
149        return 0;
150
151      case GICR_TYPER: { // Type Register
152          /*
153           * Affinity_Value   [63:32] == X
154           * (The identity of the PE associated with this Redistributor)
155           * CommonLPIAff     [25:24] == 01
156           * (All Redistributors with the same Aff3 value must share an
157           * LPI Configuration table)
158           * Processor_Number [23:8]  == X
159           * (A unique identifier for the PE)
160           * DPGS             [5]     == 1
161           * (GICR_CTLR.DPG* bits are supported)
162           * Last             [4]     == X
163           * (This Redistributor is the highest-numbered Redistributor in
164           * a series of contiguous Redistributor pages)
165           * DirectLPI        [3]     == 1
166           * (direct injection of LPIs supported)
167           * VLPIS            [1]     == 0
168           * (virtual LPIs not supported)
169           * PLPIS            [0]     == 1
170           * (physical LPIs supported)
171           */
172          uint64_t affinity = getAffinity();
173          int last = cpuId == (gic->getSystem()->numContexts() - 1);
174          return (affinity << 32) | (1 << 24) | (cpuId << 8) |
175              (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
176      }
177
178      case GICR_WAKER: // Wake Register
179        if (!distributor->DS && !is_secure_access) {
180            // RAZ/WI for non-secure accesses
181            return 0;
182        }
183
184        if (peInLowPowerState) {
185            return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
186        } else {
187            return 0;
188        }
189
190      case GICR_PIDR0: { // Peripheral ID0 Register
191          return 0x92; // Part number, bits[7:0]
192      }
193
194      case GICR_PIDR1: { // Peripheral ID1 Register
195          uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
196          uint8_t part_1 = 0x4; // Part number, bits[11:8]
197          return (des_0 << 4) | (part_1 << 0);
198      }
199
200      case GICR_PIDR2: { // Peripheral ID2 Register
201          uint8_t arch_rev = 0x3; // 0x3 GICv3
202          uint8_t jedec = 0x1; // JEP code
203          uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
204          return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
205      }
206
207      case GICR_PIDR3: // Peripheral ID3 Register
208        return 0x0; // Implementation defined
209
210      case GICR_PIDR4: { // Peripheral ID4 Register
211          uint8_t size = 0x4; // 64 KB software visible page
212          uint8_t des_2 = 0x4; // ARM implementation
213          return (size << 4) | (des_2 << 0);
214      }
215
216      case GICR_PIDR5: // Peripheral ID5 Register
217      case GICR_PIDR6: // Peripheral ID6 Register
218      case GICR_PIDR7: // Peripheral ID7 Register
219        return 0; // RES0
220
221      case GICR_IGROUPR0: { // Interrupt Group Register 0
222          uint64_t value = 0;
223
224          if (!distributor->DS && !is_secure_access) {
225              // RAZ/WI for non-secure accesses
226              return 0;
227          }
228
229          for (int int_id = 0; int_id < 8 * size; int_id++) {
230              value |= (irqGroup[int_id] << int_id);
231          }
232
233          return value;
234      }
235
236      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
237      case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
238          uint64_t value = 0;
239
240          for (int int_id = 0; int_id < 8 * size; int_id++) {
241              if (!distributor->DS && !is_secure_access) {
242                  // RAZ/WI for non-secure accesses for secure interrupts
243                  if (getIntGroup(int_id) != Gicv3::G1NS) {
244                      continue;
245                  }
246              }
247
248              if (irqEnabled[int_id]) {
249                  value |= (1 << int_id);
250              }
251          }
252
253          return value;
254      }
255
256      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
257      case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
258          uint64_t value = 0;
259
260          for (int int_id = 0; int_id < 8 * size; int_id++) {
261              if (!distributor->DS && !is_secure_access) {
262                  // RAZ/WI for non-secure accesses for secure interrupts
263                  if (getIntGroup(int_id) != Gicv3::G1NS) {
264                      continue;
265                  }
266              }
267
268              value |= (irqPending[int_id] << int_id);
269          }
270
271          return value;
272      }
273
274      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
275      case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
276          uint64_t value = 0;
277
278          for (int int_id = 0; int_id < 8 * size; int_id++) {
279              if (!distributor->DS && !is_secure_access) {
280                  // RAZ/WI for non-secure accesses for secure interrupts
281                  if (getIntGroup(int_id) != Gicv3::G1NS) {
282                      continue;
283                  }
284              }
285
286              value |=  irqActive[int_id] << int_id;
287          }
288
289          return value;
290      }
291
292      case GICR_ICFGR0: // SGI Configuration Register
293      case GICR_ICFGR1: { // PPI Configuration Register
294          uint64_t value = 0;
295          uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
296
297          for (int i = 0, int_id = first_int_id; i < 32;
298               i = i + 2, int_id++) {
299              if (!distributor->DS && !is_secure_access) {
300                  // RAZ/WI for non-secure accesses for secure interrupts
301                  if (getIntGroup(int_id) != Gicv3::G1NS) {
302                      continue;
303                  }
304              }
305
306              if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
307                  value |= (0x2) << i;
308              }
309          }
310
311          return value;
312      }
313
314      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
315          uint64_t value = 0;
316
317          if (distributor->DS) {
318              value = 0;
319          } else {
320              if (!is_secure_access) {
321                  // RAZ/WI for non-secure accesses
322                  value = 0;
323              } else {
324                  for (int int_id = 0; int_id < 8 * size; int_id++) {
325                      value |= irqGrpmod[int_id] << int_id;
326                  }
327              }
328          }
329
330          return value;
331      }
332
333      case GICR_NSACR: { // Non-secure Access Control Register
334          uint64_t value = 0;
335
336          if (distributor->DS) {
337              // RAZ/WI
338              value = 0;
339          } else {
340              if (!is_secure_access) {
341                  // RAZ/WI
342                  value = 0;
343              } else {
344                  for (int i = 0, int_id = 0; i < 8 * size;
345                       i = i + 2, int_id++) {
346                      value |= irqNsacr[int_id] << i;
347                  }
348              }
349          }
350
351          return value;
352      }
353
354      case GICR_PROPBASER: // Redistributor Properties Base Address Register
355        // OuterCache, bits [58:56]
356        //   000 Memory type defined in InnerCache field
357        // Physical_Address, bits [51:12]
358        //   Bits [51:12] of the physical address containing the LPI
359        //   Configuration table
360        // Shareability, bits [11:10]
361        //   00 Non-shareable
362        // InnerCache, bits [9:7]
363        //   000 Device-nGnRnE
364        // IDbits, bits [4:0]
365        //   limited by GICD_TYPER.IDbits
366        return lpiConfigurationTablePtr | lpiIDBits;
367
368      // Redistributor LPI Pending Table Base Address Register
369      case GICR_PENDBASER:
370        // PTZ, bit [62]
371        //   Pending Table Zero
372        // OuterCache, bits [58:56]
373        //   000 Memory type defined in InnerCache field
374        // Physical_Address, bits [51:16]
375        //   Bits [51:16] of the physical address containing the LPI Pending
376        //   table
377        // Shareability, bits [11:10]
378        //   00 Non-shareable
379        // InnerCache, bits [9:7]
380        //   000 Device-nGnRnE
381        return lpiPendingTablePtr;
382
383      // Redistributor Synchronize Register
384      case GICR_SYNCR:
385        return 0;
386
387      default:
388        panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
389        break;
390    }
391}
392
393void
394Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
395                          bool is_secure_access)
396{
397    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
398        int first_intid = addr - GICR_IPRIORITYR.start();
399
400        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
401            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
402
403            if (!distributor->DS && !is_secure_access) {
404                if (getIntGroup(int_id) != Gicv3::G1NS) {
405                    // RAZ/WI for non-secure accesses for secure interrupts
406                    continue;
407                } else {
408                    // NS view
409                    prio = 0x80 | (prio >> 1);
410                }
411            }
412
413            irqPriority[int_id] = prio;
414            DPRINTF(GIC, "Gicv3Redistributor::write(): "
415                    "int_id %d priority %d\n", int_id, irqPriority[int_id]);
416        }
417
418        return;
419    }
420
421    switch (addr) {
422      case GICR_CTLR: {
423          // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
424          EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
425          DPG1S = data & GICR_CTLR_DPG1S;
426          DPG1NS = data & GICR_CTLR_DPG1NS;
427          DPG0 = data & GICR_CTLR_DPG0;
428          break;
429      }
430
431      case GICR_WAKER: // Wake Register
432        if (!distributor->DS && !is_secure_access) {
433            // RAZ/WI for non-secure accesses
434            return;
435        }
436
437        if (not peInLowPowerState and
438            (data & GICR_WAKER_ProcessorSleep)) {
439            DPRINTF(GIC, "Gicv3Redistributor::write(): "
440                    "PE entering in low power state\n");
441        } else if (peInLowPowerState and
442                   not(data & GICR_WAKER_ProcessorSleep)) {
443            DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
444        }
445
446        peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
447        break;
448
449      case GICR_IGROUPR0: // Interrupt Group Register 0
450        if (!distributor->DS && !is_secure_access) {
451            // RAZ/WI for non-secure accesses
452            return;
453        }
454
455        for (int int_id = 0; int_id < 8 * size; int_id++) {
456            irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
457            DPRINTF(GIC, "Gicv3Redistributor::write(): "
458                    "int_id %d group %d\n", int_id, irqGroup[int_id]);
459        }
460
461        break;
462
463      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
464        for (int int_id = 0; int_id < 8 * size; int_id++) {
465            if (!distributor->DS && !is_secure_access) {
466                // RAZ/WI for non-secure accesses for secure interrupts
467                if (getIntGroup(int_id) != Gicv3::G1NS) {
468                    continue;
469                }
470            }
471
472            bool enable = data & (1 << int_id) ? 1 : 0;
473
474            if (enable) {
475                irqEnabled[int_id] = true;
476            }
477
478            DPRINTF(GIC, "Gicv3Redistributor::write(): "
479                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
480        }
481
482        break;
483
484      case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
485        for (int int_id = 0; int_id < 8 * size; int_id++) {
486            if (!distributor->DS && !is_secure_access) {
487                // RAZ/WI for non-secure accesses for secure interrupts
488                if (getIntGroup(int_id) != Gicv3::G1NS) {
489                    continue;
490                }
491            }
492
493            bool disable = data & (1 << int_id) ? 1 : 0;
494
495            if (disable) {
496                irqEnabled[int_id] = false;
497            }
498
499            DPRINTF(GIC, "Gicv3Redistributor::write(): "
500                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
501        }
502
503        break;
504
505      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
506        for (int int_id = 0; int_id < 8 * size; int_id++) {
507            if (!distributor->DS && !is_secure_access) {
508                // RAZ/WI for non-secure accesses for secure interrupts
509                if (getIntGroup(int_id) != Gicv3::G1NS) {
510                    continue;
511                }
512            }
513
514            bool pending = data & (1 << int_id) ? 1 : 0;
515
516            if (pending) {
517                DPRINTF(GIC, "Gicv3Redistributor::write() "
518                        "(GICR_ISPENDR0): int_id %d (PPI) "
519                        "pending bit set\n", int_id);
520                irqPending[int_id] = true;
521            }
522        }
523
524        updateAndInformCPUInterface();
525        break;
526
527      case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
528        for (int int_id = 0; int_id < 8 * size; int_id++) {
529            if (!distributor->DS && !is_secure_access) {
530                // RAZ/WI for non-secure accesses for secure interrupts
531                if (getIntGroup(int_id) != Gicv3::G1NS) {
532                    continue;
533                }
534            }
535
536            bool clear = data & (1 << int_id) ? 1 : 0;
537
538            if (clear) {
539                irqPending[int_id] = false;
540            }
541        }
542
543        break;
544
545      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
546        for (int int_id = 0; int_id < 8 * size; int_id++) {
547            if (!distributor->DS && !is_secure_access) {
548                // RAZ/WI for non-secure accesses for secure interrupts
549                if (getIntGroup(int_id) != Gicv3::G1NS) {
550                    continue;
551                }
552            }
553
554            bool activate = data & (1 << int_id) ? 1 : 0;
555
556            if (activate) {
557                if (!irqActive[int_id]) {
558                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
559                            "int_id %d active set\n", int_id);
560                }
561
562                irqActive[int_id] = true;
563            }
564        }
565
566        break;
567
568      case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
569        for (int int_id = 0; int_id < 8 * size; int_id++) {
570            if (!distributor->DS && !is_secure_access) {
571                // RAZ/WI for non-secure accesses for secure interrupts
572                if (getIntGroup(int_id) != Gicv3::G1NS) {
573                    continue;
574                }
575            }
576
577            bool clear = data & (1 << int_id) ? 1 : 0;
578
579            if (clear) {
580                if (irqActive[int_id]) {
581                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
582                            "int_id %d active cleared\n", int_id);
583                }
584
585                irqActive[int_id] = false;
586            }
587        }
588
589        break;
590
591      case GICR_ICFGR1: { // PPI Configuration Register
592          int first_intid = Gicv3::SGI_MAX;
593
594          for (int i = 0, int_id = first_intid; i < 8 * size;
595               i = i + 2, int_id++) {
596              if (!distributor->DS && !is_secure_access) {
597                  // RAZ/WI for non-secure accesses for secure interrupts
598                  if (getIntGroup(int_id) != Gicv3::G1NS) {
599                      continue;
600                  }
601              }
602
603              irqConfig[int_id] = data & (0x2 << i) ?
604                                  Gicv3::INT_EDGE_TRIGGERED :
605                                  Gicv3::INT_LEVEL_SENSITIVE;
606              DPRINTF(GIC, "Gicv3Redistributor::write(): "
607                      "int_id %d (PPI) config %d\n",
608                      int_id, irqConfig[int_id]);
609          }
610
611          break;
612      }
613
614      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
615          if (distributor->DS) {
616              // RAZ/WI if secutiry disabled
617          } else {
618              for (int int_id = 0; int_id < 8 * size; int_id++) {
619                  if (!is_secure_access) {
620                      // RAZ/WI for non-secure accesses
621                      continue;
622                  }
623
624                  irqGrpmod[int_id] = data & (1 << int_id);
625              }
626          }
627
628          break;
629      }
630
631      case GICR_NSACR: { // Non-secure Access Control Register
632          if (distributor->DS) {
633              // RAZ/WI
634          } else {
635              if (!is_secure_access) {
636                  // RAZ/WI
637              } else {
638                  for (int i = 0, int_id = 0; i < 8 * size;
639                       i = i + 2, int_id++) {
640                      irqNsacr[int_id] = (data >> i) & 0x3;
641                  }
642              }
643          }
644
645          break;
646      }
647
648      case GICR_SETLPIR: // Set LPI Pending Register
649        setClrLPI(data, true);
650        break;
651
652      case GICR_CLRLPIR: // Clear LPI Pending Register
653        setClrLPI(data, false);
654        break;
655
656      case GICR_PROPBASER: { // Redistributor Properties Base Address Register
657          // OuterCache, bits [58:56]
658          //   000 Memory type defined in InnerCache field
659          // Physical_Address, bits [51:12]
660          //   Bits [51:12] of the physical address containing the LPI
661          //   Configuration table
662          // Shareability, bits [11:10]
663          //   00 Non-shareable
664          // InnerCache, bits [9:7]
665          //   000 Device-nGnRnE
666          // IDbits, bits [4:0]
667          //   limited by GICD_TYPER.IDbits (= 0xf)
668          lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
669          lpiIDBits = data & 0x1f;
670
671          // 0xf here matches the value of GICD_TYPER.IDbits.
672          // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
673          // value
674          if (lpiIDBits > 0xf) {
675              lpiIDBits = 0xf;
676          }
677
678          uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
679          uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
680          lpiConfigurationTable.resize(number_lpis);
681          break;
682      }
683
684      // Redistributor LPI Pending Table Base Address Register
685      case GICR_PENDBASER:
686        // PTZ, bit [62]
687        //   Pending Table Zero
688        // OuterCache, bits [58:56]
689        //   000 Memory type defined in InnerCache field
690        // Physical_Address, bits [51:16]
691        //   Bits [51:16] of the physical address containing the LPI Pending
692        //   table
693        // Shareability, bits [11:10]
694        //   00 Non-shareable
695        // InnerCache, bits [9:7]
696        //   000 Device-nGnRnE
697        lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
698        break;
699
700      case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
701          uint32_t lpi_id = data & 0xffffffff;
702          uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
703
704          if (lpi_id > largest_lpi_id) {
705              return;
706          }
707
708          uint32_t lpi_table_entry_index = lpi_id - SMALLEST_LPI_ID;
709          invalLpiConfig(lpi_table_entry_index);
710          break;
711      }
712
713      case GICR_INVALLR: { // Redistributor Invalidate All Register
714          for (int lpi_table_entry_index = 0;
715               lpi_table_entry_index < lpiConfigurationTable.size();
716               lpi_table_entry_index++) {
717              invalLpiConfig(lpi_table_entry_index);
718          }
719
720          break;
721      }
722
723      default:
724        panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
725        break;
726    }
727}
728
729void
730Gicv3Redistributor::invalLpiConfig(uint32_t lpi_entry_index)
731{
732    Addr lpi_table_entry_ptr = lpiConfigurationTablePtr +
733        lpi_entry_index * sizeof(LPIConfigurationTableEntry);
734    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
735    tc->getPhysProxy().readBlob(lpi_table_entry_ptr,
736            (uint8_t*) &lpiConfigurationTable[lpi_entry_index],
737            sizeof(LPIConfigurationTableEntry));
738}
739
740void
741Gicv3Redistributor::sendPPInt(uint32_t int_id)
742{
743    assert((int_id >= Gicv3::SGI_MAX) &&
744           (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
745    irqPending[int_id] = true;
746    DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
747            "int_id %d (PPI) pending bit set\n", int_id);
748    updateAndInformCPUInterface();
749}
750
751void
752Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
753{
754    assert(int_id < Gicv3::SGI_MAX);
755    Gicv3::GroupId int_group = getIntGroup(int_id);
756
757    // asked for secure group 1
758    // configured as group 0
759    // send group 0
760    if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
761        group = Gicv3::G0S;
762    }
763
764    if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
765        return;
766    }
767
768    if (ns && distributor->DS == 0) {
769        int nsaccess = irqNsacr[int_id];
770
771        if ((int_group == Gicv3::G0S && nsaccess < 1) ||
772            (int_group == Gicv3::G1S && nsaccess < 2)) {
773            return;
774        }
775    }
776
777    irqPending[int_id] = true;
778    DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
779            "int_id %d (SGI) pending bit set\n", int_id);
780    updateAndInformCPUInterface();
781}
782
783Gicv3::IntStatus
784Gicv3Redistributor::intStatus(uint32_t int_id) const
785{
786    assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
787
788    if (irqPending[int_id]) {
789        if (irqActive[int_id]) {
790            return Gicv3::INT_ACTIVE_PENDING;
791        }
792
793        return Gicv3::INT_PENDING;
794    } else if (irqActive[int_id]) {
795        return Gicv3::INT_ACTIVE;
796    } else {
797        return Gicv3::INT_INACTIVE;
798    }
799}
800
801/*
802 * Recalculate the highest priority pending interrupt after a
803 * change to redistributor state.
804 */
805void
806Gicv3Redistributor::update()
807{
808    bool new_hppi = false;
809
810    for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
811        Gicv3::GroupId int_group = getIntGroup(int_id);
812        bool group_enabled = distributor->groupEnabled(int_group);
813
814        if (irqPending[int_id] && irqEnabled[int_id] &&
815                !irqActive[int_id] && group_enabled) {
816            if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
817                /*
818                 * Multiple pending ints with same priority.
819                 * Implementation choice which one to signal.
820                 * Our implementation selects the one with the lower id.
821                 */
822                (irqPriority[int_id] == cpuInterface->hppi.prio &&
823                 int_id < cpuInterface->hppi.intid)) {
824                cpuInterface->hppi.intid = int_id;
825                cpuInterface->hppi.prio = irqPriority[int_id];
826                cpuInterface->hppi.group = int_group;
827                new_hppi = true;
828            }
829        }
830    }
831
832    // Check LPIs
833    if (EnableLPIs) {
834        const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
835        char lpi_pending_table[largest_lpi_id / 8];
836        ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
837        tc->getPhysProxy().readBlob(lpiPendingTablePtr,
838                                    (uint8_t *) lpi_pending_table,
839                                    sizeof(lpi_pending_table));
840
841        for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
842             lpi_id++) {
843            uint32_t lpi_pending_entry_byte = lpi_id / 8;
844            uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
845            bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
846                                  1 << lpi_pending_entry_bit_position;
847            uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
848            bool lpi_is_enable =
849                lpiConfigurationTable[lpi_configuration_entry_index].enable;
850            // LPIs are always Non-secure Group 1 interrupts,
851            // in a system where two Security states are enabled.
852            Gicv3::GroupId lpi_group = Gicv3::G1NS;
853            bool group_enabled = distributor->groupEnabled(lpi_group);
854
855            if (lpi_is_pending && lpi_is_enable && group_enabled) {
856                uint8_t lpi_priority =
857                    lpiConfigurationTable[lpi_configuration_entry_index].priority;
858
859                if ((lpi_priority < cpuInterface->hppi.prio) ||
860                    (lpi_priority == cpuInterface->hppi.prio &&
861                     lpi_id < cpuInterface->hppi.intid)) {
862                    cpuInterface->hppi.intid = lpi_id;
863                    cpuInterface->hppi.prio = lpi_priority;
864                    cpuInterface->hppi.group = lpi_group;
865                    new_hppi = true;
866                }
867            }
868        }
869    }
870
871    if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
872        cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
873        distributor->fullUpdate();
874    }
875}
876
877void
878Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
879{
880    if (!EnableLPIs) {
881        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
882        // GICR_CTLR.EnableLPIs == 0.
883        return;
884    }
885
886    uint32_t lpi_id = data & 0xffffffff;
887    uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
888
889    if (lpi_id > largest_lpi_id) {
890        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
891        // pINTID value specifies an unimplemented LPI.
892        return;
893    }
894
895    Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
896    uint8_t lpi_pending_entry;
897    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
898    tc->getPhysProxy().readBlob(lpi_pending_entry_ptr,
899            (uint8_t*) &lpi_pending_entry,
900            sizeof(lpi_pending_entry));
901    uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
902    bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
903
904    if (set) {
905        if (is_set) {
906            // Writes to GICR_SETLPIR have not effect if the pINTID field
907            // corresponds to an LPI that is already pending.
908            return;
909        }
910
911        lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
912    } else {
913        if (!is_set) {
914            // Writes to GICR_SETLPIR have not effect if the pINTID field
915            // corresponds to an LPI that is not pending.
916            return;
917        }
918
919        lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
920    }
921
922    tc->getPhysProxy().writeBlob(lpi_pending_entry_ptr,
923            (uint8_t*) &lpi_pending_entry,
924            sizeof(lpi_pending_entry));
925    updateAndInformCPUInterface();
926}
927
928void
929Gicv3Redistributor::updateAndInformCPUInterface()
930{
931    update();
932    cpuInterface->update();
933}
934
935Gicv3::GroupId
936Gicv3Redistributor::getIntGroup(int int_id) const
937{
938    assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
939
940    if (distributor->DS) {
941        if (irqGroup[int_id] == 0) {
942            return Gicv3::G0S;
943        } else {
944            return Gicv3::G1NS;
945        }
946    } else {
947        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
948            return Gicv3::G0S;
949        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
950            return Gicv3::G1NS;
951        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
952            return Gicv3::G1S;
953        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
954            return Gicv3::G1NS;
955        }
956    }
957
958    M5_UNREACHABLE;
959}
960
961void
962Gicv3Redistributor::activateIRQ(uint32_t int_id)
963{
964    irqPending[int_id] = false;
965    irqActive[int_id] = true;
966}
967
968void
969Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
970{
971    irqActive[int_id] = false;
972}
973
974uint32_t
975Gicv3Redistributor::getAffinity() const
976{
977    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
978    uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
979    /*
980     * Aff3 = MPIDR[39:32]
981     * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
982     * Aff2 = MPIDR[23:16]
983     * Aff1 = MPIDR[15:8]
984     * Aff0 = MPIDR[7:0]
985     * affinity = Aff3.Aff2.Aff1.Aff0
986     */
987    uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
988    return affinity;
989}
990
991bool
992Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
993{
994    if (peInLowPowerState) {
995        return false;
996    }
997
998    if (!distributor->groupEnabled(group)) {
999        return false;
1000    }
1001
1002    if ((group == Gicv3::G1S) && DPG1S) {
1003        return false;
1004    }
1005
1006    if ((group == Gicv3::G1NS) && DPG1NS) {
1007        return false;
1008    }
1009
1010    if ((group == Gicv3::G0S) && DPG0) {
1011        return false;
1012    }
1013
1014    return true;
1015}
1016
1017void
1018Gicv3Redistributor::serialize(CheckpointOut & cp) const
1019{
1020    SERIALIZE_SCALAR(peInLowPowerState);
1021    SERIALIZE_CONTAINER(irqGroup);
1022    SERIALIZE_CONTAINER(irqEnabled);
1023    SERIALIZE_CONTAINER(irqPending);
1024    SERIALIZE_CONTAINER(irqActive);
1025    SERIALIZE_CONTAINER(irqPriority);
1026    SERIALIZE_CONTAINER(irqConfig);
1027    SERIALIZE_CONTAINER(irqGrpmod);
1028    SERIALIZE_CONTAINER(irqNsacr);
1029    SERIALIZE_SCALAR(DPG1S);
1030    SERIALIZE_SCALAR(DPG1NS);
1031    SERIALIZE_SCALAR(DPG0);
1032    SERIALIZE_SCALAR(EnableLPIs);
1033    SERIALIZE_SCALAR(lpiConfigurationTablePtr);
1034    SERIALIZE_SCALAR(lpiIDBits);
1035    SERIALIZE_SCALAR(lpiPendingTablePtr);
1036}
1037
1038void
1039Gicv3Redistributor::unserialize(CheckpointIn & cp)
1040{
1041    UNSERIALIZE_SCALAR(peInLowPowerState);
1042    UNSERIALIZE_CONTAINER(irqGroup);
1043    UNSERIALIZE_CONTAINER(irqEnabled);
1044    UNSERIALIZE_CONTAINER(irqPending);
1045    UNSERIALIZE_CONTAINER(irqActive);
1046    UNSERIALIZE_CONTAINER(irqPriority);
1047    UNSERIALIZE_CONTAINER(irqConfig);
1048    UNSERIALIZE_CONTAINER(irqGrpmod);
1049    UNSERIALIZE_CONTAINER(irqNsacr);
1050    UNSERIALIZE_SCALAR(DPG1S);
1051    UNSERIALIZE_SCALAR(DPG1NS);
1052    UNSERIALIZE_SCALAR(DPG0);
1053    UNSERIALIZE_SCALAR(EnableLPIs);
1054    UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
1055    UNSERIALIZE_SCALAR(lpiIDBits);
1056    UNSERIALIZE_SCALAR(lpiPendingTablePtr);
1057}
1058