gic_v3_redistributor.cc revision 13531:e6f1bf55d038
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
38const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
39        SGI_base + 0x041f);
40
41Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
42    : gic(gic),
43      distributor(nullptr),
44      cpuInterface(nullptr),
45      cpuId(cpu_id),
46      irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
47      irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
48      irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
49      irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
50      irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
51      irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
52      irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
53      irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX)
54{
55}
56
57Gicv3Redistributor::~Gicv3Redistributor()
58{
59}
60
61void
62Gicv3Redistributor::init()
63{
64    distributor = gic->getDistributor();
65    cpuInterface = gic->getCPUInterface(cpuId);
66}
67
68void
69Gicv3Redistributor::initState()
70{
71    reset();
72}
73
74void
75Gicv3Redistributor::reset()
76{
77    peInLowPowerState = true;
78    std::fill(irqGroup.begin(), irqGroup.end(), 0);
79    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
80    std::fill(irqPending.begin(), irqPending.end(), false);
81    std::fill(irqActive.begin(), irqActive.end(), false);
82    std::fill(irqPriority.begin(), irqPriority.end(), 0);
83
84    // SGIs have edge-triggered behavior
85    for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
86        irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
87    }
88
89    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
90    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
91    DPG1S = false;
92    DPG1NS = false;
93    DPG0 = false;
94}
95
96uint64_t
97Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
98{
99    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
100        uint64_t value = 0;
101        int first_intid = addr - GICR_IPRIORITYR.start();
102
103        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
104            uint8_t prio = irqPriority[int_id];
105
106            if (!distributor->DS && !is_secure_access) {
107                if (getIntGroup(int_id) != Gicv3::G1NS) {
108                    // RAZ/WI for non-secure accesses for secure interrupts
109                    continue;
110                } else {
111                    // NS view
112                    prio = (prio << 1) & 0xff;
113                }
114            }
115
116            value |= prio << (i * 8);
117        }
118
119        return value;
120    }
121
122    switch (addr) {
123      case GICR_CTLR: { // Control Register
124          uint64_t value = 0;
125
126          if (DPG1S) {
127              value |= GICR_CTLR_DPG1S;
128          }
129
130          if (DPG1NS) {
131              value |= GICR_CTLR_DPG1NS;
132          }
133
134          if (DPG0) {
135              value |= GICR_CTLR_DPG0;
136          }
137
138          return value;
139      }
140
141      case GICR_IIDR: // Implementer Identification Register
142        //return 0x43b; // r0p0 GIC-500
143        return 0;
144
145      case GICR_TYPER: { // Type Register
146          /*
147           * Affinity_Value   [63:32] == X
148           * (The identity of the PE associated with this Redistributor)
149           * CommonLPIAff     [25:24] == 01
150           * (All Redistributors with the same Aff3 value must share an
151           * LPI Configuration table)
152           * Processor_Number [23:8]  == X
153           * (A unique identifier for the PE)
154           * DPGS             [5]     == 1
155           * (GICR_CTLR.DPG* bits are supported)
156           * Last             [4]     == X
157           * (This Redistributor is the highest-numbered Redistributor in
158           * a series of contiguous Redistributor pages)
159           * DirectLPI        [3]     == 0
160           * (direct injection of LPIs not supported)
161           * VLPIS            [1]     == 0
162           * (virtual LPIs not supported)
163           * PLPIS            [0]     == 0
164           * (physical LPIs not supported)
165           */
166          uint64_t affinity = getAffinity();
167          int last = cpuId == (gic->getSystem()->numContexts() - 1);
168          return (affinity << 32) | (1 << 24) | (cpuId << 8) |
169              (1 << 5) | (last << 4);
170      }
171
172      case GICR_WAKER: // Wake Register
173        if (!distributor->DS && !is_secure_access) {
174            // RAZ/WI for non-secure accesses
175            return 0;
176        }
177
178        if (peInLowPowerState) {
179            return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
180        } else {
181            return 0;
182        }
183
184      case GICR_PIDR0: { // Peripheral ID0 Register
185          uint8_t part_0 = 0x92; // Part number, bits[7:0]
186          return part_0;
187      }
188
189      case GICR_PIDR1: { // Peripheral ID1 Register
190          uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
191          uint8_t part_1 = 0x4; // Part number, bits[11:8]
192          return (des_0 << 4) | (part_1 << 0);
193      }
194
195      case GICR_PIDR2: { // Peripheral ID2 Register
196          uint8_t arch_rev = 0x3; // 0x3 GICv3
197          uint8_t jedec = 0x1; // JEP code
198          uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
199          return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
200      }
201
202      case GICR_PIDR3: // Peripheral ID3 Register
203        return 0x0; // Implementation defined
204
205      case GICR_PIDR4: { // Peripheral ID4 Register
206          uint8_t size = 0x4; // 64 KB software visible page
207          uint8_t des_2 = 0x4; // ARM implementation
208          return (size << 4) | (des_2 << 0);
209      }
210
211      case GICR_PIDR5: // Peripheral ID5 Register
212      case GICR_PIDR6: // Peripheral ID6 Register
213      case GICR_PIDR7: // Peripheral ID7 Register
214        return 0; // RES0
215
216      case GICR_IGROUPR0: { // Interrupt Group Register 0
217          uint64_t value = 0;
218
219          if (!distributor->DS && !is_secure_access) {
220              // RAZ/WI for non-secure accesses
221              return 0;
222          }
223
224          for (int int_id = 0; int_id < 8 * size; int_id++) {
225              value |= (irqGroup[int_id] << int_id);
226          }
227
228          return value;
229      }
230
231      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
232      case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
233          uint64_t value = 0;
234
235          for (int int_id = 0; int_id < 8 * size; int_id++) {
236              if (!distributor->DS && !is_secure_access) {
237                  // RAZ/WI for non-secure accesses for secure interrupts
238                  if (getIntGroup(int_id) != Gicv3::G1NS) {
239                      continue;
240                  }
241              }
242
243              if (irqEnabled[int_id]) {
244                  value |= (1 << int_id);
245              }
246          }
247
248          return value;
249      }
250
251      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
252      case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
253          uint64_t value = 0;
254
255          for (int int_id = 0; int_id < 8 * size; int_id++) {
256              if (!distributor->DS && !is_secure_access) {
257                  // RAZ/WI for non-secure accesses for secure interrupts
258                  if (getIntGroup(int_id) != Gicv3::G1NS) {
259                      continue;
260                  }
261              }
262
263              value |= (irqPending[int_id] << int_id);
264          }
265
266          return value;
267      }
268
269      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
270      case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
271          uint64_t value = 0;
272
273          for (int int_id = 0; int_id < 8 * size; int_id++) {
274              if (!distributor->DS && !is_secure_access) {
275                  // RAZ/WI for non-secure accesses for secure interrupts
276                  if (getIntGroup(int_id) != Gicv3::G1NS) {
277                      continue;
278                  }
279              }
280
281              value |=  irqActive[int_id] << int_id;
282          }
283
284          return value;
285      }
286
287      case GICR_ICFGR0: // SGI Configuration Register
288      case GICR_ICFGR1: { // PPI Configuration Register
289          uint64_t value = 0;
290          uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
291
292          for (int i = 0, int_id = first_int_id; i < 32;
293                  i = i + 2, int_id++) {
294              if (!distributor->DS && !is_secure_access) {
295                  // RAZ/WI for non-secure accesses for secure interrupts
296                  if (getIntGroup(int_id) != Gicv3::G1NS) {
297                      continue;
298                  }
299              }
300
301              if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
302                  value |= (0x2) << i;
303              }
304          }
305
306          return value;
307      }
308
309      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
310          uint64_t value = 0;
311
312          if (distributor->DS) {
313              value = 0;
314          } else {
315              if (!is_secure_access) {
316                  // RAZ/WI for non-secure accesses
317                  value = 0;
318              } else {
319                  for (int int_id = 0; int_id < 8 * size; int_id++) {
320                      value |= irqGrpmod[int_id] << int_id;
321                  }
322              }
323          }
324
325          return value;
326      }
327
328      case GICR_NSACR: { // Non-secure Access Control Register
329          uint64_t value = 0;
330
331          if (distributor->DS) {
332              // RAZ/WI
333              value = 0;
334          } else {
335              if (!is_secure_access) {
336                  // RAZ/WI
337                  value = 0;
338              } else {
339                  for (int i = 0, int_id = 0; i < 8 * size;
340                          i = i + 2, int_id++) {
341                      value |= irqNsacr[int_id] << i;
342                  }
343              }
344          }
345
346          return value;
347      }
348
349      default:
350        panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
351        break;
352    }
353}
354
355void
356Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
357                          bool is_secure_access)
358{
359    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
360        int first_intid = addr - GICR_IPRIORITYR.start();
361
362        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
363            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
364
365            if (!distributor->DS && !is_secure_access) {
366                if (getIntGroup(int_id) != Gicv3::G1NS) {
367                    // RAZ/WI for non-secure accesses for secure interrupts
368                    continue;
369                } else {
370                    // NS view
371                    prio = 0x80 | (prio >> 1);
372                }
373            }
374
375            irqPriority[int_id] = prio;
376            DPRINTF(GIC, "Gicv3Redistributor::write(): "
377                    "int_id %d priority %d\n", int_id, irqPriority[int_id]);
378        }
379
380        return;
381    }
382
383    switch (addr) {
384      case GICR_CTLR: {
385          // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
386          DPG1S = data & GICR_CTLR_DPG1S;
387          DPG1NS = data & GICR_CTLR_DPG1NS;
388          DPG0 = data & GICR_CTLR_DPG0;
389          break;
390      }
391
392      case GICR_WAKER: // Wake Register
393        if (!distributor->DS && !is_secure_access) {
394            // RAZ/WI for non-secure accesses
395            return;
396        }
397
398        if (not peInLowPowerState and
399                (data & GICR_WAKER_ProcessorSleep)) {
400            DPRINTF(GIC, "Gicv3Redistributor::write(): "
401                    "PE entering in low power state\n");
402        } else if (peInLowPowerState and
403                not(data & GICR_WAKER_ProcessorSleep)) {
404            DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
405        }
406
407        peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
408        break;
409
410      case GICR_IGROUPR0: // Interrupt Group Register 0
411        if (!distributor->DS && !is_secure_access) {
412            // RAZ/WI for non-secure accesses
413            return;
414        }
415
416        for (int int_id = 0; int_id < 8 * size; int_id++) {
417            irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
418            DPRINTF(GIC, "Gicv3Redistributor::write(): "
419                    "int_id %d group %d\n", int_id, irqGroup[int_id]);
420        }
421
422        break;
423
424      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
425        for (int int_id = 0; int_id < 8 * size; int_id++) {
426            if (!distributor->DS && !is_secure_access) {
427                // RAZ/WI for non-secure accesses for secure interrupts
428                if (getIntGroup(int_id) != Gicv3::G1NS) {
429                    continue;
430                }
431            }
432
433            bool enable = data & (1 << int_id) ? 1 : 0;
434
435            if (enable) {
436                irqEnabled[int_id] = true;
437            }
438
439            DPRINTF(GIC, "Gicv3Redistributor::write(): "
440                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
441        }
442
443        break;
444
445      case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
446        for (int int_id = 0; int_id < 8 * size; int_id++) {
447            if (!distributor->DS && !is_secure_access) {
448                // RAZ/WI for non-secure accesses for secure interrupts
449                if (getIntGroup(int_id) != Gicv3::G1NS) {
450                    continue;
451                }
452            }
453
454            bool disable = data & (1 << int_id) ? 1 : 0;
455
456            if (disable) {
457                irqEnabled[int_id] = false;
458            }
459
460            DPRINTF(GIC, "Gicv3Redistributor::write(): "
461                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
462        }
463
464        break;
465
466      case GICR_ISPENDR0: // Interrupt Set-Pending 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 pending = data & (1 << int_id) ? 1 : 0;
476
477            if (pending) {
478                DPRINTF(GIC, "Gicv3Redistributor::write() "
479                        "(GICR_ISPENDR0): int_id %d (PPI) "
480                        "pending bit set\n", int_id);
481                irqPending[int_id] = true;
482            }
483        }
484
485        updateAndInformCPUInterface();
486        break;
487
488      case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
489        for (int int_id = 0; int_id < 8 * size; int_id++) {
490            if (!distributor->DS && !is_secure_access) {
491                // RAZ/WI for non-secure accesses for secure interrupts
492                if (getIntGroup(int_id) != Gicv3::G1NS) {
493                    continue;
494                }
495            }
496
497            bool clear = data & (1 << int_id) ? 1 : 0;
498
499            if (clear) {
500                irqPending[int_id] = false;
501            }
502        }
503
504        break;
505
506      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
507        for (int int_id = 0; int_id < 8 * size; int_id++) {
508            if (!distributor->DS && !is_secure_access) {
509                // RAZ/WI for non-secure accesses for secure interrupts
510                if (getIntGroup(int_id) != Gicv3::G1NS) {
511                    continue;
512                }
513            }
514
515            bool activate = data & (1 << int_id) ? 1 : 0;
516
517            if (activate) {
518                if (!irqActive[int_id]) {
519                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
520                            "int_id %d active set\n", int_id);
521                }
522
523                irqActive[int_id] = true;
524            }
525        }
526
527        break;
528
529      case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
530        for (int int_id = 0; int_id < 8 * size; int_id++) {
531            if (!distributor->DS && !is_secure_access) {
532                // RAZ/WI for non-secure accesses for secure interrupts
533                if (getIntGroup(int_id) != Gicv3::G1NS) {
534                    continue;
535                }
536            }
537
538            bool clear = data & (1 << int_id) ? 1 : 0;
539
540            if (clear) {
541                if (irqActive[int_id]) {
542                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
543                            "int_id %d active cleared\n", int_id);
544                }
545
546                irqActive[int_id] = false;
547            }
548        }
549
550        break;
551
552      case GICR_ICFGR1: { // PPI Configuration Register
553          int first_intid = Gicv3::SGI_MAX;
554
555          for (int i = 0, int_id = first_intid; i < 8 * size;
556                  i = i + 2, int_id++) {
557              if (!distributor->DS && !is_secure_access) {
558                  // RAZ/WI for non-secure accesses for secure interrupts
559                  if (getIntGroup(int_id) != Gicv3::G1NS) {
560                      continue;
561                  }
562              }
563
564              irqConfig[int_id] = data & (0x2 << i)
565                  ? Gicv3::INT_EDGE_TRIGGERED :
566                  Gicv3::INT_LEVEL_SENSITIVE;
567              DPRINTF(GIC, "Gicv3Redistributor::write(): "
568                      "int_id %d (PPI) config %d\n",
569                      int_id, irqConfig[int_id]);
570          }
571
572          break;
573      }
574
575      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
576          if (distributor->DS) {
577              // RAZ/WI if secutiry disabled
578          } else {
579              for (int int_id = 0; int_id < 8 * size; int_id++) {
580                  if (!is_secure_access) {
581                      // RAZ/WI for non-secure accesses
582                      continue;
583                  }
584
585                  irqGrpmod[int_id] = data & (1 << int_id);
586              }
587          }
588
589          break;
590      }
591
592      case GICR_NSACR: { // Non-secure Access Control Register
593          if (distributor->DS) {
594              // RAZ/WI
595          } else {
596              if (!is_secure_access) {
597                  // RAZ/WI
598              } else {
599                  for (int i = 0, int_id = 0; i < 8 * size;
600                          i = i + 2, int_id++) {
601                      irqNsacr[int_id] = (data >> i) & 0x3;
602                  }
603              }
604          }
605
606          break;
607      }
608
609      default:
610        panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
611        break;
612    }
613}
614
615void
616Gicv3Redistributor::sendPPInt(uint32_t int_id)
617{
618    assert((int_id >= Gicv3::SGI_MAX) &&
619           (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
620    irqPending[int_id] = true;
621    DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
622            "int_id %d (PPI) pending bit set\n", int_id);
623    updateAndInformCPUInterface();
624}
625
626void
627Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
628{
629    assert(int_id < Gicv3::SGI_MAX);
630    Gicv3::GroupId int_group = getIntGroup(int_id);
631
632    // asked for secure group 1
633    // configured as group 0
634    // send group 0
635    if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
636        group = Gicv3::G0S;
637    }
638
639    if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
640        return;
641    }
642
643    if (ns && distributor->DS == 0) {
644        int nsaccess = irqNsacr[int_id];
645
646        if ((int_group == Gicv3::G0S && nsaccess < 1) ||
647                (int_group == Gicv3::G1S && nsaccess < 2)) {
648            return;
649        }
650    }
651
652    irqPending[int_id] = true;
653    DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
654            "int_id %d (SGI) pending bit set\n", int_id);
655    updateAndInformCPUInterface();
656}
657
658Gicv3::IntStatus
659Gicv3Redistributor::intStatus(uint32_t int_id)
660{
661    assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
662
663    if (irqPending[int_id]) {
664        if (irqActive[int_id]) {
665            return Gicv3::INT_ACTIVE_PENDING;
666        }
667
668        return Gicv3::INT_PENDING;
669    } else if (irqActive[int_id]) {
670        return Gicv3::INT_ACTIVE;
671    } else {
672        return Gicv3::INT_INACTIVE;
673    }
674}
675
676/*
677 * Recalculate the highest priority pending interrupt after a
678 * change to redistributor state.
679 */
680void
681Gicv3Redistributor::update()
682{
683    bool new_hppi = false;
684
685    for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
686        Gicv3::GroupId int_group = getIntGroup(int_id);
687        bool group_enabled = distributor->groupEnabled(int_group);
688
689        if (irqPending[int_id] && irqEnabled[int_id] &&
690                !irqActive[int_id] && group_enabled) {
691            if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
692                    /*
693                     * Multiple pending ints with same priority.
694                     * Implementation choice which one to signal.
695                     * Our implementation selects the one with the lower id.
696                     */
697                    (irqPriority[int_id] == cpuInterface->hppi.prio &&
698                     int_id < cpuInterface->hppi.intid)) {
699                cpuInterface->hppi.intid = int_id;
700                cpuInterface->hppi.prio = irqPriority[int_id];
701                cpuInterface->hppi.group = int_group;
702                new_hppi = true;
703            }
704        }
705    }
706
707    if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
708            cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
709        distributor->fullUpdate();
710    }
711}
712
713void
714Gicv3Redistributor::updateAndInformCPUInterface()
715{
716    update();
717    cpuInterface->update();
718}
719
720Gicv3::GroupId
721Gicv3Redistributor::getIntGroup(int int_id)
722{
723    assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
724
725    if (distributor->DS) {
726        if (irqGroup[int_id] == 0) {
727            return Gicv3::G0S;
728        } else {
729            return Gicv3::G1NS;
730        }
731    } else {
732        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
733            return Gicv3::G0S;
734        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
735            return Gicv3::G1NS;
736        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
737            return Gicv3::G1S;
738        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
739            return Gicv3::G1NS;
740        }
741    }
742
743    M5_UNREACHABLE;
744}
745
746void
747Gicv3Redistributor::activateIRQ(uint32_t int_id)
748{
749    irqPending[int_id] = false;
750    irqActive[int_id] = true;
751}
752
753void
754Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
755{
756    irqActive[int_id] = false;
757}
758
759uint32_t
760Gicv3Redistributor::getAffinity()
761{
762    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
763    uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
764    /*
765     * Aff3 = MPIDR[39:32]
766     * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
767     * Aff2 = MPIDR[23:16]
768     * Aff1 = MPIDR[15:8]
769     * Aff0 = MPIDR[7:0]
770     * affinity = Aff3.Aff2.Aff1.Aff0
771     */
772    uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
773    return affinity;
774}
775
776bool
777Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
778{
779    if (peInLowPowerState) {
780        return false;
781    }
782
783    if (!distributor->groupEnabled(group)) {
784        return false;
785    }
786
787    if ((group == Gicv3::G1S) && DPG1S) {
788        return false;
789    }
790
791    if ((group == Gicv3::G1NS) && DPG1NS) {
792        return false;
793    }
794
795    if ((group == Gicv3::G0S) && DPG0) {
796        return false;
797    }
798
799    return true;
800}
801
802void
803Gicv3Redistributor::serialize(CheckpointOut & cp) const
804{
805    SERIALIZE_SCALAR(peInLowPowerState);
806    SERIALIZE_CONTAINER(irqGroup);
807    SERIALIZE_CONTAINER(irqEnabled);
808    SERIALIZE_CONTAINER(irqPending);
809    SERIALIZE_CONTAINER(irqActive);
810    SERIALIZE_CONTAINER(irqPriority);
811    SERIALIZE_CONTAINER(irqConfig);
812    SERIALIZE_CONTAINER(irqGrpmod);
813    SERIALIZE_CONTAINER(irqNsacr);
814    SERIALIZE_SCALAR(DPG1S);
815    SERIALIZE_SCALAR(DPG1NS);
816    SERIALIZE_SCALAR(DPG0);
817}
818
819void
820Gicv3Redistributor::unserialize(CheckpointIn & cp)
821{
822    UNSERIALIZE_SCALAR(peInLowPowerState);
823    UNSERIALIZE_CONTAINER(irqGroup);
824    UNSERIALIZE_CONTAINER(irqEnabled);
825    UNSERIALIZE_CONTAINER(irqPending);
826    UNSERIALIZE_CONTAINER(irqActive);
827    UNSERIALIZE_CONTAINER(irqPriority);
828    UNSERIALIZE_CONTAINER(irqConfig);
829    UNSERIALIZE_CONTAINER(irqGrpmod);
830    UNSERIALIZE_CONTAINER(irqNsacr);
831    UNSERIALIZE_SCALAR(DPG1S);
832    UNSERIALIZE_SCALAR(DPG1NS);
833    UNSERIALIZE_SCALAR(DPG0);
834}
835