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