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